mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-11 18:50:28 +09:00
Compare commits
47 Commits
b2abcf8534
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f13a8d7ced | ||
|
|
c0963b3417 | ||
|
|
50313883f3 | ||
|
|
7e02580dff | ||
|
|
3232d72812 | ||
|
|
60ad19c2c8 | ||
|
|
6a7f19ec34 | ||
|
|
12ccea8dd8 | ||
|
|
daa80818f8 | ||
|
|
a5eb30dbfd | ||
|
|
1b2a4f760b | ||
|
|
9be83584a5 | ||
|
|
417a095e67 | ||
|
|
a411de5ce8 | ||
|
|
90a5d8f473 | ||
|
|
20856f44c1 | ||
|
|
28d6d10ddc | ||
|
|
b3e13b7f0b | ||
|
|
5654c593df | ||
|
|
b90b7f2451 | ||
|
|
855a0853ad | ||
|
|
f0fdfd4f49 | ||
|
|
dc39902006 | ||
|
|
29dd7874cd | ||
|
|
8a134e03db | ||
|
|
39d931f7e5 | ||
|
|
b4f6d8b800 | ||
|
|
c78d2bb8fb | ||
|
|
5b0cee7c1b | ||
|
|
59ed66b684 | ||
|
|
ce0b616bc6 | ||
|
|
31ceec02fe | ||
|
|
a7cf4bb37b | ||
|
|
3dfaa70fcf | ||
|
|
76b14eaed7 | ||
|
|
8e8f091aba | ||
|
|
d75a54e206 | ||
|
|
efb7a7c4e0 | ||
|
|
7342e73d10 | ||
|
|
832f92e35f | ||
|
|
ea3464532e | ||
|
|
7e235f8748 | ||
|
|
052c8217b7 | ||
|
|
26b9ba5f8c | ||
|
|
1b3c061aae | ||
|
|
1525ea3dda | ||
|
|
a189c2ef4d |
90
CHANGELOG
90
CHANGELOG
@@ -1,6 +1,96 @@
|
|||||||
CHANGELOG
|
CHANGELOG
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
version 0.12.0 (released 2026-02-10)
|
||||||
|
* Deprecations and removals:
|
||||||
|
* Bumped minimal RSA key size to 1024 bits
|
||||||
|
* New functionality:
|
||||||
|
* Add support for hybrid key exchange mechanisms using Quantum Resistant
|
||||||
|
cryptography for all backends. These are now preferred:
|
||||||
|
* sntrup761x25519-sha512, sntrup761x25519-sha512@openssh.com
|
||||||
|
* mlkem768nistp256-sha256
|
||||||
|
* mlkem768x25519-sha256
|
||||||
|
* mlkem1024nistp384-sha384 (only OpenSSL 3.5+ and libgcrypt)
|
||||||
|
* New cmake option WITH_HERMETIC_USR
|
||||||
|
* Added support for Ed25519 keys through PKCS#11
|
||||||
|
* Support for host-bound public key authentication
|
||||||
|
(publickey-hostbound-v00@openssh.com)
|
||||||
|
* Use curve25519 implementation from mbedTLS and libgcrypt
|
||||||
|
* New functions for signing arbitrary data (commits) with SSH keys
|
||||||
|
* sshsig_sign()
|
||||||
|
* sshsig_verify()
|
||||||
|
* Support for FIDO/U2F keys (internal implementation using libfido2)
|
||||||
|
* Compatible with OpenSSH: should work out of the box
|
||||||
|
* Extensible with callbacks
|
||||||
|
* Add support for GSSAPI Key Exchange (RFC 4462, RFC 8732)
|
||||||
|
* Add support for new configuration options (client and server):
|
||||||
|
* RequiredRsaSize
|
||||||
|
* AddressFamily (client)
|
||||||
|
* GSSAPIKeyExchange
|
||||||
|
* GSSAPIKexAlgorithms
|
||||||
|
* New option to get list of configured identities (SSH_OPTIONS_NEXT_IDENTITY)
|
||||||
|
* More OpenSSH compatible percent expansion characters
|
||||||
|
* Add new server auth_kbdint_function() callback
|
||||||
|
* New PKI Context structure for key operations
|
||||||
|
* Stability and compatibility improvements of ProxyJump
|
||||||
|
* SFTP
|
||||||
|
* Prevent failures when SFTP status message does not contain error message
|
||||||
|
* Fix possible timeouts while waiting for SFTP messages
|
||||||
|
* Support for users-groups-by-id@openssh.com extension in client
|
||||||
|
* Support for SSH_FXF_TRUNC in server
|
||||||
|
|
||||||
|
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)
|
||||||
|
* Security:
|
||||||
|
* CVE-2025-4877 - Write beyond bounds in binary to base64 conversion
|
||||||
|
* CVE-2025-4878 - Use of uninitialized variable in privatekey_from_file()
|
||||||
|
* CVE-2025-5318 - Likely read beyond bounds in sftp server handle management
|
||||||
|
* CVE-2025-5351 - Double free in functions exporting keys
|
||||||
|
* CVE-2025-5372 - ssh_kdf() returns a success code on certain failures
|
||||||
|
* CVE-2025-5449 - Likely read beyond bounds in sftp server message decoding
|
||||||
|
* CVE-2025-5987 - Invalid return code for chacha20 poly1305 with OpenSSL
|
||||||
|
* Compatibility
|
||||||
|
* Fixed compatibility with CPM.cmake
|
||||||
|
* Compatibility with OpenSSH 10.0
|
||||||
|
* Tests compatibility with new Dropbear releases
|
||||||
|
* Removed p11-kit remoting from the pkcs11 testsuite
|
||||||
|
* Bugfixes
|
||||||
|
* Implement missing packet filter for DH GEX
|
||||||
|
* Properly process the SSH2_MSG_DEBUG message
|
||||||
|
* Allow escaping quotes in quoted arguments to ssh configuration
|
||||||
|
* Do not fail with unknown match keywords in ssh configuration
|
||||||
|
* Process packets before selecting signature algorithm during authentication
|
||||||
|
* Do not fail hard when the SFTP status message is not sent by noncompliant
|
||||||
|
servers
|
||||||
|
|
||||||
|
version 0.11.1 (released 2024-08-30)
|
||||||
|
* Fixed default TTY modes that are set when stdin is not connected to tty (#270)
|
||||||
|
* Fixed zlib cleanup procedure, which could crash on i386
|
||||||
|
* Various test fixes improving their stability
|
||||||
|
* Fixed cygwin build
|
||||||
|
|
||||||
version 0.11.0 (released 2024-07-31)
|
version 0.11.0 (released 2024-07-31)
|
||||||
* Deprecations and Removals:
|
* Deprecations and Removals:
|
||||||
* Dropped support for DSA
|
* Dropped support for DSA
|
||||||
|
|||||||
@@ -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.00 LANGUAGES C)
|
project(libssh VERSION 0.12.00 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.0")
|
set(LIBRARY_VERSION "4.11.0")
|
||||||
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
|
||||||
|
|||||||
@@ -12,21 +12,36 @@ 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(WITH_FIDO2 "Build with FIDO2/U2F support" OFF)
|
option(WITH_FIDO2 "Build with FIDO2/U2F support" 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)
|
||||||
option(WITH_HERMETIC_USR "Build with support for hermetic /usr/" OFF)
|
option(WITH_HERMETIC_USR "Build with support for hermetic /usr/" OFF)
|
||||||
|
|
||||||
@@ -39,11 +54,14 @@ endif (WITH_ZLIB)
|
|||||||
if (WITH_BENCHMARKS)
|
if (WITH_BENCHMARKS)
|
||||||
set(UNIT_TESTING ON)
|
set(UNIT_TESTING ON)
|
||||||
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 ()
|
||||||
|
|
||||||
if (WITH_NACL)
|
if (WITH_NACL)
|
||||||
set(WITH_NACL ON)
|
set(WITH_NACL ON)
|
||||||
@@ -53,18 +71,34 @@ 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 ()
|
||||||
|
if (WITH_HERMETIC_USR)
|
||||||
|
set(USR_GLOBAL_CONF_DIR "/usr${GLOBAL_CONF_DIR}")
|
||||||
|
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")
|
||||||
|
|
||||||
|
if (WITH_HERMETIC_USR)
|
||||||
|
set(USR_GLOBAL_BIND_CONFIG "/usr${GLOBAL_BIND_CONFIG}")
|
||||||
|
endif ()
|
||||||
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)
|
|
||||||
|
|
||||||
if (WITH_HERMETIC_USR)
|
if (WITH_HERMETIC_USR)
|
||||||
set(USR_GLOBAL_BIND_CONFIG "/usr${GLOBAL_BIND_CONFIG}")
|
|
||||||
set(USR_GLOBAL_CLIENT_CONFIG "/usr${GLOBAL_CLIENT_CONFIG}")
|
set(USR_GLOBAL_CLIENT_CONFIG "/usr${GLOBAL_CLIENT_CONFIG}")
|
||||||
endif (WITH_HERMETIC_USR)
|
endif ()
|
||||||
|
endif (NOT GLOBAL_CLIENT_CONFIG)
|
||||||
|
|
||||||
if (FUZZ_TESTING)
|
if (FUZZ_TESTING)
|
||||||
set(WITH_INSECURE_NONE ON)
|
set(WITH_INSECURE_NONE ON)
|
||||||
@@ -72,4 +106,4 @@ endif (FUZZ_TESTING)
|
|||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
set(WITH_EXEC 0)
|
set(WITH_EXEC 0)
|
||||||
endif(WIN32)
|
endif (WIN32)
|
||||||
|
|||||||
@@ -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 USR_GLOBAL_BIND_CONFIG "${USR_GLOBAL_BIND_CONFIG}"
|
#cmakedefine USR_GLOBAL_BIND_CONFIG "${USR_GLOBAL_BIND_CONFIG}"
|
||||||
#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) {
|
||||||
|
|||||||
@@ -171,21 +171,15 @@ The following RFC documents described SSH-2 protocol as an Internet standard.
|
|||||||
The Secure Shell (SSH) Session Channel Break Extension
|
The Secure Shell (SSH) Session Channel Break Extension
|
||||||
- <a href="https://tools.ietf.org/html/rfc4344" target="_blank">RFC 4344</a>,
|
- <a href="https://tools.ietf.org/html/rfc4344" target="_blank">RFC 4344</a>,
|
||||||
The Secure Shell (SSH) Transport Layer Encryption Modes
|
The Secure Shell (SSH) Transport Layer Encryption Modes
|
||||||
- <a href="https://tools.ietf.org/html/rfc4345" target="_blank">RFC 4345</a>,
|
|
||||||
Improved Arcfour Modes for the Secure Shell (SSH) Transport Layer Protocol
|
|
||||||
|
|
||||||
It was later modified and expanded by the following RFCs.
|
It was later modified and expanded by the following RFCs.
|
||||||
|
|
||||||
- <a href="https://tools.ietf.org/html/rfc4419" target="_blank">RFC 4419</a>,
|
- <a href="https://tools.ietf.org/html/rfc4419" target="_blank">RFC 4419</a>,
|
||||||
Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer
|
Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer
|
||||||
Protocol
|
Protocol
|
||||||
- <a href="https://tools.ietf.org/html/rfc4432" target="_blank">RFC 4432</a>,
|
|
||||||
RSA Key Exchange for the Secure Shell (SSH) Transport Layer Protocol
|
|
||||||
(not implemented in libssh)
|
|
||||||
- <a href="https://tools.ietf.org/html/rfc4462" target="_blank">RFC 4462</a>,
|
- <a href="https://tools.ietf.org/html/rfc4462" target="_blank">RFC 4462</a>,
|
||||||
Generic Security Service Application Program Interface (GSS-API)
|
Generic Security Service Application Program Interface (GSS-API)
|
||||||
Authentication and Key Exchange for the Secure Shell (SSH) Protocol
|
Authentication and Key Exchange for the Secure Shell (SSH) Protocol
|
||||||
(only the authentication implemented in libssh)
|
|
||||||
- <a href="https://tools.ietf.org/html/rfc4716" target="_blank">RFC 4716</a>,
|
- <a href="https://tools.ietf.org/html/rfc4716" target="_blank">RFC 4716</a>,
|
||||||
The Secure Shell (SSH) Public Key File Format
|
The Secure Shell (SSH) Public Key File Format
|
||||||
(not implemented in libssh)
|
(not implemented in libssh)
|
||||||
@@ -204,7 +198,6 @@ It was later modified and expanded by the following RFCs.
|
|||||||
(not implemented in libssh)
|
(not implemented in libssh)
|
||||||
- <a href="https://tools.ietf.org/html/rfc8160" target="_blank">RFC 8160</a>,
|
- <a href="https://tools.ietf.org/html/rfc8160" target="_blank">RFC 8160</a>,
|
||||||
IUTF8 Terminal Mode in Secure Shell (SSH)
|
IUTF8 Terminal Mode in Secure Shell (SSH)
|
||||||
(not handled in libssh)
|
|
||||||
- <a href="https://tools.ietf.org/html/rfc8270" target="_blank">RFC 8270</a>,
|
- <a href="https://tools.ietf.org/html/rfc8270" target="_blank">RFC 8270</a>,
|
||||||
Increase the Secure Shell Minimum Recommended Diffie-Hellman Modulus Size to 2048 Bits
|
Increase the Secure Shell Minimum Recommended Diffie-Hellman Modulus Size to 2048 Bits
|
||||||
- <a href="https://tools.ietf.org/html/rfc8308" target="_blank">RFC 8308</a>,
|
- <a href="https://tools.ietf.org/html/rfc8308" target="_blank">RFC 8308</a>,
|
||||||
@@ -223,6 +216,14 @@ There are also drafts that are being currently developed and followed.
|
|||||||
|
|
||||||
- <a href="https://tools.ietf.org/html/draft-miller-ssh-agent-03" target="_blank">draft-miller-ssh-agent-08</a>
|
- <a href="https://tools.ietf.org/html/draft-miller-ssh-agent-03" target="_blank">draft-miller-ssh-agent-08</a>
|
||||||
SSH Agent Protocol
|
SSH Agent Protocol
|
||||||
|
- <a href="https://tools.ietf.org/html/draft-ietf-sshm-mlkem-hybrid-kex-09" target="_blank">draft-ietf-sshm-mlkem-hybrid-kex-09</a>
|
||||||
|
PQ/T Hybrid Key Exchange with ML-KEM in SSH
|
||||||
|
- <a href="https://tools.ietf.org/html/draft-ietf-sshm-ntruprime-ssh-06" target="_blank">draft-ietf-sshm-ntruprime-ssh-06</a>
|
||||||
|
Secure Shell (SSH) Key Exchange Method Using Hybrid Streamlined NTRU Prime sntrup761 and X25519 with SHA-512: sntrup761x25519-sha512
|
||||||
|
- <a href="https://tools.ietf.org/html/draft-ietf-sshm-chacha20-poly1305-02" target="_blank">draft-ietf-sshm-chacha20-poly1305-02</a>
|
||||||
|
Secure Shell (SSH) authenticated encryption cipher: chacha20-poly1305
|
||||||
|
- <a href="https://tools.ietf.org/html/draft-ietf-sshm-strict-kex-01" target="_blank">draft-ietf-sshm-strict-kex-01</a>
|
||||||
|
SSH Strict KEX extension
|
||||||
|
|
||||||
Interesting cryptography documents:
|
Interesting cryptography documents:
|
||||||
|
|
||||||
@@ -247,8 +248,6 @@ them like the statvfs calls in SFTP or the ssh-agent.
|
|||||||
OpenSSH's deviations and extensions</a>
|
OpenSSH's deviations and extensions</a>
|
||||||
- <a href="https://api.libssh.org/rfc/PROTOCOL.certkeys" target="_blank">
|
- <a href="https://api.libssh.org/rfc/PROTOCOL.certkeys" target="_blank">
|
||||||
OpenSSH's pubkey certificate authentication</a>
|
OpenSSH's pubkey certificate authentication</a>
|
||||||
- <a href="https://api.libssh.org/rfc/PROTOCOL.chacha20poly1305" target="_blank">
|
|
||||||
chacha20-poly1305@openssh.com authenticated encryption mode</a>
|
|
||||||
- <a href="https://api.libssh.org/rfc/PROTOCOL.key" target="_blank">
|
- <a href="https://api.libssh.org/rfc/PROTOCOL.key" target="_blank">
|
||||||
OpenSSH private key format (openssh-key-v1)</a>
|
OpenSSH private key format (openssh-key-v1)</a>
|
||||||
|
|
||||||
|
|||||||
@@ -337,6 +337,7 @@ static void batch_shell(ssh_session session)
|
|||||||
static int client(ssh_session session)
|
static int client(ssh_session session)
|
||||||
{
|
{
|
||||||
int auth = 0;
|
int auth = 0;
|
||||||
|
int authenticated = 0;
|
||||||
char *banner = NULL;
|
char *banner = NULL;
|
||||||
int state;
|
int state;
|
||||||
|
|
||||||
@@ -369,16 +370,28 @@ static int client(ssh_session session)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_userauth_none(session, NULL);
|
|
||||||
banner = ssh_get_issue_banner(session);
|
banner = ssh_get_issue_banner(session);
|
||||||
if (banner) {
|
if (banner) {
|
||||||
printf("%s\n", banner);
|
printf("%s\n", banner);
|
||||||
free(banner);
|
free(banner);
|
||||||
}
|
}
|
||||||
|
auth = ssh_userauth_none(session, NULL);
|
||||||
|
if (auth == SSH_AUTH_SUCCESS) {
|
||||||
|
authenticated = 1;
|
||||||
|
} else if (auth == SSH_AUTH_ERROR) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Authentication error during none auth: %s\n",
|
||||||
|
ssh_get_error(session));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!authenticated) {
|
||||||
auth = authenticate_console(session);
|
auth = authenticate_console(session);
|
||||||
if (auth != SSH_AUTH_SUCCESS) {
|
if (auth != SSH_AUTH_SUCCESS) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (cmds[0] == NULL) {
|
if (cmds[0] == NULL) {
|
||||||
shell(session);
|
shell(session);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -432,6 +432,7 @@ enum ssh_options_e {
|
|||||||
SSH_OPTIONS_ADDRESS_FAMILY,
|
SSH_OPTIONS_ADDRESS_FAMILY,
|
||||||
SSH_OPTIONS_GSSAPI_KEY_EXCHANGE,
|
SSH_OPTIONS_GSSAPI_KEY_EXCHANGE,
|
||||||
SSH_OPTIONS_GSSAPI_KEY_EXCHANGE_ALGS,
|
SSH_OPTIONS_GSSAPI_KEY_EXCHANGE_ALGS,
|
||||||
|
SSH_OPTIONS_NEXT_IDENTITY,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
|||||||
@@ -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" {
|
||||||
@@ -43,8 +44,9 @@ extern "C" {
|
|||||||
|
|
||||||
/* in misc.c */
|
/* in misc.c */
|
||||||
/* gets the user home dir. */
|
/* gets the user home dir. */
|
||||||
char *ssh_get_user_home_dir(void);
|
char *ssh_get_user_home_dir(ssh_session session);
|
||||||
char *ssh_get_local_username(void);
|
char *ssh_get_local_username(void);
|
||||||
|
char *ssh_get_local_hostname(void);
|
||||||
int ssh_file_readaccess_ok(const char *file);
|
int ssh_file_readaccess_ok(const char *file);
|
||||||
int ssh_dir_writeable(const char *path);
|
int ssh_dir_writeable(const char *path);
|
||||||
|
|
||||||
@@ -136,6 +138,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
|
||||||
|
|||||||
@@ -508,6 +508,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
|
||||||
|
|||||||
@@ -246,13 +246,16 @@ struct ssh_session_struct {
|
|||||||
struct {
|
struct {
|
||||||
struct ssh_list *identity;
|
struct ssh_list *identity;
|
||||||
struct ssh_list *identity_non_exp;
|
struct ssh_list *identity_non_exp;
|
||||||
|
struct ssh_iterator *identity_it;
|
||||||
struct ssh_list *certificate;
|
struct ssh_list *certificate;
|
||||||
struct ssh_list *certificate_non_exp;
|
struct ssh_list *certificate_non_exp;
|
||||||
struct ssh_list *proxy_jumps;
|
struct ssh_list *proxy_jumps;
|
||||||
struct ssh_list *proxy_jumps_user_cb;
|
struct ssh_list *proxy_jumps_user_cb;
|
||||||
|
char *proxy_jumps_str;
|
||||||
char *username;
|
char *username;
|
||||||
char *host;
|
char *host;
|
||||||
char *bindaddr; /* bind the client to an ip addr */
|
char *bindaddr; /* bind the client to an ip addr */
|
||||||
|
char *homedir;
|
||||||
char *sshdir;
|
char *sshdir;
|
||||||
char *knownhosts;
|
char *knownhosts;
|
||||||
char *global_knownhosts;
|
char *global_knownhosts;
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
4.10.0
|
4.11.0
|
||||||
445
src/ABI/libssh-4.10.1.symbols
Normal file
445
src/ABI/libssh-4.10.1.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.2.symbols
Normal file
445
src/ABI/libssh-4.10.2.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.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
|
||||||
465
src/ABI/libssh-4.11.0.symbols
Normal file
465
src/ABI/libssh-4.11.0.symbols
Normal file
@@ -0,0 +1,465 @@
|
|||||||
|
_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_get_users_groups_by_id
|
||||||
|
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_name_id_map_free
|
||||||
|
sftp_name_id_map_new
|
||||||
|
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_supported_methods
|
||||||
|
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_get_sk_application
|
||||||
|
ssh_key_get_sk_flags
|
||||||
|
ssh_key_get_sk_user_id
|
||||||
|
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_ctx_free
|
||||||
|
ssh_pki_ctx_get_sk_attestation_buffer
|
||||||
|
ssh_pki_ctx_new
|
||||||
|
ssh_pki_ctx_options_set
|
||||||
|
ssh_pki_ctx_set_sk_pin_callback
|
||||||
|
ssh_pki_ctx_sk_callbacks_option_set
|
||||||
|
ssh_pki_ctx_sk_callbacks_options_clear
|
||||||
|
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_generate_key
|
||||||
|
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_sk_resident_keys_load
|
||||||
|
ssh_string_burn
|
||||||
|
ssh_string_cmp
|
||||||
|
ssh_string_copy
|
||||||
|
ssh_string_data
|
||||||
|
ssh_string_fill
|
||||||
|
ssh_string_free
|
||||||
|
ssh_string_free_char
|
||||||
|
ssh_string_from_char
|
||||||
|
ssh_string_from_data
|
||||||
|
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
|
||||||
|
sshsig_sign
|
||||||
|
sshsig_verify
|
||||||
|
string_burn
|
||||||
|
string_copy
|
||||||
|
string_data
|
||||||
|
string_fill
|
||||||
|
string_free
|
||||||
|
string_from_char
|
||||||
|
string_len
|
||||||
|
string_new
|
||||||
|
string_to_char
|
||||||
@@ -1396,6 +1396,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;
|
||||||
|
|||||||
@@ -217,7 +217,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);
|
||||||
@@ -655,7 +655,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;
|
||||||
}
|
}
|
||||||
|
|||||||
23
src/config.c
23
src/config.c
@@ -256,10 +256,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -493,6 +492,10 @@ ssh_config_parse_proxy_jump(ssh_session session, const char *s, bool do_parsing)
|
|||||||
bool parse_entry = do_parsing;
|
bool parse_entry = do_parsing;
|
||||||
bool libssh_proxy_jump = ssh_libssh_proxy_jumps();
|
bool libssh_proxy_jump = ssh_libssh_proxy_jumps();
|
||||||
|
|
||||||
|
if (do_parsing) {
|
||||||
|
SAFE_FREE(session->opts.proxy_jumps_str);
|
||||||
|
ssh_proxyjumps_free(session->opts.proxy_jumps);
|
||||||
|
}
|
||||||
/* Special value none disables the proxy */
|
/* Special value none disables the proxy */
|
||||||
cmp = strcasecmp(s, "none");
|
cmp = strcasecmp(s, "none");
|
||||||
if (cmp == 0) {
|
if (cmp == 0) {
|
||||||
@@ -509,6 +512,17 @@ ssh_config_parse_proxy_jump(ssh_session session, const char *s, bool do_parsing)
|
|||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (do_parsing) {
|
||||||
|
/* Store the whole string in session */
|
||||||
|
SAFE_FREE(session->opts.proxy_jumps_str);
|
||||||
|
session->opts.proxy_jumps_str = strdup(s);
|
||||||
|
if (session->opts.proxy_jumps_str == NULL) {
|
||||||
|
free(c);
|
||||||
|
ssh_set_error_oom(session);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cp = c;
|
cp = c;
|
||||||
do {
|
do {
|
||||||
endp = strchr(cp, ',');
|
endp = strchr(cp, ',');
|
||||||
@@ -1693,8 +1707,9 @@ int ssh_config_parse_file(ssh_session session, const char *filename)
|
|||||||
int rv;
|
int rv;
|
||||||
bool global = 0;
|
bool global = 0;
|
||||||
|
|
||||||
fp = fopen(filename, "r");
|
fp = ssh_strict_fopen(filename, SSH_MAX_CONFIG_FILE_SIZE);
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
|
/* The underlying function logs the reasons */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
111
src/connector.c
111
src/connector.c
@@ -305,6 +305,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 occurred.
|
||||||
|
*
|
||||||
|
* @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
|
||||||
*
|
*
|
||||||
@@ -390,8 +471,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;
|
||||||
}
|
}
|
||||||
@@ -444,8 +525,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;
|
||||||
}
|
}
|
||||||
@@ -542,16 +623,8 @@ static int ssh_connector_channel_data_cb(ssh_session session,
|
|||||||
window_len = MIN(window, len);
|
window_len = MIN(window, len);
|
||||||
|
|
||||||
/* Route the data to the right exception channel */
|
/* Route the data to the right exception channel */
|
||||||
if (is_stderr && (connector->out_flags & SSH_CONNECTOR_STDERR)) {
|
if (connector->out_flags & SSH_CONNECTOR_STDOUT &&
|
||||||
w = ssh_channel_write_stderr(connector->out_channel,
|
!(is_stderr && (connector->out_flags & SSH_CONNECTOR_STDERR))) {
|
||||||
data,
|
|
||||||
window_len);
|
|
||||||
} else if (!is_stderr &&
|
|
||||||
(connector->out_flags & SSH_CONNECTOR_STDOUT)) {
|
|
||||||
w = ssh_channel_write(connector->out_channel,
|
|
||||||
data,
|
|
||||||
window_len);
|
|
||||||
} else if (connector->out_flags & SSH_CONNECTOR_STDOUT) {
|
|
||||||
w = ssh_channel_write(connector->out_channel,
|
w = ssh_channel_write(connector->out_channel,
|
||||||
data,
|
data,
|
||||||
window_len);
|
window_len);
|
||||||
@@ -574,11 +647,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;
|
||||||
@@ -650,8 +719,8 @@ 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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -526,9 +526,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};
|
||||||
|
|||||||
23
src/gssapi.c
23
src/gssapi.c
@@ -198,7 +198,7 @@ int
|
|||||||
ssh_gssapi_handle_userauth(ssh_session session, const char *user,
|
ssh_gssapi_handle_userauth(ssh_session session, const char *user,
|
||||||
uint32_t n_oid, ssh_string *oids)
|
uint32_t n_oid, ssh_string *oids)
|
||||||
{
|
{
|
||||||
char hostname[NI_MAXHOST] = {0};
|
char *hostname = NULL;
|
||||||
OM_uint32 maj_stat, min_stat;
|
OM_uint32 maj_stat, min_stat;
|
||||||
size_t i;
|
size_t i;
|
||||||
gss_OID_set supported; /* oids supported by server */
|
gss_OID_set supported; /* oids supported by server */
|
||||||
@@ -210,14 +210,6 @@ ssh_gssapi_handle_userauth(ssh_session session, const char *user,
|
|||||||
int rc;
|
int rc;
|
||||||
char err_msg[SSH_ERRNO_MSG_MAX] = {0};
|
char err_msg[SSH_ERRNO_MSG_MAX] = {0};
|
||||||
|
|
||||||
rc = gethostname(hostname, 64);
|
|
||||||
if (rc != 0) {
|
|
||||||
SSH_LOG(SSH_LOG_TRACE,
|
|
||||||
"Error getting hostname: %s",
|
|
||||||
ssh_strerror(errno, err_msg, SSH_ERRNO_MSG_MAX));
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Destroy earlier GSSAPI context if any */
|
/* Destroy earlier GSSAPI context if any */
|
||||||
ssh_gssapi_free(session);
|
ssh_gssapi_free(session);
|
||||||
rc = ssh_gssapi_init(session);
|
rc = ssh_gssapi_init(session);
|
||||||
@@ -284,7 +276,16 @@ ssh_gssapi_handle_userauth(ssh_session session, const char *user,
|
|||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hostname = ssh_get_local_hostname();
|
||||||
|
if (hostname == NULL) {
|
||||||
|
SSH_LOG(SSH_LOG_TRACE,
|
||||||
|
"Error getting hostname: %s",
|
||||||
|
ssh_strerror(errno, err_msg, SSH_ERRNO_MSG_MAX));
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
rc = ssh_gssapi_import_name(session->gssapi, hostname);
|
rc = ssh_gssapi_import_name(session->gssapi, hostname);
|
||||||
|
SAFE_FREE(hostname);
|
||||||
if (rc != SSH_OK) {
|
if (rc != SSH_OK) {
|
||||||
ssh_auth_reply_default(session, 0);
|
ssh_auth_reply_default(session, 0);
|
||||||
gss_release_oid_set(&min_stat, &both_supported);
|
gss_release_oid_set(&min_stat, &both_supported);
|
||||||
@@ -850,6 +851,10 @@ int ssh_gssapi_client_identity(ssh_session session, gss_OID_set *valid_oids)
|
|||||||
char *ptr = NULL;
|
char *ptr = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (session == NULL || session->gssapi == NULL) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if (session->gssapi->client.client_deleg_creds == NULL) {
|
if (session->gssapi->client.client_deleg_creds == NULL) {
|
||||||
if (session->opts.gss_client_identity != NULL) {
|
if (session->opts.gss_client_identity != NULL) {
|
||||||
namebuf.value = (void *)session->opts.gss_client_identity;
|
namebuf.value = (void *)session->opts.gss_client_identity;
|
||||||
|
|||||||
@@ -421,7 +421,7 @@ int ssh_server_gss_kex_process_init(ssh_session session, ssh_buffer packet)
|
|||||||
gss_name_t client_name = GSS_C_NO_NAME;
|
gss_name_t client_name = GSS_C_NO_NAME;
|
||||||
OM_uint32 ret_flags = 0;
|
OM_uint32 ret_flags = 0;
|
||||||
gss_buffer_desc mic = GSS_C_EMPTY_BUFFER, msg = GSS_C_EMPTY_BUFFER;
|
gss_buffer_desc mic = GSS_C_EMPTY_BUFFER, msg = GSS_C_EMPTY_BUFFER;
|
||||||
char hostname[NI_MAXHOST] = {0};
|
char *hostname = NULL;
|
||||||
char err_msg[SSH_ERRNO_MSG_MAX] = {0};
|
char err_msg[SSH_ERRNO_MSG_MAX] = {0};
|
||||||
|
|
||||||
rc = ssh_buffer_unpack(packet, "S", &otoken);
|
rc = ssh_buffer_unpack(packet, "S", &otoken);
|
||||||
@@ -538,8 +538,8 @@ int ssh_server_gss_kex_process_init(ssh_session session, ssh_buffer packet)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = gethostname(hostname, 64);
|
hostname = ssh_get_local_hostname();
|
||||||
if (rc != 0) {
|
if (hostname == NULL) {
|
||||||
SSH_LOG(SSH_LOG_TRACE,
|
SSH_LOG(SSH_LOG_TRACE,
|
||||||
"Error getting hostname: %s",
|
"Error getting hostname: %s",
|
||||||
ssh_strerror(errno, err_msg, SSH_ERRNO_MSG_MAX));
|
ssh_strerror(errno, err_msg, SSH_ERRNO_MSG_MAX));
|
||||||
@@ -547,6 +547,7 @@ int ssh_server_gss_kex_process_init(ssh_session session, ssh_buffer packet)
|
|||||||
}
|
}
|
||||||
|
|
||||||
rc = ssh_gssapi_import_name(session->gssapi, hostname);
|
rc = ssh_gssapi_import_name(session->gssapi, hostname);
|
||||||
|
SAFE_FREE(hostname);
|
||||||
if (rc != SSH_OK) {
|
if (rc != SSH_OK) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -453,7 +491,7 @@ struct ssh_list *ssh_known_hosts_get_algorithms(ssh_session session)
|
|||||||
|
|
||||||
return list;
|
return list;
|
||||||
error:
|
error:
|
||||||
ssh_list_free(entry_list);
|
ssh_knownhosts_entries_free(entry_list);
|
||||||
ssh_list_free(list);
|
ssh_list_free(list);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -505,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
|
||||||
@@ -549,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -558,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -799,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;
|
||||||
@@ -860,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -871,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -883,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;
|
||||||
}
|
}
|
||||||
@@ -1079,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1115,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;
|
||||||
}
|
}
|
||||||
@@ -1196,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.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -615,10 +615,10 @@ int ssh_publickey_to_file(ssh_session session,
|
|||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
char *user = NULL;
|
char *user = NULL;
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
char host[256];
|
char *host = NULL;
|
||||||
unsigned char *pubkey_64 = NULL;
|
unsigned char *pubkey_64 = NULL;
|
||||||
size_t len;
|
size_t len;
|
||||||
int rc;
|
|
||||||
if(session==NULL)
|
if(session==NULL)
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
if(file==NULL || pubkey==NULL){
|
if(file==NULL || pubkey==NULL){
|
||||||
@@ -636,8 +636,8 @@ int ssh_publickey_to_file(ssh_session session,
|
|||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = gethostname(host, sizeof(host));
|
host = ssh_get_local_hostname();
|
||||||
if (rc < 0) {
|
if (host == NULL) {
|
||||||
SAFE_FREE(user);
|
SAFE_FREE(user);
|
||||||
SAFE_FREE(pubkey_64);
|
SAFE_FREE(pubkey_64);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
@@ -651,6 +651,7 @@ int ssh_publickey_to_file(ssh_session session,
|
|||||||
|
|
||||||
SAFE_FREE(pubkey_64);
|
SAFE_FREE(pubkey_64);
|
||||||
SAFE_FREE(user);
|
SAFE_FREE(user);
|
||||||
|
SAFE_FREE(host);
|
||||||
|
|
||||||
SSH_LOG(SSH_LOG_RARE, "Trying to write public key file: %s", file);
|
SSH_LOG(SSH_LOG_RARE, "Trying to write public key file: %s", file);
|
||||||
SSH_LOG(SSH_LOG_PACKET, "public key file content: %s", buffer);
|
SSH_LOG(SSH_LOG_PACKET, "public key file content: %s", buffer);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# This map file was updated with abimap-0.3.2
|
# This map file was updated with abimap-0.4.0
|
||||||
|
|
||||||
LIBSSH_4_5_0 # Released
|
LIBSSH_4_5_0 # Released
|
||||||
{
|
{
|
||||||
@@ -482,27 +482,28 @@ LIBSSH_4_10_0 # Released
|
|||||||
ssh_request_no_more_sessions;
|
ssh_request_no_more_sessions;
|
||||||
} LIBSSH_4_9_0;
|
} LIBSSH_4_9_0;
|
||||||
|
|
||||||
LIBSSH_AFTER_4_10_0
|
LIBSSH_4_11_0 # Released
|
||||||
{
|
{
|
||||||
global:
|
global:
|
||||||
sftp_get_users_groups_by_id;
|
sftp_get_users_groups_by_id;
|
||||||
sftp_name_id_map_free;
|
sftp_name_id_map_free;
|
||||||
sftp_name_id_map_new;
|
sftp_name_id_map_new;
|
||||||
ssh_get_supported_methods;
|
ssh_get_supported_methods;
|
||||||
sshsig_sign;
|
ssh_key_get_sk_application;
|
||||||
sshsig_verify;
|
ssh_key_get_sk_flags;
|
||||||
ssh_string_cmp;
|
ssh_key_get_sk_user_id;
|
||||||
ssh_string_from_data;
|
|
||||||
ssh_pki_ctx_new;
|
|
||||||
ssh_pki_ctx_free;
|
ssh_pki_ctx_free;
|
||||||
|
ssh_pki_ctx_get_sk_attestation_buffer;
|
||||||
|
ssh_pki_ctx_new;
|
||||||
ssh_pki_ctx_options_set;
|
ssh_pki_ctx_options_set;
|
||||||
ssh_pki_ctx_set_sk_pin_callback;
|
ssh_pki_ctx_set_sk_pin_callback;
|
||||||
ssh_pki_ctx_sk_callbacks_option_set;
|
ssh_pki_ctx_sk_callbacks_option_set;
|
||||||
ssh_pki_ctx_sk_callbacks_options_clear;
|
ssh_pki_ctx_sk_callbacks_options_clear;
|
||||||
ssh_pki_ctx_get_sk_attestation_buffer;
|
|
||||||
ssh_key_get_sk_flags;
|
|
||||||
ssh_key_get_sk_application;
|
|
||||||
ssh_key_get_sk_user_id;
|
|
||||||
ssh_pki_generate_key;
|
ssh_pki_generate_key;
|
||||||
ssh_sk_resident_keys_load;
|
ssh_sk_resident_keys_load;
|
||||||
|
ssh_string_cmp;
|
||||||
|
ssh_string_from_data;
|
||||||
|
sshsig_sign;
|
||||||
|
sshsig_verify;
|
||||||
} LIBSSH_4_10_0;
|
} LIBSSH_4_10_0;
|
||||||
|
|
||||||
|
|||||||
123
src/match.c
123
src/match.c
@@ -53,85 +53,70 @@
|
|||||||
|
|
||||||
#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');
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -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 {
|
||||||
|
|||||||
330
src/misc.c
330
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>
|
||||||
@@ -108,7 +109,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
char *ssh_get_user_home_dir(void)
|
static char *ssh_get_user_home_dir_internal(void)
|
||||||
{
|
{
|
||||||
char tmp[PATH_MAX] = {0};
|
char tmp[PATH_MAX] = {0};
|
||||||
char *szPath = NULL;
|
char *szPath = NULL;
|
||||||
@@ -298,7 +299,7 @@ int ssh_is_ipaddr(const char *str)
|
|||||||
#define NSS_BUFLEN_PASSWD 4096
|
#define NSS_BUFLEN_PASSWD 4096
|
||||||
#endif /* NSS_BUFLEN_PASSWD */
|
#endif /* NSS_BUFLEN_PASSWD */
|
||||||
|
|
||||||
char *ssh_get_user_home_dir(void)
|
static char *ssh_get_user_home_dir_internal(void)
|
||||||
{
|
{
|
||||||
char *szPath = NULL;
|
char *szPath = NULL;
|
||||||
struct passwd pwd;
|
struct passwd pwd;
|
||||||
@@ -313,7 +314,6 @@ char *ssh_get_user_home_dir(void)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
snprintf(buf, sizeof(buf), "%s", szPath);
|
snprintf(buf, sizeof(buf), "%s", szPath);
|
||||||
|
|
||||||
return strdup(buf);
|
return strdup(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,6 +428,29 @@ int ssh_is_ipaddr(const char *str)
|
|||||||
|
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
char *ssh_get_user_home_dir(ssh_session session)
|
||||||
|
{
|
||||||
|
char *szPath = NULL;
|
||||||
|
|
||||||
|
/* If used previously, reuse cached value */
|
||||||
|
if (session != NULL && session->opts.homedir != NULL) {
|
||||||
|
return strdup(session->opts.homedir);
|
||||||
|
}
|
||||||
|
|
||||||
|
szPath = ssh_get_user_home_dir_internal();
|
||||||
|
if (szPath == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session != NULL) {
|
||||||
|
/* cache it:
|
||||||
|
* failure is not fatal -- at worst we will just not cache it */
|
||||||
|
session->opts.homedir = strdup(szPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return szPath;
|
||||||
|
}
|
||||||
|
|
||||||
char *ssh_lowercase(const char* str)
|
char *ssh_lowercase(const char* str)
|
||||||
{
|
{
|
||||||
char *new = NULL, *p = NULL;
|
char *new = NULL, *p = NULL;
|
||||||
@@ -468,6 +491,38 @@ char *ssh_hostport(const char *host, int port)
|
|||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
ssh_get_hexa_internal(const unsigned char *what, size_t len, bool colons)
|
||||||
|
{
|
||||||
|
const char h[] = "0123456789abcdef";
|
||||||
|
char *hexa = NULL;
|
||||||
|
size_t i;
|
||||||
|
size_t bytes_per_byte = 2 + (colons ? 1 : 0);
|
||||||
|
size_t hlen = len * bytes_per_byte;
|
||||||
|
|
||||||
|
if (what == NULL || len < 1 || len > (UINT_MAX - 1) / bytes_per_byte) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
hexa = calloc(hlen + 1, sizeof(char));
|
||||||
|
if (hexa == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
hexa[i * bytes_per_byte] = h[(what[i] >> 4) & 0xF];
|
||||||
|
hexa[i * bytes_per_byte + 1] = h[what[i] & 0xF];
|
||||||
|
if (colons) {
|
||||||
|
hexa[i * bytes_per_byte + 2] = ':';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (colons) {
|
||||||
|
hexa[hlen - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return hexa;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Convert a buffer into a colon separated hex string.
|
* @brief Convert a buffer into a colon separated hex string.
|
||||||
* The caller has to free the memory.
|
* The caller has to free the memory.
|
||||||
@@ -483,28 +538,7 @@ char *ssh_hostport(const char *host, int port)
|
|||||||
*/
|
*/
|
||||||
char *ssh_get_hexa(const unsigned char *what, size_t len)
|
char *ssh_get_hexa(const unsigned char *what, size_t len)
|
||||||
{
|
{
|
||||||
const char h[] = "0123456789abcdef";
|
return ssh_get_hexa_internal(what, len, true);
|
||||||
char *hexa = NULL;
|
|
||||||
size_t i;
|
|
||||||
size_t hlen = len * 3;
|
|
||||||
|
|
||||||
if (len > (UINT_MAX - 1) / 3) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
hexa = malloc(hlen + 1);
|
|
||||||
if (hexa == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
hexa[i * 3] = h[(what[i] >> 4) & 0xF];
|
|
||||||
hexa[i * 3 + 1] = h[what[i] & 0xF];
|
|
||||||
hexa[i * 3 + 2] = ':';
|
|
||||||
}
|
|
||||||
hexa[hlen - 1] = '\0';
|
|
||||||
|
|
||||||
return hexa;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -814,7 +848,17 @@ static struct ssh_iterator *ssh_iterator_new(const void *data)
|
|||||||
return iterator;
|
return iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ssh_list_append(struct ssh_list *list,const void *data)
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @brief Appends an element to the end of the list.
|
||||||
|
*
|
||||||
|
* @param[in] list The list to append the element
|
||||||
|
* @param[in] data The element to append
|
||||||
|
*
|
||||||
|
* @return `SSH_OK` on success, `SSH_ERROR` on error
|
||||||
|
*/
|
||||||
|
int ssh_list_append(struct ssh_list *list, const void *data)
|
||||||
{
|
{
|
||||||
struct ssh_iterator *iterator = NULL;
|
struct ssh_iterator *iterator = NULL;
|
||||||
|
|
||||||
@@ -1179,7 +1223,7 @@ char *ssh_path_expand_tilde(const char *d)
|
|||||||
} else {
|
} else {
|
||||||
ld = strlen(d);
|
ld = strlen(d);
|
||||||
p = (char *) d;
|
p = (char *) d;
|
||||||
h = ssh_get_user_home_dir();
|
h = ssh_get_user_home_dir(NULL);
|
||||||
}
|
}
|
||||||
if (h == NULL) {
|
if (h == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1201,15 +1245,118 @@ char *ssh_path_expand_tilde(const char *d)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *ssh_get_local_hostname(void)
|
||||||
|
{
|
||||||
|
char host[NI_MAXHOST] = {0};
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = gethostname(host, sizeof(host));
|
||||||
|
if (rc != 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return strdup(host);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *get_connection_hash(ssh_session session)
|
||||||
|
{
|
||||||
|
unsigned char conn_hash[SHA_DIGEST_LENGTH];
|
||||||
|
char *local_hostname = NULL;
|
||||||
|
SHACTX ctx = sha1_init();
|
||||||
|
char strport[10] = {0};
|
||||||
|
unsigned int port;
|
||||||
|
char *username = NULL;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (session == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx == NULL) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Local hostname %l */
|
||||||
|
local_hostname = ssh_get_local_hostname();
|
||||||
|
if (local_hostname == NULL) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
rc = sha1_update(ctx, local_hostname, strlen(local_hostname));
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
SAFE_FREE(local_hostname);
|
||||||
|
|
||||||
|
/* Remote hostname %h */
|
||||||
|
if (session->opts.host == NULL) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
rc = sha1_update(ctx, session->opts.host, strlen(session->opts.host));
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remote port %p */
|
||||||
|
ssh_options_get_port(session, &port);
|
||||||
|
snprintf(strport, sizeof(strport), "%d", port);
|
||||||
|
rc = sha1_update(ctx, strport, strlen(strport));
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The remote username %r */
|
||||||
|
username = session->opts.username;
|
||||||
|
if (username == NULL) {
|
||||||
|
/* fallback to local username: it will be used if not explicitly set */
|
||||||
|
username = ssh_get_local_username();
|
||||||
|
if (username == NULL) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rc = sha1_update(ctx, username, strlen(username));
|
||||||
|
if (username != session->opts.username) {
|
||||||
|
free(username);
|
||||||
|
}
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ProxyJump */
|
||||||
|
if (session->opts.proxy_jumps_str != NULL) {
|
||||||
|
rc = sha1_update(ctx,
|
||||||
|
session->opts.proxy_jumps_str,
|
||||||
|
strlen(session->opts.proxy_jumps_str));
|
||||||
|
}
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Frees context */
|
||||||
|
rc = sha1_final(conn_hash, ctx);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ssh_get_hexa_internal(conn_hash, SHA_DIGEST_LENGTH, false);
|
||||||
|
|
||||||
|
err:
|
||||||
|
free(local_hostname);
|
||||||
|
sha1_ctx_free(ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/** @internal
|
/** @internal
|
||||||
* @brief expands a string in function of session options
|
* @brief expands a string in function of session options
|
||||||
|
*
|
||||||
* @param[in] s Format string to expand. Known parameters:
|
* @param[in] s Format string to expand. Known parameters:
|
||||||
* %d SSH configuration directory (~/.ssh)
|
* - %d user home directory (~)
|
||||||
* %h target host name
|
* - %h target host name
|
||||||
* %u local username
|
* - %u local username
|
||||||
* %l local hostname
|
* - %l local hostname
|
||||||
* %r remote username
|
* - %r remote username
|
||||||
* %p remote port
|
* - %p remote port
|
||||||
|
* - %j proxyjump string
|
||||||
|
* - %C Hash of %l%h%p%r%j
|
||||||
|
*
|
||||||
* @returns Expanded string. The caller needs to free the memory using
|
* @returns Expanded string. The caller needs to free the memory using
|
||||||
* ssh_string_free_char().
|
* ssh_string_free_char().
|
||||||
*
|
*
|
||||||
@@ -1217,7 +1364,6 @@ char *ssh_path_expand_tilde(const char *d)
|
|||||||
*/
|
*/
|
||||||
char *ssh_path_expand_escape(ssh_session session, const char *s)
|
char *ssh_path_expand_escape(ssh_session session, const char *s)
|
||||||
{
|
{
|
||||||
char host[NI_MAXHOST] = {0};
|
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
char *r = NULL;
|
char *r = NULL;
|
||||||
char *x = NULL;
|
char *x = NULL;
|
||||||
@@ -1269,11 +1415,9 @@ char *ssh_path_expand_escape(ssh_session session, const char *s)
|
|||||||
case '%':
|
case '%':
|
||||||
goto escape;
|
goto escape;
|
||||||
case 'd':
|
case 'd':
|
||||||
if (session->opts.sshdir) {
|
x = ssh_get_user_home_dir(session);
|
||||||
x = strdup(session->opts.sshdir);
|
if (x == NULL) {
|
||||||
} else {
|
ssh_set_error(session, SSH_FATAL, "Cannot expand homedir");
|
||||||
ssh_set_error(session, SSH_FATAL,
|
|
||||||
"Cannot expand sshdir");
|
|
||||||
free(buf);
|
free(buf);
|
||||||
free(r);
|
free(r);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1283,16 +1427,13 @@ char *ssh_path_expand_escape(ssh_session session, const char *s)
|
|||||||
x = ssh_get_local_username();
|
x = ssh_get_local_username();
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
if (gethostname(host, sizeof(host) == 0)) {
|
x = ssh_get_local_hostname();
|
||||||
x = strdup(host);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
if (session->opts.host) {
|
if (session->opts.host) {
|
||||||
x = strdup(session->opts.host);
|
x = strdup(session->opts.host);
|
||||||
} else {
|
} else {
|
||||||
ssh_set_error(session, SSH_FATAL,
|
ssh_set_error(session, SSH_FATAL, "Cannot expand host");
|
||||||
"Cannot expand host");
|
|
||||||
free(buf);
|
free(buf);
|
||||||
free(r);
|
free(r);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1302,26 +1443,33 @@ char *ssh_path_expand_escape(ssh_session session, const char *s)
|
|||||||
if (session->opts.username) {
|
if (session->opts.username) {
|
||||||
x = strdup(session->opts.username);
|
x = strdup(session->opts.username);
|
||||||
} else {
|
} else {
|
||||||
ssh_set_error(session, SSH_FATAL,
|
ssh_set_error(session, SSH_FATAL, "Cannot expand username");
|
||||||
"Cannot expand username");
|
|
||||||
free(buf);
|
free(buf);
|
||||||
free(r);
|
free(r);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p': {
|
||||||
{
|
|
||||||
char tmp[6];
|
char tmp[6];
|
||||||
|
unsigned int port;
|
||||||
|
|
||||||
snprintf(tmp, sizeof(tmp), "%hu",
|
ssh_options_get_port(session, &port);
|
||||||
(uint16_t)(session->opts.port > 0 ? session->opts.port
|
snprintf(tmp, sizeof(tmp), "%u", port);
|
||||||
: 22));
|
|
||||||
x = strdup(tmp);
|
x = strdup(tmp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'j':
|
||||||
|
if (session->opts.proxy_jumps_str != NULL) {
|
||||||
|
x = strdup(session->opts.proxy_jumps_str);
|
||||||
|
} else {
|
||||||
|
x = strdup("");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'C':
|
||||||
|
x = get_connection_hash(session);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ssh_set_error(session, SSH_FATAL,
|
ssh_set_error(session, SSH_FATAL, "Wrong escape sequence detected");
|
||||||
"Wrong escape sequence detected");
|
|
||||||
free(buf);
|
free(buf);
|
||||||
free(r);
|
free(r);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1336,8 +1484,7 @@ char *ssh_path_expand_escape(ssh_session session, const char *s)
|
|||||||
|
|
||||||
i += strlen(x);
|
i += strlen(x);
|
||||||
if (i >= MAX_BUF_SIZE) {
|
if (i >= MAX_BUF_SIZE) {
|
||||||
ssh_set_error(session, SSH_FATAL,
|
ssh_set_error(session, SSH_FATAL, "String too long");
|
||||||
"String too long");
|
|
||||||
free(buf);
|
free(buf);
|
||||||
free(x);
|
free(x);
|
||||||
free(r);
|
free(r);
|
||||||
@@ -2283,4 +2430,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;
|
||||||
|
}
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|||||||
@@ -907,7 +907,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;
|
||||||
@@ -1197,7 +1197,6 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
|||||||
ssh_set_error_invalid(session);
|
ssh_set_error_invalid(session);
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
ssh_proxyjumps_free(session->opts.proxy_jumps);
|
|
||||||
rc = ssh_config_parse_proxy_jump(session, v, true);
|
rc = ssh_config_parse_proxy_jump(session, v, true);
|
||||||
if (rc != SSH_OK) {
|
if (rc != SSH_OK) {
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
@@ -1562,7 +1561,16 @@ int ssh_options_get_port(ssh_session session, unsigned int* port_target) {
|
|||||||
* - SSH_OPTIONS_IDENTITY:
|
* - SSH_OPTIONS_IDENTITY:
|
||||||
* Get the first identity file name (const char *).\n
|
* Get the first identity file name (const char *).\n
|
||||||
* \n
|
* \n
|
||||||
* By default id_rsa, id_ecdsa and id_ed25519 files are used.
|
* By default `id_rsa`, `id_ecdsa`, `id_ed25519`, `id_ecdsa_sk`
|
||||||
|
* and `id_ed25519_sk` (when SK support is built in) files are
|
||||||
|
* used.
|
||||||
|
*
|
||||||
|
* - SSH_OPTIONS_NEXT_IDENTITY:
|
||||||
|
* Get the next identity file name (const char *).\n
|
||||||
|
* \n
|
||||||
|
* Repeat calls to get all key paths. SSH_EOF is returned when
|
||||||
|
* the end of list is reached. Another call will start another
|
||||||
|
* iteration over the same list.
|
||||||
*
|
*
|
||||||
* - SSH_OPTIONS_PROXYCOMMAND:
|
* - SSH_OPTIONS_PROXYCOMMAND:
|
||||||
* Get the proxycommand necessary to log into the
|
* Get the proxycommand necessary to log into the
|
||||||
@@ -1658,6 +1666,30 @@ int ssh_options_get(ssh_session session, enum ssh_options_e type, char** value)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case SSH_OPTIONS_NEXT_IDENTITY: {
|
||||||
|
if (session->opts.identity_it != NULL) {
|
||||||
|
/* Move to the next item */
|
||||||
|
session->opts.identity_it = session->opts.identity_it->next;
|
||||||
|
if (session->opts.identity_it == NULL) {
|
||||||
|
*value = NULL;
|
||||||
|
return SSH_EOF;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Get iterator from opts */
|
||||||
|
struct ssh_iterator *it = NULL;
|
||||||
|
it = ssh_list_get_iterator(session->opts.identity);
|
||||||
|
if (it == NULL) {
|
||||||
|
it = ssh_list_get_iterator(session->opts.identity_non_exp);
|
||||||
|
}
|
||||||
|
if (it == NULL) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
session->opts.identity_it = it;
|
||||||
|
}
|
||||||
|
src = ssh_iterator_value(char *, session->opts.identity_it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case SSH_OPTIONS_PROXYCOMMAND:
|
case SSH_OPTIONS_PROXYCOMMAND:
|
||||||
src = session->opts.ProxyCommand;
|
src = session->opts.ProxyCommand;
|
||||||
break;
|
break;
|
||||||
@@ -1963,7 +1995,7 @@ int ssh_options_parse_config(ssh_session session, const char *filename)
|
|||||||
|
|
||||||
/* set default filename */
|
/* set default filename */
|
||||||
if (filename == NULL) {
|
if (filename == NULL) {
|
||||||
expanded_filename = ssh_path_expand_escape(session, "%d/config");
|
expanded_filename = ssh_path_expand_escape(session, "%d/.ssh/config");
|
||||||
} else {
|
} else {
|
||||||
expanded_filename = ssh_path_expand_escape(session, filename);
|
expanded_filename = ssh_path_expand_escape(session, filename);
|
||||||
}
|
}
|
||||||
@@ -1976,11 +2008,16 @@ int ssh_options_parse_config(ssh_session session, const char *filename)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (filename == NULL) {
|
if (filename == NULL) {
|
||||||
if ((fp = fopen(GLOBAL_CLIENT_CONFIG, "r")) != NULL) {
|
fp = ssh_strict_fopen(GLOBAL_CLIENT_CONFIG, SSH_MAX_CONFIG_FILE_SIZE);
|
||||||
|
if (fp != NULL) {
|
||||||
filename = GLOBAL_CLIENT_CONFIG;
|
filename = GLOBAL_CLIENT_CONFIG;
|
||||||
#ifdef USR_GLOBAL_CLIENT_CONFIG
|
#ifdef USR_GLOBAL_CLIENT_CONFIG
|
||||||
} else if ((fp = fopen(USR_GLOBAL_CLIENT_CONFIG, "r")) != NULL) {
|
} else {
|
||||||
|
fp = ssh_strict_fopen(USR_GLOBAL_CLIENT_CONFIG,
|
||||||
|
SSH_MAX_CONFIG_FILE_SIZE);
|
||||||
|
if (fp != NULL) {
|
||||||
filename = USR_GLOBAL_CLIENT_CONFIG;
|
filename = USR_GLOBAL_CLIENT_CONFIG;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2021,7 +2058,7 @@ int ssh_options_apply(ssh_session session)
|
|||||||
|
|
||||||
if ((session->opts.exp_flags & SSH_OPT_EXP_FLAG_KNOWNHOSTS) == 0) {
|
if ((session->opts.exp_flags & SSH_OPT_EXP_FLAG_KNOWNHOSTS) == 0) {
|
||||||
if (session->opts.knownhosts == NULL) {
|
if (session->opts.knownhosts == NULL) {
|
||||||
tmp = ssh_path_expand_escape(session, "%d/known_hosts");
|
tmp = ssh_path_expand_escape(session, "%d/.ssh/known_hosts");
|
||||||
} else {
|
} else {
|
||||||
tmp = ssh_path_expand_escape(session, session->opts.knownhosts);
|
tmp = ssh_path_expand_escape(session, session->opts.knownhosts);
|
||||||
}
|
}
|
||||||
@@ -2035,7 +2072,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);
|
||||||
|
|||||||
12
src/pki.c
12
src/pki.c
@@ -834,6 +834,10 @@ int ssh_key_is_private(const ssh_key k) {
|
|||||||
/**
|
/**
|
||||||
* @brief Compare keys if they are equal.
|
* @brief Compare keys if they are equal.
|
||||||
*
|
*
|
||||||
|
* Note that comparing private keys is almost never needed. The private key
|
||||||
|
* is cryptographically bound to the public key and comparing public keys should
|
||||||
|
* always be preferred.
|
||||||
|
*
|
||||||
* @param[in] k1 The first key to compare.
|
* @param[in] k1 The first key to compare.
|
||||||
*
|
*
|
||||||
* @param[in] k2 The second key to compare.
|
* @param[in] k2 The second key to compare.
|
||||||
@@ -2684,7 +2688,7 @@ int ssh_pki_export_pubkey_file(const ssh_key key,
|
|||||||
const char *filename)
|
const char *filename)
|
||||||
{
|
{
|
||||||
char key_buf[MAX_LINE_SIZE];
|
char key_buf[MAX_LINE_SIZE];
|
||||||
char host[256];
|
char *host = NULL;
|
||||||
char *b64_key = NULL;
|
char *b64_key = NULL;
|
||||||
char *user = NULL;
|
char *user = NULL;
|
||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
@@ -2699,8 +2703,8 @@ int ssh_pki_export_pubkey_file(const ssh_key key,
|
|||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = gethostname(host, sizeof(host));
|
host = ssh_get_local_hostname();
|
||||||
if (rc < 0) {
|
if (host == NULL) {
|
||||||
free(user);
|
free(user);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
@@ -2708,6 +2712,7 @@ int ssh_pki_export_pubkey_file(const ssh_key key,
|
|||||||
rc = ssh_pki_export_pubkey_base64(key, &b64_key);
|
rc = ssh_pki_export_pubkey_base64(key, &b64_key);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
free(user);
|
free(user);
|
||||||
|
free(host);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2718,6 +2723,7 @@ int ssh_pki_export_pubkey_file(const ssh_key key,
|
|||||||
user,
|
user,
|
||||||
host);
|
host);
|
||||||
free(user);
|
free(user);
|
||||||
|
free(host);
|
||||||
free(b64_key);
|
free(b64_key);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ pki_ed25519_key_cmp(const ssh_key k1, const ssh_key k2, enum ssh_keycmp_e what)
|
|||||||
}
|
}
|
||||||
/* In the internal implementation, the private key is the concatenation
|
/* In the internal implementation, the private key is the concatenation
|
||||||
* of the private seed with the public key. */
|
* of the private seed with the public key. */
|
||||||
cmp = memcmp(k1->ed25519_privkey,
|
cmp = secure_memcmp(k1->ed25519_privkey,
|
||||||
k2->ed25519_privkey,
|
k2->ed25519_privkey,
|
||||||
2 * ED25519_KEY_LEN);
|
2 * ED25519_KEY_LEN);
|
||||||
if (cmp != 0) {
|
if (cmp != 0) {
|
||||||
|
|||||||
16
src/scp.c
16
src/scp.c
@@ -874,6 +874,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') {
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ ssh_session ssh_new(void)
|
|||||||
}
|
}
|
||||||
#endif /* WITH_GSSAPI */
|
#endif /* WITH_GSSAPI */
|
||||||
|
|
||||||
id = strdup("%d/id_ed25519");
|
id = strdup("%d/.ssh/id_ed25519");
|
||||||
if (id == NULL) {
|
if (id == NULL) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -179,7 +179,7 @@ ssh_session ssh_new(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_ECC
|
#ifdef HAVE_ECC
|
||||||
id = strdup("%d/id_ecdsa");
|
id = strdup("%d/.ssh/id_ecdsa");
|
||||||
if (id == NULL) {
|
if (id == NULL) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -189,7 +189,7 @@ ssh_session ssh_new(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
id = strdup("%d/id_rsa");
|
id = strdup("%d/.ssh/id_rsa");
|
||||||
if (id == NULL) {
|
if (id == NULL) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -200,7 +200,7 @@ ssh_session ssh_new(void)
|
|||||||
|
|
||||||
#ifdef WITH_FIDO2
|
#ifdef WITH_FIDO2
|
||||||
/* Add security key identities */
|
/* Add security key identities */
|
||||||
id = strdup("%d/id_ed25519_sk");
|
id = strdup("%d/.ssh/id_ed25519_sk");
|
||||||
if (id == NULL) {
|
if (id == NULL) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -210,7 +210,7 @@ ssh_session ssh_new(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_ECC
|
#ifdef HAVE_ECC
|
||||||
id = strdup("%d/id_ecdsa_sk");
|
id = strdup("%d/.ssh/id_ecdsa_sk");
|
||||||
if (id == NULL) {
|
if (id == NULL) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -384,6 +384,7 @@ void ssh_free(ssh_session session)
|
|||||||
ssh_proxyjumps_free(session->opts.proxy_jumps);
|
ssh_proxyjumps_free(session->opts.proxy_jumps);
|
||||||
SSH_LIST_FREE(session->opts.proxy_jumps);
|
SSH_LIST_FREE(session->opts.proxy_jumps);
|
||||||
SSH_LIST_FREE(session->opts.proxy_jumps_user_cb);
|
SSH_LIST_FREE(session->opts.proxy_jumps_user_cb);
|
||||||
|
SAFE_FREE(session->opts.proxy_jumps_str);
|
||||||
|
|
||||||
while ((b = ssh_list_pop_head(struct ssh_buffer_struct *,
|
while ((b = ssh_list_pop_head(struct ssh_buffer_struct *,
|
||||||
session->out_queue)) != NULL) {
|
session->out_queue)) != NULL) {
|
||||||
@@ -405,6 +406,7 @@ void ssh_free(ssh_session session)
|
|||||||
SAFE_FREE(session->opts.bindaddr);
|
SAFE_FREE(session->opts.bindaddr);
|
||||||
SAFE_FREE(session->opts.username);
|
SAFE_FREE(session->opts.username);
|
||||||
SAFE_FREE(session->opts.host);
|
SAFE_FREE(session->opts.host);
|
||||||
|
SAFE_FREE(session->opts.homedir);
|
||||||
SAFE_FREE(session->opts.sshdir);
|
SAFE_FREE(session->opts.sshdir);
|
||||||
SAFE_FREE(session->opts.knownhosts);
|
SAFE_FREE(session->opts.knownhosts);
|
||||||
SAFE_FREE(session->opts.global_knownhosts);
|
SAFE_FREE(session->opts.global_knownhosts);
|
||||||
|
|||||||
21
src/sftp.c
21
src/sftp.c
@@ -583,7 +583,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;
|
||||||
}
|
}
|
||||||
@@ -591,15 +592,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;
|
||||||
}
|
}
|
||||||
@@ -607,15 +611,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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -461,19 +461,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 {
|
||||||
@@ -481,8 +486,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++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -549,17 +559,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) {
|
||||||
|
|||||||
218
src/socket.c
218
src/socket.c
@@ -97,6 +97,10 @@ struct ssh_socket_struct {
|
|||||||
struct jump_thread_data_struct {
|
struct jump_thread_data_struct {
|
||||||
ssh_session session;
|
ssh_session session;
|
||||||
socket_t fd;
|
socket_t fd;
|
||||||
|
char *next_hostname;
|
||||||
|
uint16_t next_port;
|
||||||
|
struct ssh_jump_info_struct *next_jump;
|
||||||
|
struct ssh_jump_callbacks_struct *next_cb;
|
||||||
};
|
};
|
||||||
|
|
||||||
int proxy_disconnect = 0;
|
int proxy_disconnect = 0;
|
||||||
@@ -1249,6 +1253,22 @@ verify_knownhost(ssh_session session)
|
|||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void free_jump_thread_data(struct jump_thread_data_struct *data)
|
||||||
|
{
|
||||||
|
if (data == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssh_free(data->session);
|
||||||
|
SAFE_FREE(data->next_hostname);
|
||||||
|
if (data->next_jump != NULL) {
|
||||||
|
SAFE_FREE(data->next_jump->hostname);
|
||||||
|
SAFE_FREE(data->next_jump->username);
|
||||||
|
}
|
||||||
|
SAFE_FREE(data->next_jump);
|
||||||
|
SAFE_FREE(data);
|
||||||
|
}
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
jump_thread_func(void *arg)
|
jump_thread_func(void *arg)
|
||||||
{
|
{
|
||||||
@@ -1260,72 +1280,30 @@ jump_thread_func(void *arg)
|
|||||||
int rc;
|
int rc;
|
||||||
ssh_event event = NULL;
|
ssh_event event = NULL;
|
||||||
ssh_connector connector_in = NULL, connector_out = NULL;
|
ssh_connector connector_in = NULL, connector_out = NULL;
|
||||||
ssh_session session = NULL;
|
uint16_t next_port;
|
||||||
int next_port;
|
|
||||||
char *next_hostname = NULL;
|
char *next_hostname = NULL;
|
||||||
|
|
||||||
jump_thread_data = (struct jump_thread_data_struct *)arg;
|
jump_thread_data = (struct jump_thread_data_struct *)arg;
|
||||||
session = jump_thread_data->session;
|
jump_session = jump_thread_data->session;
|
||||||
|
|
||||||
next_port = session->opts.port;
|
/* First thing we need to do is to set the right level as its kept in
|
||||||
next_hostname = strdup(session->opts.host);
|
* thread local variable, therefore reset to 0 after spawning new thread.
|
||||||
|
*/
|
||||||
|
ssh_set_log_level(jump_session->common.log_verbosity);
|
||||||
|
|
||||||
jump_session = ssh_new();
|
cb = jump_thread_data->next_cb;
|
||||||
if (jump_session == NULL) {
|
jis = jump_thread_data->next_jump;
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
jump_session->proxy_root = false;
|
/* This is the calling thread target where we will eventually initialize
|
||||||
/* Reset the global variable if it was previously 1 */
|
* forwarding */
|
||||||
if (session->proxy_root) {
|
next_port = jump_thread_data->next_port;
|
||||||
proxy_disconnect = 0;
|
next_hostname = jump_thread_data->next_hostname;
|
||||||
}
|
|
||||||
|
|
||||||
for (jis = ssh_list_pop_head(struct ssh_jump_info_struct *,
|
|
||||||
session->opts.proxy_jumps);
|
|
||||||
jis != NULL;
|
|
||||||
jis = ssh_list_pop_head(struct ssh_jump_info_struct *,
|
|
||||||
session->opts.proxy_jumps)) {
|
|
||||||
rc = ssh_list_append(jump_session->opts.proxy_jumps, jis);
|
|
||||||
if (rc != SSH_OK) {
|
|
||||||
ssh_set_error_oom(session);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (jis =
|
|
||||||
ssh_list_pop_head(struct ssh_jump_info_struct *,
|
|
||||||
session->opts.proxy_jumps_user_cb);
|
|
||||||
jis != NULL;
|
|
||||||
jis = ssh_list_pop_head(struct ssh_jump_info_struct *,
|
|
||||||
session->opts.proxy_jumps_user_cb)) {
|
|
||||||
rc = ssh_list_append(jump_session->opts.proxy_jumps_user_cb, jis);
|
|
||||||
if (rc != SSH_OK) {
|
|
||||||
ssh_set_error_oom(session);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ssh_options_set(jump_session,
|
|
||||||
SSH_OPTIONS_LOG_VERBOSITY,
|
|
||||||
&session->common.log_verbosity);
|
|
||||||
|
|
||||||
/* Pop the information about the current jump */
|
|
||||||
jis = ssh_list_pop_head(struct ssh_jump_info_struct *,
|
|
||||||
jump_session->opts.proxy_jumps);
|
|
||||||
if (jis == NULL) {
|
|
||||||
SSH_LOG(SSH_LOG_WARN, "Inconsistent list of proxy jumps received");
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssh_options_set(jump_session, SSH_OPTIONS_HOST, jis->hostname);
|
ssh_options_set(jump_session, SSH_OPTIONS_HOST, jis->hostname);
|
||||||
ssh_options_set(jump_session, SSH_OPTIONS_USER, jis->username);
|
ssh_options_set(jump_session, SSH_OPTIONS_USER, jis->username);
|
||||||
ssh_options_set(jump_session, SSH_OPTIONS_PORT, &jis->port);
|
ssh_options_set(jump_session, SSH_OPTIONS_PORT, &jis->port);
|
||||||
|
|
||||||
/* Pop the callbacks for the current jump */
|
if (cb != NULL && cb->before_connection != NULL) {
|
||||||
cb = ssh_list_pop_head(struct ssh_jump_callbacks_struct *,
|
|
||||||
jump_session->opts.proxy_jumps_user_cb);
|
|
||||||
|
|
||||||
if (cb != 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));
|
||||||
@@ -1333,6 +1311,13 @@ jump_thread_func(void *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SSH_LOG(SSH_LOG_PACKET,
|
||||||
|
"Proxy connecting to host %s port %d user %s, callbacks=%p",
|
||||||
|
jis->hostname,
|
||||||
|
jis->port,
|
||||||
|
jis->username,
|
||||||
|
(void *)cb);
|
||||||
|
|
||||||
/* If there are more jumps then this will make a new thread and call the
|
/* If there are more jumps then this will make a new thread and call the
|
||||||
* current function again, until there are no jumps. When there are no jumps
|
* current function again, until there are no jumps. When there are no jumps
|
||||||
* it connects normally. */
|
* it connects normally. */
|
||||||
@@ -1423,36 +1408,42 @@ exit:
|
|||||||
ssh_event_remove_connector(event, connector_out);
|
ssh_event_remove_connector(event, connector_out);
|
||||||
ssh_connector_free(connector_out);
|
ssh_connector_free(connector_out);
|
||||||
}
|
}
|
||||||
SAFE_FREE(next_hostname);
|
|
||||||
if (jis != NULL) {
|
|
||||||
SAFE_FREE(jis->hostname);
|
|
||||||
SAFE_FREE(jis->username);
|
|
||||||
}
|
|
||||||
SAFE_FREE(jis);
|
|
||||||
|
|
||||||
ssh_disconnect(jump_session);
|
ssh_disconnect(jump_session);
|
||||||
ssh_event_free(event);
|
ssh_event_free(event);
|
||||||
ssh_free(jump_session);
|
|
||||||
|
|
||||||
shutdown(jump_thread_data->fd, SHUT_RDWR);
|
shutdown(jump_thread_data->fd, SHUT_RDWR);
|
||||||
close(jump_thread_data->fd);
|
close(jump_thread_data->fd);
|
||||||
SAFE_FREE(jump_thread_data);
|
|
||||||
|
|
||||||
|
free_jump_thread_data(jump_thread_data);
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ssh_socket_connect_proxyjump(ssh_socket s)
|
ssh_socket_connect_proxyjump(ssh_socket s)
|
||||||
{
|
{
|
||||||
|
char err_msg[SSH_ERRNO_MSG_MAX] = {0};
|
||||||
ssh_poll_handle h = NULL;
|
ssh_poll_handle h = NULL;
|
||||||
int rc;
|
int rc;
|
||||||
pthread_t jump_thread;
|
pthread_t jump_thread;
|
||||||
|
struct ssh_jump_info_struct *jis = NULL;
|
||||||
|
struct ssh_jump_callbacks_struct *cb = NULL;
|
||||||
struct jump_thread_data_struct *jump_thread_data = NULL;
|
struct jump_thread_data_struct *jump_thread_data = NULL;
|
||||||
socket_t pair[2];
|
ssh_session jump_session = NULL, session = NULL;
|
||||||
|
struct ssh_list *empty_list = NULL;
|
||||||
|
socket_t pair[2] = {SSH_INVALID_SOCKET, SSH_INVALID_SOCKET};
|
||||||
|
|
||||||
|
session = s->session;
|
||||||
|
|
||||||
|
SSH_LOG(SSH_LOG_INFO,
|
||||||
|
"Connecting to host %s port %d user %s through ProxyJump",
|
||||||
|
session->opts.host,
|
||||||
|
session->opts.port,
|
||||||
|
session->opts.username);
|
||||||
|
|
||||||
if (s->state != SSH_SOCKET_NONE) {
|
if (s->state != SSH_SOCKET_NONE) {
|
||||||
ssh_set_error(
|
ssh_set_error(
|
||||||
s->session,
|
session,
|
||||||
SSH_FATAL,
|
SSH_FATAL,
|
||||||
"ssh_socket_connect_proxyjump called on socket not unconnected");
|
"ssh_socket_connect_proxyjump called on socket not unconnected");
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
@@ -1460,50 +1451,100 @@ ssh_socket_connect_proxyjump(ssh_socket s)
|
|||||||
|
|
||||||
jump_thread_data = calloc(1, sizeof(struct jump_thread_data_struct));
|
jump_thread_data = calloc(1, sizeof(struct jump_thread_data_struct));
|
||||||
if (jump_thread_data == NULL) {
|
if (jump_thread_data == NULL) {
|
||||||
ssh_set_error_oom(s->session);
|
ssh_set_error_oom(session);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = socketpair(PF_UNIX, SOCK_STREAM, 0, pair);
|
rc = socketpair(PF_UNIX, SOCK_STREAM, 0, pair);
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
char err_msg[SSH_ERRNO_MSG_MAX] = {0};
|
ssh_set_error(session,
|
||||||
|
|
||||||
ssh_set_error(s->session,
|
|
||||||
SSH_FATAL,
|
SSH_FATAL,
|
||||||
"Creating socket pair failed: %s",
|
"Creating socket pair failed: %s",
|
||||||
ssh_strerror(errno, err_msg, SSH_ERRNO_MSG_MAX));
|
ssh_strerror(errno, err_msg, SSH_ERRNO_MSG_MAX));
|
||||||
SAFE_FREE(jump_thread_data);
|
goto fail;
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jump_thread_data->session = s->session;
|
jump_session = ssh_new();
|
||||||
|
if (jump_session == NULL) {
|
||||||
|
ssh_set_error_oom(session);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
jump_session->proxy_root = false;
|
||||||
|
/* Reset the global variable if it was previously 1 */
|
||||||
|
if (session->proxy_root) {
|
||||||
|
proxy_disconnect = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pop first jump that will be used by the following thread */
|
||||||
|
jis = ssh_list_pop_head(struct ssh_jump_info_struct *,
|
||||||
|
session->opts.proxy_jumps);
|
||||||
|
if (jis == NULL) {
|
||||||
|
SSH_LOG(SSH_LOG_WARN, "Inconsistent list of proxy jumps received");
|
||||||
|
ssh_free(jump_session);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
jump_thread_data->next_jump = jis;
|
||||||
|
/* Move remaining to the jump session without reallocation.
|
||||||
|
* The list in the new jump_session is just allocated so empty */
|
||||||
|
empty_list = jump_session->opts.proxy_jumps;
|
||||||
|
jump_session->opts.proxy_jumps = session->opts.proxy_jumps;
|
||||||
|
session->opts.proxy_jumps = empty_list;
|
||||||
|
|
||||||
|
/* Pop the callbacks for the first jump */
|
||||||
|
cb = ssh_list_pop_head(struct ssh_jump_callbacks_struct *,
|
||||||
|
session->opts.proxy_jumps_user_cb);
|
||||||
|
/* empty is ok */
|
||||||
|
jump_thread_data->next_cb = cb;
|
||||||
|
/* Move remaining to the jump session without reallocation.
|
||||||
|
* The list in the new jump_session is just allocated so empty */
|
||||||
|
empty_list = jump_session->opts.proxy_jumps_user_cb;
|
||||||
|
jump_session->opts.proxy_jumps_user_cb = session->opts.proxy_jumps_user_cb;
|
||||||
|
session->opts.proxy_jumps_user_cb = empty_list;
|
||||||
|
|
||||||
|
ssh_options_set(jump_session,
|
||||||
|
SSH_OPTIONS_LOG_VERBOSITY,
|
||||||
|
&session->common.log_verbosity);
|
||||||
|
|
||||||
|
jump_thread_data->next_port = session->opts.port;
|
||||||
|
jump_thread_data->next_hostname = strdup(session->opts.host);
|
||||||
|
|
||||||
jump_thread_data->fd = pair[0];
|
jump_thread_data->fd = pair[0];
|
||||||
|
pair[0] = SSH_INVALID_SOCKET;
|
||||||
|
jump_thread_data->session = jump_session;
|
||||||
|
/* transferred to the jump_thread_data */
|
||||||
|
jump_session = NULL;
|
||||||
|
|
||||||
|
SSH_LOG(SSH_LOG_INFO,
|
||||||
|
"Starting proxy thread to host %s port %d user %s, callbacks=%p",
|
||||||
|
jump_thread_data->next_jump->hostname,
|
||||||
|
jump_thread_data->next_jump->port,
|
||||||
|
jump_thread_data->next_jump->username,
|
||||||
|
(void *)jump_thread_data->next_cb);
|
||||||
|
|
||||||
rc = pthread_create(&jump_thread, NULL, jump_thread_func, jump_thread_data);
|
rc = pthread_create(&jump_thread, NULL, jump_thread_func, jump_thread_data);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
char err_msg[SSH_ERRNO_MSG_MAX] = {0};
|
ssh_set_error(session,
|
||||||
|
|
||||||
ssh_set_error(s->session,
|
|
||||||
SSH_FATAL,
|
SSH_FATAL,
|
||||||
"Creating new thread failed: %s",
|
"Creating new thread failed: %s",
|
||||||
ssh_strerror(rc, err_msg, SSH_ERRNO_MSG_MAX));
|
ssh_strerror(rc, err_msg, SSH_ERRNO_MSG_MAX));
|
||||||
SAFE_FREE(jump_thread_data);
|
goto fail;
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
}
|
||||||
|
/* ownership passed to the thread */
|
||||||
|
jump_thread_data = NULL;
|
||||||
|
|
||||||
rc = pthread_detach(jump_thread);
|
rc = pthread_detach(jump_thread);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
char err_msg[SSH_ERRNO_MSG_MAX] = {0};
|
ssh_set_error(session,
|
||||||
|
|
||||||
ssh_set_error(s->session,
|
|
||||||
SSH_FATAL,
|
SSH_FATAL,
|
||||||
"Failed to detach thread: %s",
|
"Failed to detach thread: %s",
|
||||||
ssh_strerror(rc, err_msg, SSH_ERRNO_MSG_MAX));
|
ssh_strerror(rc, err_msg, SSH_ERRNO_MSG_MAX));
|
||||||
SAFE_FREE(jump_thread_data);
|
goto fail;
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SSH_LOG(SSH_LOG_DEBUG,
|
SSH_LOG(SSH_LOG_DEBUG,
|
||||||
"ProxyJump connection pipe: [%d,%d]",
|
"ProxyJump connection thread %lu started pipe: [%d,%d]",
|
||||||
|
(unsigned long)jump_thread,
|
||||||
pair[0],
|
pair[0],
|
||||||
pair[1]);
|
pair[1]);
|
||||||
|
|
||||||
@@ -1511,6 +1552,7 @@ ssh_socket_connect_proxyjump(ssh_socket s)
|
|||||||
if (rc != SSH_OK) {
|
if (rc != SSH_OK) {
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
pair[1] = SSH_INVALID_SOCKET;
|
||||||
|
|
||||||
s->fd_is_socket = 1;
|
s->fd_is_socket = 1;
|
||||||
h = ssh_socket_get_poll_handle(s);
|
h = ssh_socket_get_poll_handle(s);
|
||||||
@@ -1525,6 +1567,16 @@ ssh_socket_connect_proxyjump(ssh_socket s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (pair[0] != SSH_INVALID_SOCKET) {
|
||||||
|
close(pair[0]);
|
||||||
|
}
|
||||||
|
if (pair[1] != SSH_INVALID_SOCKET) {
|
||||||
|
close(pair[1]);
|
||||||
|
}
|
||||||
|
free_jump_thread_data(jump_thread_data);
|
||||||
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* HAVE_PTHREAD */
|
#endif /* HAVE_PTHREAD */
|
||||||
|
|||||||
@@ -394,6 +394,7 @@ if (CLIENT_TESTING OR SERVER_TESTING)
|
|||||||
# Allow to auth with bob's public keys on alice and doe account
|
# Allow to auth with bob's public keys on alice and doe account
|
||||||
configure_file(keys/id_rsa.pub ${CMAKE_CURRENT_BINARY_DIR}/home/alice/.ssh/authorized_keys @ONLY)
|
configure_file(keys/id_rsa.pub ${CMAKE_CURRENT_BINARY_DIR}/home/alice/.ssh/authorized_keys @ONLY)
|
||||||
configure_file(keys/id_rsa.pub ${CMAKE_CURRENT_BINARY_DIR}/home/doe/.ssh/authorized_keys @ONLY)
|
configure_file(keys/id_rsa.pub ${CMAKE_CURRENT_BINARY_DIR}/home/doe/.ssh/authorized_keys @ONLY)
|
||||||
|
configure_file(keys/id_ecdsa.pub ${CMAKE_CURRENT_BINARY_DIR}/home/frank/.ssh/authorized_keys @ONLY)
|
||||||
|
|
||||||
# append ECDSA public key
|
# append ECDSA public key
|
||||||
file(READ keys/id_ecdsa.pub CONTENTS)
|
file(READ keys/id_ecdsa.pub CONTENTS)
|
||||||
@@ -418,6 +419,9 @@ if (CLIENT_TESTING OR SERVER_TESTING)
|
|||||||
file(READ keys/pkcs11/id_pkcs11_ecdsa_256_openssh.pub CONTENTS)
|
file(READ keys/pkcs11/id_pkcs11_ecdsa_256_openssh.pub CONTENTS)
|
||||||
file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/home/charlie/.ssh/authorized_keys "${CONTENTS}")
|
file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/home/charlie/.ssh/authorized_keys "${CONTENTS}")
|
||||||
|
|
||||||
|
# Create home directory for noneuser (for "none" authentication test)
|
||||||
|
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/home/noneuser/.ssh)
|
||||||
|
|
||||||
file(READ keys/pkcs11/id_pkcs11_ecdsa_384_openssh.pub CONTENTS)
|
file(READ keys/pkcs11/id_pkcs11_ecdsa_384_openssh.pub CONTENTS)
|
||||||
file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/home/charlie/.ssh/authorized_keys "${CONTENTS}")
|
file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/home/charlie/.ssh/authorized_keys "${CONTENTS}")
|
||||||
|
|
||||||
|
|||||||
@@ -228,6 +228,44 @@ static void torture_auth_none_max_tries(void **state) {
|
|||||||
torture_update_sshd_config(state, "");
|
torture_update_sshd_config(state, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void torture_auth_none_success(void **state)
|
||||||
|
{
|
||||||
|
struct torture_state *s = *state;
|
||||||
|
const char *additional_config = "PermitEmptyPasswords yes\n"
|
||||||
|
"PasswordAuthentication yes\n"
|
||||||
|
"KbdInteractiveAuthentication no\n"
|
||||||
|
"PubkeyAuthentication no\n"
|
||||||
|
"AuthenticationMethods none\n";
|
||||||
|
|
||||||
|
ssh_session session = s->ssh.session;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
torture_update_sshd_config(state, additional_config);
|
||||||
|
|
||||||
|
/* Use noneuser which has an empty password set in shadow.in
|
||||||
|
* When PermitEmptyPasswords is yes and PasswordAuthentication is yes,
|
||||||
|
* OpenSSH's userauth_none() internally calls mm_auth_password() with
|
||||||
|
* an empty password, which succeeds for users with empty passwords.
|
||||||
|
*/
|
||||||
|
rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_NONEUSER);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_connect(session);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_userauth_none(session, NULL);
|
||||||
|
assert_int_equal(rc, SSH_AUTH_SUCCESS);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
torture_update_sshd_config(state, "");
|
||||||
|
if (rc != SSH_OK && rc != SSH_AUTH_SUCCESS) {
|
||||||
|
assert_int_equal(rc, SSH_OK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void torture_auth_pubkey(void **state) {
|
static void torture_auth_pubkey(void **state) {
|
||||||
struct torture_state *s = *state;
|
struct torture_state *s = *state;
|
||||||
@@ -376,7 +414,7 @@ torture_auth_autopubkey_protected_auth_function (const char *prompt, char *buf,
|
|||||||
assert_int_equal(echo, 0);
|
assert_int_equal(echo, 0);
|
||||||
assert_int_equal(verify, 0);
|
assert_int_equal(verify, 0);
|
||||||
|
|
||||||
expected_id = ssh_path_expand_escape(data->session, "%d/id_rsa_protected");
|
expected_id = ssh_path_expand_escape(data->session, "%d/.ssh/id_rsa_protected");
|
||||||
assert_true(expected_id != NULL);
|
assert_true(expected_id != NULL);
|
||||||
|
|
||||||
rc = ssh_userauth_publickey_auto_get_current_identity(data->session, &id);
|
rc = ssh_userauth_publickey_auto_get_current_identity(data->session, &id);
|
||||||
@@ -429,7 +467,7 @@ static void torture_auth_autopubkey_protected(void **state) {
|
|||||||
|
|
||||||
/* Try id_rsa_protected first.
|
/* Try id_rsa_protected first.
|
||||||
*/
|
*/
|
||||||
rc = ssh_options_set(session, SSH_OPTIONS_IDENTITY, "%d/id_rsa_protected");
|
rc = ssh_options_set(session, SSH_OPTIONS_IDENTITY, "%d/.ssh/id_rsa_protected");
|
||||||
assert_int_equal(rc, SSH_OK);
|
assert_int_equal(rc, SSH_OK);
|
||||||
|
|
||||||
rc = ssh_connect(session);
|
rc = ssh_connect(session);
|
||||||
@@ -1373,6 +1411,9 @@ int torture_run_tests(void) {
|
|||||||
cmocka_unit_test_setup_teardown(torture_auth_none_nonblocking,
|
cmocka_unit_test_setup_teardown(torture_auth_none_nonblocking,
|
||||||
session_setup,
|
session_setup,
|
||||||
session_teardown),
|
session_teardown),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_auth_none_success,
|
||||||
|
session_setup,
|
||||||
|
session_teardown),
|
||||||
cmocka_unit_test_setup_teardown(torture_auth_none_max_tries,
|
cmocka_unit_test_setup_teardown(torture_auth_none_max_tries,
|
||||||
session_setup,
|
session_setup,
|
||||||
session_teardown),
|
session_teardown),
|
||||||
@@ -1424,7 +1465,8 @@ int torture_run_tests(void) {
|
|||||||
cmocka_unit_test_setup_teardown(torture_auth_agent_identities_only,
|
cmocka_unit_test_setup_teardown(torture_auth_agent_identities_only,
|
||||||
agent_setup,
|
agent_setup,
|
||||||
agent_teardown),
|
agent_teardown),
|
||||||
cmocka_unit_test_setup_teardown(torture_auth_agent_identities_only_protected,
|
cmocka_unit_test_setup_teardown(
|
||||||
|
torture_auth_agent_identities_only_protected,
|
||||||
agent_setup,
|
agent_setup,
|
||||||
agent_teardown),
|
agent_teardown),
|
||||||
cmocka_unit_test_setup_teardown(torture_auth_pubkey_types,
|
cmocka_unit_test_setup_teardown(torture_auth_pubkey_types,
|
||||||
@@ -1436,13 +1478,15 @@ int torture_run_tests(void) {
|
|||||||
cmocka_unit_test_setup_teardown(torture_auth_pubkey_types_ecdsa,
|
cmocka_unit_test_setup_teardown(torture_auth_pubkey_types_ecdsa,
|
||||||
pubkey_setup,
|
pubkey_setup,
|
||||||
session_teardown),
|
session_teardown),
|
||||||
cmocka_unit_test_setup_teardown(torture_auth_pubkey_types_ecdsa_nonblocking,
|
cmocka_unit_test_setup_teardown(
|
||||||
|
torture_auth_pubkey_types_ecdsa_nonblocking,
|
||||||
pubkey_setup,
|
pubkey_setup,
|
||||||
session_teardown),
|
session_teardown),
|
||||||
cmocka_unit_test_setup_teardown(torture_auth_pubkey_types_ed25519,
|
cmocka_unit_test_setup_teardown(torture_auth_pubkey_types_ed25519,
|
||||||
pubkey_setup,
|
pubkey_setup,
|
||||||
session_teardown),
|
session_teardown),
|
||||||
cmocka_unit_test_setup_teardown(torture_auth_pubkey_types_ed25519_nonblocking,
|
cmocka_unit_test_setup_teardown(
|
||||||
|
torture_auth_pubkey_types_ed25519_nonblocking,
|
||||||
pubkey_setup,
|
pubkey_setup,
|
||||||
session_teardown),
|
session_teardown),
|
||||||
#ifdef WITH_FIDO2
|
#ifdef WITH_FIDO2
|
||||||
@@ -1456,7 +1500,8 @@ int torture_run_tests(void) {
|
|||||||
cmocka_unit_test_setup_teardown(torture_auth_pubkey_rsa_key_size,
|
cmocka_unit_test_setup_teardown(torture_auth_pubkey_rsa_key_size,
|
||||||
pubkey_setup,
|
pubkey_setup,
|
||||||
session_teardown),
|
session_teardown),
|
||||||
cmocka_unit_test_setup_teardown(torture_auth_pubkey_rsa_key_size_nonblocking,
|
cmocka_unit_test_setup_teardown(
|
||||||
|
torture_auth_pubkey_rsa_key_size_nonblocking,
|
||||||
pubkey_setup,
|
pubkey_setup,
|
||||||
session_teardown),
|
session_teardown),
|
||||||
cmocka_unit_test_setup_teardown(torture_auth_pubkey_skip_none,
|
cmocka_unit_test_setup_teardown(torture_auth_pubkey_skip_none,
|
||||||
|
|||||||
@@ -100,13 +100,10 @@ static int session_setup(void **state)
|
|||||||
static int session_setup_ssh_dir(void **state)
|
static int session_setup_ssh_dir(void **state)
|
||||||
{
|
{
|
||||||
struct torture_state *s = *state;
|
struct torture_state *s = *state;
|
||||||
const char *no_home = "~/.no_ssh";
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
session_setup(state);
|
session_setup(state);
|
||||||
|
|
||||||
rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_SSH_DIR, no_home);
|
s->ssh.session->opts.homedir = strdup("~/.no_ssh");
|
||||||
assert_ssh_return_code(s->ssh.session, rc);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "torture.h"
|
#include "torture.h"
|
||||||
#include "libssh/session.h"
|
#include "libssh/session.h"
|
||||||
|
#include "libssh/options.h"
|
||||||
#include "libssh/misc.h"
|
#include "libssh/misc.h"
|
||||||
|
|
||||||
#define LIBSSH_SSH_CONFIG "libssh_config"
|
#define LIBSSH_SSH_CONFIG "libssh_config"
|
||||||
@@ -59,6 +60,23 @@ static int setup_config_files(void **state)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int setup_session(void **state)
|
||||||
|
{
|
||||||
|
struct torture_state *s = *state;
|
||||||
|
int verbosity;
|
||||||
|
|
||||||
|
s->ssh.session = ssh_new();
|
||||||
|
assert_non_null(s->ssh.session);
|
||||||
|
|
||||||
|
verbosity = torture_libssh_verbosity();
|
||||||
|
ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
|
||||||
|
ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER);
|
||||||
|
|
||||||
|
setenv("NSS_WRAPPER_HOSTNAME", "client.libssh.site", 1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int teardown(void **state)
|
static int teardown(void **state)
|
||||||
{
|
{
|
||||||
struct torture_state *s = *state;
|
struct torture_state *s = *state;
|
||||||
@@ -80,6 +98,16 @@ static int teardown(void **state)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int teardown_session(void **state)
|
||||||
|
{
|
||||||
|
struct torture_state *s = *state;
|
||||||
|
|
||||||
|
ssh_disconnect(s->ssh.session);
|
||||||
|
ssh_free(s->ssh.session);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* This tests makes sure that parsing both system-wide and per-user
|
/* This tests makes sure that parsing both system-wide and per-user
|
||||||
* configuration files retains OpenSSH semantics (the per-user overrides
|
* configuration files retains OpenSSH semantics (the per-user overrides
|
||||||
* the system-wide values).
|
* the system-wide values).
|
||||||
@@ -210,10 +238,233 @@ static void torture_client_config_suppress(void **state)
|
|||||||
assert_string_equal(s->ssh.session->opts.username, "bob");
|
assert_string_equal(s->ssh.session->opts.username, "bob");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void torture_client_config_expand_bad(void **state)
|
||||||
|
{
|
||||||
|
ssh_session session = ssh_new();
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
(void)state;
|
||||||
|
|
||||||
|
assert_non_null(session);
|
||||||
|
|
||||||
|
/* The hash without host fails, but does not crash */
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, "%C");
|
||||||
|
|
||||||
|
ret = ssh_options_apply(session);
|
||||||
|
assert_ssh_return_code_equal(session, ret, SSH_ERROR);
|
||||||
|
|
||||||
|
/* The hash without host fails, but does not crash */
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER);
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, "%C");
|
||||||
|
|
||||||
|
ret = ssh_options_apply(session);
|
||||||
|
assert_ssh_return_code_equal(session, ret, SSH_OK);
|
||||||
|
|
||||||
|
ssh_free(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void torture_client_config_expand(void **state)
|
||||||
|
{
|
||||||
|
struct torture_state *s = *state;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
/* TEST: user home directory */
|
||||||
|
ssh_options_set(s->ssh.session, SSH_OPTIONS_KNOWNHOSTS, "%d");
|
||||||
|
|
||||||
|
ret = ssh_options_apply(s->ssh.session);
|
||||||
|
assert_ssh_return_code(s->ssh.session, ret);
|
||||||
|
|
||||||
|
assert_string_equal(s->ssh.session->opts.knownhosts,
|
||||||
|
BINARYDIR "/tests/home");
|
||||||
|
|
||||||
|
/* Reset the flag so we can repeat the test */
|
||||||
|
s->ssh.session->opts.exp_flags &= ~SSH_OPT_EXP_FLAG_KNOWNHOSTS;
|
||||||
|
|
||||||
|
|
||||||
|
/* TEST: target host name */
|
||||||
|
ssh_options_set(s->ssh.session, SSH_OPTIONS_KNOWNHOSTS, "%h");
|
||||||
|
|
||||||
|
ret = ssh_options_apply(s->ssh.session);
|
||||||
|
assert_ssh_return_code(s->ssh.session, ret);
|
||||||
|
|
||||||
|
assert_string_equal(s->ssh.session->opts.knownhosts, TORTURE_SSH_SERVER);
|
||||||
|
|
||||||
|
/* Reset the flag so we can repeat the test */
|
||||||
|
s->ssh.session->opts.exp_flags &= ~SSH_OPT_EXP_FLAG_KNOWNHOSTS;
|
||||||
|
|
||||||
|
|
||||||
|
/* TEST: local username */
|
||||||
|
ssh_options_set(s->ssh.session, SSH_OPTIONS_KNOWNHOSTS, "%u");
|
||||||
|
|
||||||
|
ret = ssh_options_apply(s->ssh.session);
|
||||||
|
assert_ssh_return_code(s->ssh.session, ret);
|
||||||
|
|
||||||
|
assert_string_equal(s->ssh.session->opts.knownhosts, "root");
|
||||||
|
|
||||||
|
/* Reset the flag so we can repeat the test */
|
||||||
|
s->ssh.session->opts.exp_flags &= ~SSH_OPT_EXP_FLAG_KNOWNHOSTS;
|
||||||
|
|
||||||
|
|
||||||
|
/* TEST: local hostname */
|
||||||
|
ssh_options_set(s->ssh.session, SSH_OPTIONS_KNOWNHOSTS, "%l");
|
||||||
|
|
||||||
|
ret = ssh_options_apply(s->ssh.session);
|
||||||
|
assert_ssh_return_code(s->ssh.session, ret);
|
||||||
|
|
||||||
|
assert_string_equal(s->ssh.session->opts.knownhosts, "client.libssh.site");
|
||||||
|
|
||||||
|
/* Reset the flag so we can repeat the test */
|
||||||
|
s->ssh.session->opts.exp_flags &= ~SSH_OPT_EXP_FLAG_KNOWNHOSTS;
|
||||||
|
|
||||||
|
|
||||||
|
/* TEST: remote username */
|
||||||
|
ssh_options_set(s->ssh.session, SSH_OPTIONS_USER, "alice");
|
||||||
|
ssh_options_set(s->ssh.session, SSH_OPTIONS_KNOWNHOSTS, "%r");
|
||||||
|
|
||||||
|
ret = ssh_options_apply(s->ssh.session);
|
||||||
|
assert_ssh_return_code(s->ssh.session, ret);
|
||||||
|
|
||||||
|
assert_string_equal(s->ssh.session->opts.knownhosts, "alice");
|
||||||
|
|
||||||
|
/* Reset the flag so we can repeat the test */
|
||||||
|
s->ssh.session->opts.exp_flags &= ~SSH_OPT_EXP_FLAG_KNOWNHOSTS;
|
||||||
|
|
||||||
|
|
||||||
|
/* TEST: remote port */
|
||||||
|
ssh_options_set(s->ssh.session, SSH_OPTIONS_PORT_STR, "2222");
|
||||||
|
ssh_options_set(s->ssh.session, SSH_OPTIONS_KNOWNHOSTS, "%p");
|
||||||
|
|
||||||
|
ret = ssh_options_apply(s->ssh.session);
|
||||||
|
assert_ssh_return_code(s->ssh.session, ret);
|
||||||
|
|
||||||
|
assert_string_equal(s->ssh.session->opts.knownhosts, "2222");
|
||||||
|
|
||||||
|
/* Reset the flag so we can repeat the test */
|
||||||
|
s->ssh.session->opts.exp_flags &= ~SSH_OPT_EXP_FLAG_KNOWNHOSTS;
|
||||||
|
|
||||||
|
|
||||||
|
/* TEST: empty proxyjump */
|
||||||
|
ssh_options_set(s->ssh.session, SSH_OPTIONS_KNOWNHOSTS, "%j");
|
||||||
|
|
||||||
|
ret = ssh_options_apply(s->ssh.session);
|
||||||
|
assert_ssh_return_code(s->ssh.session, ret);
|
||||||
|
|
||||||
|
/* No proxyjump string should not explode */
|
||||||
|
assert_string_equal(s->ssh.session->opts.knownhosts, "");
|
||||||
|
|
||||||
|
/* Reset the flag so we can repeat the test */
|
||||||
|
s->ssh.session->opts.exp_flags &= ~SSH_OPT_EXP_FLAG_KNOWNHOSTS;
|
||||||
|
|
||||||
|
|
||||||
|
/* TEST: proxyjump string present */
|
||||||
|
ssh_options_set(s->ssh.session, SSH_OPTIONS_KNOWNHOSTS, "%j");
|
||||||
|
ssh_options_set(s->ssh.session,
|
||||||
|
SSH_OPTIONS_PROXYJUMP,
|
||||||
|
"user@" TORTURE_SSH_SERVER ":22");
|
||||||
|
|
||||||
|
ret = ssh_options_apply(s->ssh.session);
|
||||||
|
assert_ssh_return_code(s->ssh.session, ret);
|
||||||
|
|
||||||
|
assert_string_equal(s->ssh.session->opts.knownhosts,
|
||||||
|
"user@" TORTURE_SSH_SERVER ":22");
|
||||||
|
|
||||||
|
/* Reset the flag so we can repeat the test */
|
||||||
|
s->ssh.session->opts.exp_flags &= ~SSH_OPT_EXP_FLAG_KNOWNHOSTS;
|
||||||
|
|
||||||
|
|
||||||
|
/* TEST: separate list %l-%h-%p-%r-%j with empty ProxyJump */
|
||||||
|
ssh_options_set(s->ssh.session, SSH_OPTIONS_KNOWNHOSTS, "%l-%h-%p-%r-%j");
|
||||||
|
ssh_options_set(s->ssh.session, SSH_OPTIONS_PROXYJUMP, "none");
|
||||||
|
ssh_options_set(s->ssh.session, SSH_OPTIONS_PORT_STR, "22");
|
||||||
|
|
||||||
|
ret = ssh_options_apply(s->ssh.session);
|
||||||
|
assert_ssh_return_code(s->ssh.session, ret);
|
||||||
|
|
||||||
|
// Tested by
|
||||||
|
// ret = system(SSH_EXECUTABLE
|
||||||
|
// " -p 22 -o UserKnownHostsFile=/dev/null"
|
||||||
|
// " -o KnownHostsCommand='/bin/touch \"/tmp/%l-%h-%p-%r-%j\"'"
|
||||||
|
// " alice@" TORTURE_SSH_SERVER);
|
||||||
|
// assert_return_code(ret, errno);
|
||||||
|
assert_string_equal(s->ssh.session->opts.knownhosts,
|
||||||
|
"client.libssh.site-127.0.0.10-22-alice-");
|
||||||
|
|
||||||
|
|
||||||
|
/* TEST: hash of %l%h%p%r%j with empty ProxyJump */
|
||||||
|
ssh_options_set(s->ssh.session, SSH_OPTIONS_KNOWNHOSTS, "%C");
|
||||||
|
|
||||||
|
ret = ssh_options_apply(s->ssh.session);
|
||||||
|
assert_ssh_return_code(s->ssh.session, ret);
|
||||||
|
|
||||||
|
// Tested by
|
||||||
|
// ret = system(SSH_EXECUTABLE
|
||||||
|
// " -p 22 -o UserKnownHostsFile=/dev/null"
|
||||||
|
// " -o KnownHostsCommand='/bin/touch \"/tmp/%C\"'"
|
||||||
|
// " alice@" TORTURE_SSH_SERVER);
|
||||||
|
// assert_return_code(ret, errno);
|
||||||
|
assert_string_equal(s->ssh.session->opts.knownhosts,
|
||||||
|
"133e3957ff9d01fdcf1f6c7f83325a8ce49bf850");
|
||||||
|
|
||||||
|
/* Reset the flag so we can repeat the test */
|
||||||
|
s->ssh.session->opts.exp_flags &= ~SSH_OPT_EXP_FLAG_KNOWNHOSTS;
|
||||||
|
|
||||||
|
|
||||||
|
/* TEST: separate list %l-%h-%p-%r-%j */
|
||||||
|
ssh_options_set(s->ssh.session, SSH_OPTIONS_KNOWNHOSTS, "%l-%h-%p-%r-%j");
|
||||||
|
ssh_options_set(s->ssh.session,
|
||||||
|
SSH_OPTIONS_PROXYJUMP,
|
||||||
|
"user@" TORTURE_SSH_SERVER ":22");
|
||||||
|
|
||||||
|
ret = ssh_options_apply(s->ssh.session);
|
||||||
|
assert_ssh_return_code(s->ssh.session, ret);
|
||||||
|
|
||||||
|
// Tested by
|
||||||
|
// ret = system(SSH_EXECUTABLE
|
||||||
|
// " -p 22 -oProxyJump=user@" TORTURE_SSH_SERVER ":22"
|
||||||
|
// " -o UserKnownHostsFile=/dev/null"
|
||||||
|
// " -o KnownHostsCommand='/bin/touch \"/tmp/%l-%h-%p-%r-%j\"'"
|
||||||
|
// " alice@" TORTURE_SSH_SERVER);
|
||||||
|
// assert_return_code(ret, errno);
|
||||||
|
assert_string_equal(s->ssh.session->opts.knownhosts,
|
||||||
|
"client.libssh.site-127.0.0.10-22-alice-user@"
|
||||||
|
TORTURE_SSH_SERVER ":22");
|
||||||
|
|
||||||
|
|
||||||
|
/* Reset the flag so we can repeat the test */
|
||||||
|
s->ssh.session->opts.exp_flags &= ~SSH_OPT_EXP_FLAG_KNOWNHOSTS;
|
||||||
|
|
||||||
|
|
||||||
|
/* TEST: hash of %l%h%p%r%j */
|
||||||
|
ssh_options_set(s->ssh.session, SSH_OPTIONS_KNOWNHOSTS, "%C");
|
||||||
|
|
||||||
|
ret = ssh_options_apply(s->ssh.session);
|
||||||
|
assert_ssh_return_code(s->ssh.session, ret);
|
||||||
|
|
||||||
|
// Tested by
|
||||||
|
// ret = system(SSH_EXECUTABLE
|
||||||
|
// " -p 22 -oProxyJump=user@" TORTURE_SSH_SERVER ":22"
|
||||||
|
// " -o UserKnownHostsFile=/dev/null"
|
||||||
|
// " -o KnownHostsCommand='/bin/touch \"/tmp/%C\"'"
|
||||||
|
// " alice@" TORTURE_SSH_SERVER);
|
||||||
|
// assert_return_code(ret, errno);
|
||||||
|
assert_string_equal(s->ssh.session->opts.knownhosts,
|
||||||
|
"adf0b7c4e71a0fee85fd97506507ba8591f3663b");
|
||||||
|
|
||||||
|
/* Reset the flag so we can repeat the test */
|
||||||
|
s->ssh.session->opts.exp_flags &= ~SSH_OPT_EXP_FLAG_KNOWNHOSTS;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int torture_run_tests(void) {
|
int torture_run_tests(void) {
|
||||||
int rc;
|
int rc;
|
||||||
struct CMUnitTest tests[] = {
|
struct CMUnitTest tests[] = {
|
||||||
|
/* Keep these first -- following setup is changing user to bob, which we
|
||||||
|
* do not want */
|
||||||
|
cmocka_unit_test(torture_client_config_expand_bad),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_client_config_expand,
|
||||||
|
setup_session,
|
||||||
|
teardown_session),
|
||||||
cmocka_unit_test_setup_teardown(torture_client_config_system,
|
cmocka_unit_test_setup_teardown(torture_client_config_system,
|
||||||
setup_config_files,
|
setup_config_files,
|
||||||
teardown),
|
teardown),
|
||||||
@@ -228,7 +479,6 @@ int torture_run_tests(void) {
|
|||||||
teardown),
|
teardown),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
ssh_init();
|
ssh_init();
|
||||||
torture_filter_tests(tests);
|
torture_filter_tests(tests);
|
||||||
rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown);
|
rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown);
|
||||||
|
|||||||
@@ -121,6 +121,50 @@ static int authenticate(ssh_session jump_session, void *user)
|
|||||||
return ssh_userauth_publickey_auto(jump_session, NULL, NULL);
|
return ssh_userauth_publickey_auto(jump_session, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int authenticate_doe(ssh_session jump_session, void *user)
|
||||||
|
{
|
||||||
|
ssh_key pkey = NULL;
|
||||||
|
char bob_ssh_key[1024];
|
||||||
|
struct passwd *pwd = NULL;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
(void)user;
|
||||||
|
|
||||||
|
pwd = getpwnam("bob");
|
||||||
|
assert_non_null(pwd);
|
||||||
|
|
||||||
|
snprintf(bob_ssh_key, sizeof(bob_ssh_key), "%s/.ssh/id_rsa", pwd->pw_dir);
|
||||||
|
|
||||||
|
rc = ssh_pki_import_privkey_file(bob_ssh_key, NULL, NULL, NULL, &pkey);
|
||||||
|
assert_int_equal(rc, SSH_OK);
|
||||||
|
|
||||||
|
rc = ssh_userauth_publickey(jump_session, NULL, pkey);
|
||||||
|
ssh_key_free(pkey);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int authenticate_frank(ssh_session jump_session, void *user)
|
||||||
|
{
|
||||||
|
ssh_key pkey = NULL;
|
||||||
|
char bob_ssh_key[1024];
|
||||||
|
struct passwd *pwd = NULL;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
(void)user;
|
||||||
|
|
||||||
|
pwd = getpwnam("bob");
|
||||||
|
assert_non_null(pwd);
|
||||||
|
|
||||||
|
snprintf(bob_ssh_key, sizeof(bob_ssh_key), "%s/.ssh/id_ecdsa", pwd->pw_dir);
|
||||||
|
|
||||||
|
rc = ssh_pki_import_privkey_file(bob_ssh_key, NULL, NULL, NULL, &pkey);
|
||||||
|
assert_int_equal(rc, SSH_OK);
|
||||||
|
|
||||||
|
rc = ssh_userauth_publickey(jump_session, NULL, pkey);
|
||||||
|
ssh_key_free(pkey);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static void torture_proxyjump_multiple_jump(void **state)
|
static void torture_proxyjump_multiple_jump(void **state)
|
||||||
{
|
{
|
||||||
struct torture_state *s = *state;
|
struct torture_state *s = *state;
|
||||||
@@ -129,11 +173,10 @@ static void torture_proxyjump_multiple_jump(void **state)
|
|||||||
const char *address = torture_server_address(AF_INET);
|
const char *address = torture_server_address(AF_INET);
|
||||||
int rc;
|
int rc;
|
||||||
socket_t fd;
|
socket_t fd;
|
||||||
|
|
||||||
struct ssh_jump_callbacks_struct c = {
|
struct ssh_jump_callbacks_struct c = {
|
||||||
.before_connection = before_connection,
|
.before_connection = before_connection,
|
||||||
.verify_knownhost = verify_knownhost,
|
.verify_knownhost = verify_knownhost,
|
||||||
.authenticate = authenticate
|
.authenticate = authenticate,
|
||||||
};
|
};
|
||||||
|
|
||||||
rc = snprintf(proxyjump_buf,
|
rc = snprintf(proxyjump_buf,
|
||||||
@@ -177,14 +220,14 @@ static void torture_proxyjump_multiple_sshd_jump(void **state)
|
|||||||
struct ssh_jump_callbacks_struct c = {
|
struct ssh_jump_callbacks_struct c = {
|
||||||
.before_connection = before_connection,
|
.before_connection = before_connection,
|
||||||
.verify_knownhost = verify_knownhost,
|
.verify_knownhost = verify_knownhost,
|
||||||
.authenticate = authenticate,
|
.authenticate = authenticate_doe,
|
||||||
};
|
};
|
||||||
|
|
||||||
torture_setup_sshd_servers(state, false);
|
torture_setup_sshd_servers(state, false);
|
||||||
|
|
||||||
rc = snprintf(proxyjump_buf,
|
rc = snprintf(proxyjump_buf,
|
||||||
sizeof(proxyjump_buf),
|
sizeof(proxyjump_buf),
|
||||||
"alice@%s:22,alice@%s:22",
|
"doe@%s:22,doe@%s:22",
|
||||||
address,
|
address,
|
||||||
address1);
|
address1);
|
||||||
if (rc < 0 || rc >= (int)sizeof(proxyjump_buf)) {
|
if (rc < 0 || rc >= (int)sizeof(proxyjump_buf)) {
|
||||||
@@ -222,17 +265,22 @@ static void torture_proxyjump_multiple_sshd_users_jump(void **state)
|
|||||||
int rc;
|
int rc;
|
||||||
socket_t fd;
|
socket_t fd;
|
||||||
|
|
||||||
struct ssh_jump_callbacks_struct c = {
|
struct ssh_jump_callbacks_struct c1 = {
|
||||||
.before_connection = before_connection,
|
.before_connection = before_connection,
|
||||||
.verify_knownhost = verify_knownhost,
|
.verify_knownhost = verify_knownhost,
|
||||||
.authenticate = authenticate,
|
.authenticate = authenticate_doe,
|
||||||
|
};
|
||||||
|
struct ssh_jump_callbacks_struct c2 = {
|
||||||
|
.before_connection = before_connection,
|
||||||
|
.verify_knownhost = verify_knownhost,
|
||||||
|
.authenticate = authenticate_frank,
|
||||||
};
|
};
|
||||||
|
|
||||||
torture_setup_sshd_servers(state, false);
|
torture_setup_sshd_servers(state, false);
|
||||||
|
|
||||||
rc = snprintf(proxyjump_buf,
|
rc = snprintf(proxyjump_buf,
|
||||||
sizeof(proxyjump_buf),
|
sizeof(proxyjump_buf),
|
||||||
"doe@%s:22,alice@%s:22",
|
"doe@%s:22,frank@%s:22",
|
||||||
address,
|
address,
|
||||||
address1);
|
address1);
|
||||||
if (rc < 0 || rc >= (int)sizeof(proxyjump_buf)) {
|
if (rc < 0 || rc >= (int)sizeof(proxyjump_buf)) {
|
||||||
@@ -240,9 +288,9 @@ static void torture_proxyjump_multiple_sshd_users_jump(void **state)
|
|||||||
}
|
}
|
||||||
rc = ssh_options_set(session, SSH_OPTIONS_PROXYJUMP, proxyjump_buf);
|
rc = ssh_options_set(session, SSH_OPTIONS_PROXYJUMP, proxyjump_buf);
|
||||||
assert_ssh_return_code(session, rc);
|
assert_ssh_return_code(session, rc);
|
||||||
rc = ssh_options_set(session, SSH_OPTIONS_PROXYJUMP_CB_LIST_APPEND, &c);
|
rc = ssh_options_set(session, SSH_OPTIONS_PROXYJUMP_CB_LIST_APPEND, &c1);
|
||||||
assert_ssh_return_code(session, rc);
|
assert_ssh_return_code(session, rc);
|
||||||
rc = ssh_options_set(session, SSH_OPTIONS_PROXYJUMP_CB_LIST_APPEND, &c);
|
rc = ssh_options_set(session, SSH_OPTIONS_PROXYJUMP_CB_LIST_APPEND, &c2);
|
||||||
assert_ssh_return_code(session, rc);
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
rc = ssh_connect(session);
|
rc = ssh_connect(session);
|
||||||
|
|||||||
@@ -11,19 +11,37 @@
|
|||||||
|
|
||||||
#define MAX_XFER_BUF_SIZE 16384
|
#define MAX_XFER_BUF_SIZE 16384
|
||||||
|
|
||||||
|
#define DIRECT_AND_PROXYJUMP_SETUP_TEARDOWN(TEST_NAME) \
|
||||||
|
{ \
|
||||||
|
#TEST_NAME, \
|
||||||
|
TEST_NAME, \
|
||||||
|
session_setup, \
|
||||||
|
session_teardown, \
|
||||||
|
NULL \
|
||||||
|
}, \
|
||||||
|
{ \
|
||||||
|
#TEST_NAME"_proxyjump", \
|
||||||
|
TEST_NAME, \
|
||||||
|
session_proxyjump_setup, \
|
||||||
|
session_teardown, \
|
||||||
|
NULL \
|
||||||
|
}
|
||||||
|
|
||||||
static int sshd_setup(void **state)
|
static int sshd_setup(void **state)
|
||||||
{
|
{
|
||||||
torture_setup_sshd_server(state, false);
|
torture_setup_sshd_server(state, false);
|
||||||
|
torture_setup_sshd_servers(state, false);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sshd_teardown(void **state)
|
static int sshd_teardown(void **state)
|
||||||
{
|
{
|
||||||
|
/* this will take care of the server1 teardown too */
|
||||||
torture_teardown_sshd_server(state);
|
torture_teardown_sshd_server(state);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int session_setup(void **state)
|
static int session_setup_helper(void **state, bool with_proxyjump)
|
||||||
{
|
{
|
||||||
struct torture_state *s = *state;
|
struct torture_state *s = *state;
|
||||||
struct passwd *pwd = NULL;
|
struct passwd *pwd = NULL;
|
||||||
@@ -35,11 +53,15 @@ static int session_setup(void **state)
|
|||||||
rc = setuid(pwd->pw_uid);
|
rc = setuid(pwd->pw_uid);
|
||||||
assert_return_code(rc, errno);
|
assert_return_code(rc, errno);
|
||||||
|
|
||||||
|
if (with_proxyjump) {
|
||||||
|
s->ssh.session = torture_ssh_session_proxyjump();
|
||||||
|
} else {
|
||||||
s->ssh.session = torture_ssh_session(s,
|
s->ssh.session = torture_ssh_session(s,
|
||||||
TORTURE_SSH_SERVER,
|
TORTURE_SSH_SERVER,
|
||||||
NULL,
|
NULL,
|
||||||
TORTURE_SSH_USER_ALICE,
|
TORTURE_SSH_USER_ALICE,
|
||||||
NULL);
|
NULL);
|
||||||
|
}
|
||||||
assert_non_null(s->ssh.session);
|
assert_non_null(s->ssh.session);
|
||||||
|
|
||||||
s->ssh.tsftp = torture_sftp_session(s->ssh.session);
|
s->ssh.tsftp = torture_sftp_session(s->ssh.session);
|
||||||
@@ -48,6 +70,16 @@ static int session_setup(void **state)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int session_setup(void **state)
|
||||||
|
{
|
||||||
|
return session_setup_helper(state, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int session_proxyjump_setup(void **state)
|
||||||
|
{
|
||||||
|
return session_setup_helper(state, true);
|
||||||
|
}
|
||||||
|
|
||||||
static int session_teardown(void **state)
|
static int session_teardown(void **state)
|
||||||
{
|
{
|
||||||
struct torture_state *s = *state;
|
struct torture_state *s = *state;
|
||||||
@@ -722,37 +754,18 @@ int torture_run_tests(void)
|
|||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct CMUnitTest tests[] = {
|
struct CMUnitTest tests[] = {
|
||||||
cmocka_unit_test_setup_teardown(torture_sftp_aio_read_file,
|
DIRECT_AND_PROXYJUMP_SETUP_TEARDOWN(torture_sftp_aio_read_file),
|
||||||
session_setup,
|
DIRECT_AND_PROXYJUMP_SETUP_TEARDOWN(
|
||||||
session_teardown),
|
torture_sftp_aio_read_more_than_cap),
|
||||||
|
DIRECT_AND_PROXYJUMP_SETUP_TEARDOWN(torture_sftp_aio_write_file),
|
||||||
cmocka_unit_test_setup_teardown(torture_sftp_aio_read_more_than_cap,
|
DIRECT_AND_PROXYJUMP_SETUP_TEARDOWN(
|
||||||
session_setup,
|
torture_sftp_aio_write_more_than_cap),
|
||||||
session_teardown),
|
DIRECT_AND_PROXYJUMP_SETUP_TEARDOWN(torture_sftp_aio_read_negative),
|
||||||
|
DIRECT_AND_PROXYJUMP_SETUP_TEARDOWN(torture_sftp_aio_write_negative),
|
||||||
cmocka_unit_test_setup_teardown(torture_sftp_aio_write_file,
|
DIRECT_AND_PROXYJUMP_SETUP_TEARDOWN(
|
||||||
session_setup,
|
torture_sftp_aio_read_unordered_wait),
|
||||||
session_teardown),
|
DIRECT_AND_PROXYJUMP_SETUP_TEARDOWN(
|
||||||
|
torture_sftp_aio_write_unordered_wait),
|
||||||
cmocka_unit_test_setup_teardown(torture_sftp_aio_write_more_than_cap,
|
|
||||||
session_setup,
|
|
||||||
session_teardown),
|
|
||||||
|
|
||||||
cmocka_unit_test_setup_teardown(torture_sftp_aio_read_negative,
|
|
||||||
session_setup,
|
|
||||||
session_teardown),
|
|
||||||
|
|
||||||
cmocka_unit_test_setup_teardown(torture_sftp_aio_write_negative,
|
|
||||||
session_setup,
|
|
||||||
session_teardown),
|
|
||||||
|
|
||||||
cmocka_unit_test_setup_teardown(torture_sftp_aio_read_unordered_wait,
|
|
||||||
session_setup,
|
|
||||||
session_teardown),
|
|
||||||
|
|
||||||
cmocka_unit_test_setup_teardown(torture_sftp_aio_write_unordered_wait,
|
|
||||||
session_setup,
|
|
||||||
session_teardown),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ssh_init();
|
ssh_init();
|
||||||
|
|||||||
@@ -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,4 +2,4 @@ users:x:9000:
|
|||||||
sshd:x:65531:
|
sshd:x:65531:
|
||||||
nobody:x:65533:
|
nobody:x:65533:
|
||||||
nogroup:x:65534:nobody
|
nogroup:x:65534:nobody
|
||||||
root:x:65532:
|
root:x:0:
|
||||||
|
|||||||
@@ -2,3 +2,4 @@ bob:secret:sshd
|
|||||||
alice:secret:sshd
|
alice:secret:sshd
|
||||||
charlie:secret:sshd
|
charlie:secret:sshd
|
||||||
doe:secret:sshd
|
doe:secret:sshd
|
||||||
|
noneuser::sshd
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ bob:x:5000:9000:bob gecos:@HOMEDIR@/bob:/bin/sh
|
|||||||
alice:x:5001:9000:alice gecos:@HOMEDIR@/alice:/bin/sh
|
alice:x:5001:9000:alice gecos:@HOMEDIR@/alice:/bin/sh
|
||||||
charlie:x:5002:9000:charlie gecos:@HOMEDIR@/charlie:/bin/sh
|
charlie:x:5002:9000:charlie gecos:@HOMEDIR@/charlie:/bin/sh
|
||||||
doe:x:5003:9000:doe gecos:@HOMEDIR@/doe:/bin/sh
|
doe:x:5003:9000:doe gecos:@HOMEDIR@/doe:/bin/sh
|
||||||
|
frank:x:5003:9000:doe gecos:@HOMEDIR@/frank:/bin/sh
|
||||||
|
noneuser:x:5004:9000:noneuser gecos:@HOMEDIR@/noneuser:/bin/sh
|
||||||
sshd:x:65530:65531:sshd:@HOMEDIR@:/sbin/nologin
|
sshd:x:65530:65531:sshd:@HOMEDIR@:/sbin/nologin
|
||||||
nobody:x:65533:65534:nobody gecos:@HOMEDIR@:/bin/false
|
nobody:x:65533:65534:nobody gecos:@HOMEDIR@:/bin/false
|
||||||
root:x:65534:65532:root gecos:@HOMEDIR@:/bin/false
|
root:x:0:0:root gecos:@HOMEDIR@:/bin/false
|
||||||
@LOCAL_USER@:x:@LOCAL_UID@:9000:local user:@HOMEDIR@:/bin/false
|
@LOCAL_USER@:x:@LOCAL_UID@:9000:local user:@HOMEDIR@:/bin/false
|
||||||
|
|||||||
@@ -2,3 +2,4 @@ alice:$6$0jWkA8VP$MvBUvtGy38jWCZ5KtqnZEKQWXvvImDkDhDQII1kTqtAp3/xH31b71c.AjGkBFl
|
|||||||
bob:$6$0jWkA8VP$MvBUvtGy38jWCZ5KtqnZEKQWXvvImDkDhDQII1kTqtAp3/xH31b71c.AjGkBFle.2QwCJQH7OzB/NXiMprusr/::0:::::
|
bob:$6$0jWkA8VP$MvBUvtGy38jWCZ5KtqnZEKQWXvvImDkDhDQII1kTqtAp3/xH31b71c.AjGkBFle.2QwCJQH7OzB/NXiMprusr/::0:::::
|
||||||
charlie:$6$0jWkA8VP$MvBUvtGy38jWCZ5KtqnZEKQWXvvImDkDhDQII1kTqtAp3/xH31b71c.AjGkBFle.2QwCJQH7OzB/NXiMprusr/::0:::::
|
charlie:$6$0jWkA8VP$MvBUvtGy38jWCZ5KtqnZEKQWXvvImDkDhDQII1kTqtAp3/xH31b71c.AjGkBFle.2QwCJQH7OzB/NXiMprusr/::0:::::
|
||||||
doe:$6$0jWkA8VP$MvBUvtGy38jWCZ5KtqnZEKQWXvvImDkDhDQII1kTqtAp3/xH31b71c.AjGkBFle.2QwCJQH7OzB/NXiMprusr/::0:::::
|
doe:$6$0jWkA8VP$MvBUvtGy38jWCZ5KtqnZEKQWXvvImDkDhDQII1kTqtAp3/xH31b71c.AjGkBFle.2QwCJQH7OzB/NXiMprusr/::0:::::
|
||||||
|
noneuser:::0:::::
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ fuzzer(ssh_client_config_fuzzer)
|
|||||||
fuzzer(ssh_known_hosts_fuzzer)
|
fuzzer(ssh_known_hosts_fuzzer)
|
||||||
fuzzer(ssh_privkey_fuzzer)
|
fuzzer(ssh_privkey_fuzzer)
|
||||||
fuzzer(ssh_pubkey_fuzzer)
|
fuzzer(ssh_pubkey_fuzzer)
|
||||||
|
fuzzer(ssh_sftp_attr_fuzzer)
|
||||||
fuzzer(ssh_sshsig_fuzzer)
|
fuzzer(ssh_sshsig_fuzzer)
|
||||||
if (WITH_SERVER)
|
if (WITH_SERVER)
|
||||||
fuzzer(ssh_server_fuzzer)
|
fuzzer(ssh_server_fuzzer)
|
||||||
|
|||||||
131
tests/fuzz/ssh_sftp_attr_fuzzer.c
Normal file
131
tests/fuzz/ssh_sftp_attr_fuzzer.c
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2026 libssh authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define LIBSSH_STATIC 1
|
||||||
|
#include "libssh/libssh.h"
|
||||||
|
#include "libssh/sftp.h"
|
||||||
|
#include "libssh/sftp_priv.h"
|
||||||
|
|
||||||
|
#include "nallocinc.c"
|
||||||
|
|
||||||
|
/* SFTP protocol version constants */
|
||||||
|
#define SFTP_PROTOCOL_VERSION_3 3
|
||||||
|
#define SFTP_PROTOCOL_VERSION_4 4
|
||||||
|
|
||||||
|
/* Flags for sftp_parse_attr expectname parameter */
|
||||||
|
#define SFTP_EXPECT_NAME 1
|
||||||
|
#define SFTP_NO_NAME 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper to create a minimal sftp_session for fuzzing.
|
||||||
|
* We don't use sftp_new() as it requires a real SSH connection.
|
||||||
|
*/
|
||||||
|
static sftp_session create_minimal_sftp_session(ssh_session session)
|
||||||
|
{
|
||||||
|
sftp_session sftp;
|
||||||
|
|
||||||
|
sftp = calloc(1, sizeof(struct sftp_session_struct));
|
||||||
|
if (sftp == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
sftp->session = session;
|
||||||
|
|
||||||
|
return sftp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _fuzz_finalize(void)
|
||||||
|
{
|
||||||
|
ssh_finalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
int LLVMFuzzerInitialize(int *argc, char ***argv)
|
||||||
|
{
|
||||||
|
(void)argc;
|
||||||
|
|
||||||
|
nalloc_init(*argv[0]);
|
||||||
|
|
||||||
|
ssh_init();
|
||||||
|
|
||||||
|
atexit(_fuzz_finalize);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||||
|
{
|
||||||
|
ssh_session session = NULL;
|
||||||
|
sftp_session sftp = NULL;
|
||||||
|
ssh_buffer buffer = NULL;
|
||||||
|
sftp_attributes attr = NULL;
|
||||||
|
int versions[] = {
|
||||||
|
SFTP_PROTOCOL_VERSION_3, SFTP_PROTOCOL_VERSION_3,
|
||||||
|
SFTP_PROTOCOL_VERSION_4, SFTP_PROTOCOL_VERSION_4
|
||||||
|
};
|
||||||
|
int expectnames[] = {SFTP_NO_NAME, SFTP_EXPECT_NAME, SFTP_NO_NAME, SFTP_EXPECT_NAME};
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
/* Minimum bytes for a valid SFTP message */
|
||||||
|
if (size == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(nalloc_start(data, size) > 0);
|
||||||
|
|
||||||
|
/* Allocate shared resources once for all test iterations */
|
||||||
|
session = ssh_new();
|
||||||
|
if (session == NULL) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
sftp = create_minimal_sftp_session(session);
|
||||||
|
if (sftp == NULL) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = ssh_buffer_new();
|
||||||
|
if (buffer == NULL) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Main fuzzing target: sftp_parse_attr */
|
||||||
|
/* Parses untrusted SFTP messages from client */
|
||||||
|
/* Test all combinations (v3/v4, with/without name) */
|
||||||
|
for (i = 0; i < (sizeof(versions) / sizeof(versions[0])); i++) {
|
||||||
|
sftp->version = versions[i];
|
||||||
|
|
||||||
|
/* Reset and repopulate buffer for each iteration */
|
||||||
|
ssh_buffer_reinit(buffer);
|
||||||
|
if (ssh_buffer_add_data(buffer, data, size) == SSH_OK) {
|
||||||
|
attr = sftp_parse_attr(sftp, buffer, expectnames[i]);
|
||||||
|
sftp_attributes_free(attr);
|
||||||
|
attr = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
ssh_buffer_free(buffer);
|
||||||
|
free(sftp);
|
||||||
|
ssh_free(session);
|
||||||
|
nalloc_end();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
141
tests/torture.c
141
tests/torture.c
@@ -389,6 +389,143 @@ failed:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* always return verification successful */
|
||||||
|
static int verify_knownhost_trust_all(UNUSED_PARAM(ssh_session jump_session),
|
||||||
|
UNUSED_PARAM(void *user))
|
||||||
|
{
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a session connected to server via proxyjump
|
||||||
|
*
|
||||||
|
* @param[in] state A pointer to a pointer to an initialized torture_state
|
||||||
|
* structure
|
||||||
|
*
|
||||||
|
* @warning It is expected that both sshd servers are setup before calling
|
||||||
|
* this, see torture_setup_sshd_server() and
|
||||||
|
* torture_setup_sshd_servers()
|
||||||
|
*
|
||||||
|
* TODO: If needed, in future, we can extend this function to:
|
||||||
|
* - allow caller to pass server host port, user, password similar to
|
||||||
|
* torture_ssh_session() or club this with that function
|
||||||
|
*
|
||||||
|
* - allow caller to customize jump hosts and callbacks for each of them
|
||||||
|
*/
|
||||||
|
ssh_session torture_ssh_session_proxyjump(void)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* We'll setup the connection chain:
|
||||||
|
* - client
|
||||||
|
* - jump host 1: doe (sshd server, IPV4)
|
||||||
|
* - jump host 2: alice (sshd server1, IPV6)
|
||||||
|
* - server: alice (sshd server, IPV4)
|
||||||
|
*/
|
||||||
|
char jump_host_list[1024] = {0};
|
||||||
|
int jump_host_count = 2;
|
||||||
|
const char *jump_host_1_address = torture_server_address(AF_INET);
|
||||||
|
const char *jump_host_2_address = torture_server1_address(AF_INET6);
|
||||||
|
struct ssh_jump_callbacks_struct jump_host_callbacks = {
|
||||||
|
.before_connection = NULL,
|
||||||
|
.verify_knownhost = verify_knownhost_trust_all,
|
||||||
|
.authenticate = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
ssh_session session = NULL;
|
||||||
|
bool process_config = false;
|
||||||
|
int rc, i;
|
||||||
|
|
||||||
|
session = ssh_new();
|
||||||
|
if (session == NULL) {
|
||||||
|
fprintf(stderr, "Failed to create new ssh session\n");
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_options_set(session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER);
|
||||||
|
if (rc < 0) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Failed to set session host: %s\n",
|
||||||
|
ssh_get_error(session));
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE);
|
||||||
|
if (rc < 0) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Failed to set session user: %s\n",
|
||||||
|
ssh_get_error(session));
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_options_set(session, SSH_OPTIONS_PROCESS_CONFIG, &process_config);
|
||||||
|
if (rc < 0) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Failed to set process config option: %s\n",
|
||||||
|
ssh_get_error(session));
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = snprintf(jump_host_list,
|
||||||
|
sizeof(jump_host_list),
|
||||||
|
"doe@%s:22,alice@%s:22",
|
||||||
|
jump_host_1_address,
|
||||||
|
jump_host_2_address);
|
||||||
|
if (rc < 0) {
|
||||||
|
fprintf(stderr, "snprintf failed: %s\n", strerror(errno));
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc >= (int)sizeof(jump_host_list)) {
|
||||||
|
fprintf(stderr, "Insufficient jump host list buffer size\n");
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_options_set(session, SSH_OPTIONS_PROXYJUMP, jump_host_list);
|
||||||
|
if (rc < 0) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Failed to set jump hosts for the session: %s\n",
|
||||||
|
ssh_get_error(session));
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < jump_host_count; ++i) {
|
||||||
|
rc = ssh_options_set(session,
|
||||||
|
SSH_OPTIONS_PROXYJUMP_CB_LIST_APPEND,
|
||||||
|
&jump_host_callbacks);
|
||||||
|
if (rc < 0) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Failed to set jump callbacks for jump host %d: %s\n",
|
||||||
|
i + 1,
|
||||||
|
ssh_get_error(session));
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_connect(session);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Failed to connect to ssh server: %s\n",
|
||||||
|
ssh_get_error(session));
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
|
||||||
|
if (rc != SSH_AUTH_SUCCESS) {
|
||||||
|
fprintf(stderr, "Public key authentication did not succeed\n");
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
return session;
|
||||||
|
|
||||||
|
failed:
|
||||||
|
if (ssh_is_connected(session)) {
|
||||||
|
ssh_disconnect(session);
|
||||||
|
}
|
||||||
|
ssh_free(session);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef WITH_SERVER
|
#ifdef WITH_SERVER
|
||||||
|
|
||||||
ssh_bind torture_ssh_bind(const char *addr,
|
ssh_bind torture_ssh_bind(const char *addr,
|
||||||
@@ -833,7 +970,7 @@ torture_setup_create_sshd_config(void **state, bool pam, bool second_sshd)
|
|||||||
"TrustedUserCAKeys %s\n"
|
"TrustedUserCAKeys %s\n"
|
||||||
"\n"
|
"\n"
|
||||||
"LogLevel DEBUG3\n"
|
"LogLevel DEBUG3\n"
|
||||||
"Subsystem sftp %s -l DEBUG2\n"
|
"Subsystem sftp %s -l DEBUG3 -e\n"
|
||||||
"\n"
|
"\n"
|
||||||
"PasswordAuthentication yes\n"
|
"PasswordAuthentication yes\n"
|
||||||
"PubkeyAuthentication yes\n"
|
"PubkeyAuthentication yes\n"
|
||||||
@@ -873,7 +1010,7 @@ torture_setup_create_sshd_config(void **state, bool pam, bool second_sshd)
|
|||||||
"TrustedUserCAKeys %s\n" /* Trusted CA */
|
"TrustedUserCAKeys %s\n" /* Trusted CA */
|
||||||
"\n"
|
"\n"
|
||||||
"LogLevel DEBUG3\n"
|
"LogLevel DEBUG3\n"
|
||||||
"Subsystem sftp %s -l DEBUG2\n" /* SFTP server */
|
"Subsystem sftp %s -l DEBUG3 -e\n" /* SFTP server */
|
||||||
"\n"
|
"\n"
|
||||||
"PasswordAuthentication yes\n"
|
"PasswordAuthentication yes\n"
|
||||||
"PubkeyAuthentication yes\n"
|
"PubkeyAuthentication yes\n"
|
||||||
|
|||||||
@@ -51,6 +51,7 @@
|
|||||||
|
|
||||||
#define TORTURE_SSH_USER_ALICE "alice"
|
#define TORTURE_SSH_USER_ALICE "alice"
|
||||||
#define TORTURE_SSH_USER_CHARLIE "charlie"
|
#define TORTURE_SSH_USER_CHARLIE "charlie"
|
||||||
|
#define TORTURE_SSH_USER_NONEUSER "noneuser"
|
||||||
|
|
||||||
/* Used by main to communicate with parse_opt. */
|
/* Used by main to communicate with parse_opt. */
|
||||||
struct argument_s {
|
struct argument_s {
|
||||||
@@ -115,6 +116,8 @@ ssh_session torture_ssh_session(struct torture_state *s,
|
|||||||
const char *user,
|
const char *user,
|
||||||
const char *password);
|
const char *password);
|
||||||
|
|
||||||
|
ssh_session torture_ssh_session_proxyjump(void);
|
||||||
|
|
||||||
ssh_bind torture_ssh_bind(const char *addr,
|
ssh_bind torture_ssh_bind(const char *addr,
|
||||||
const unsigned int port,
|
const unsigned int port,
|
||||||
enum ssh_keytypes_e key_type,
|
enum ssh_keytypes_e key_type,
|
||||||
|
|||||||
@@ -126,6 +126,13 @@ if (HAVE_LIBFIDO2)
|
|||||||
)
|
)
|
||||||
endif (HAVE_LIBFIDO2)
|
endif (HAVE_LIBFIDO2)
|
||||||
|
|
||||||
|
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
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ extern LIBSSH_THREAD int ssh_log_level;
|
|||||||
#define HOSTKEYALGORITHMS "ssh-ed25519,ecdsa-sha2-nistp521,ssh-rsa"
|
#define HOSTKEYALGORITHMS "ssh-ed25519,ecdsa-sha2-nistp521,ssh-rsa"
|
||||||
#define PUBKEYACCEPTEDTYPES "rsa-sha2-512,ssh-rsa,ecdsa-sha2-nistp521"
|
#define PUBKEYACCEPTEDTYPES "rsa-sha2-512,ssh-rsa,ecdsa-sha2-nistp521"
|
||||||
#define MACS "hmac-sha1,hmac-sha2-256,hmac-sha2-512,hmac-sha1-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com"
|
#define MACS "hmac-sha1,hmac-sha2-256,hmac-sha2-512,hmac-sha1-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com"
|
||||||
#define USER_KNOWN_HOSTS "%d/my_known_hosts"
|
#define USER_KNOWN_HOSTS "%d/.ssh/my_known_hosts"
|
||||||
#define GLOBAL_KNOWN_HOSTS "/etc/ssh/my_ssh_known_hosts"
|
#define GLOBAL_KNOWN_HOSTS "/etc/ssh/my_ssh_known_hosts"
|
||||||
#define BIND_ADDRESS "::1"
|
#define BIND_ADDRESS "::1"
|
||||||
|
|
||||||
@@ -159,6 +159,8 @@ extern LIBSSH_THREAD int ssh_log_level;
|
|||||||
"\tProxyJump jumpbox:2222\n" \
|
"\tProxyJump jumpbox:2222\n" \
|
||||||
"Host two-step\n" \
|
"Host two-step\n" \
|
||||||
"\tProxyJump u1@first:222,u2@second:33\n" \
|
"\tProxyJump u1@first:222,u2@second:33\n" \
|
||||||
|
"Host three-step\n" \
|
||||||
|
"\tProxyJump u1@first:222,u2@second:33,u3@third:444\n" \
|
||||||
"Host none\n" \
|
"Host none\n" \
|
||||||
"\tProxyJump none\n" \
|
"\tProxyJump none\n" \
|
||||||
"Host only-command\n" \
|
"Host only-command\n" \
|
||||||
@@ -1172,6 +1174,23 @@ static void torture_config_proxyjump(void **state,
|
|||||||
"u1",
|
"u1",
|
||||||
"222");
|
"222");
|
||||||
|
|
||||||
|
/* Three step jump */
|
||||||
|
torture_reset_config(session);
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_HOST, "three-step");
|
||||||
|
_parse_config(session, file, string, SSH_OK);
|
||||||
|
helper_proxy_jump_check(session->opts.proxy_jumps->root,
|
||||||
|
"third",
|
||||||
|
"u3",
|
||||||
|
"444");
|
||||||
|
helper_proxy_jump_check(session->opts.proxy_jumps->root->next,
|
||||||
|
"second",
|
||||||
|
"u2",
|
||||||
|
"33");
|
||||||
|
helper_proxy_jump_check(session->opts.proxy_jumps->root->next->next,
|
||||||
|
"first",
|
||||||
|
"u1",
|
||||||
|
"222");
|
||||||
|
|
||||||
/* none */
|
/* none */
|
||||||
torture_reset_config(session);
|
torture_reset_config(session);
|
||||||
ssh_options_set(session, SSH_OPTIONS_HOST, "none");
|
ssh_options_set(session, SSH_OPTIONS_HOST, "none");
|
||||||
@@ -1237,6 +1256,13 @@ static void torture_config_proxyjump(void **state,
|
|||||||
assert_string_equal(session->opts.ProxyCommand,
|
assert_string_equal(session->opts.ProxyCommand,
|
||||||
"ssh -l u1 -p 222 -J u2@second:33 -W '[%h]:%p' first");
|
"ssh -l u1 -p 222 -J u2@second:33 -W '[%h]:%p' first");
|
||||||
|
|
||||||
|
/* Three step jump */
|
||||||
|
torture_reset_config(session);
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_HOST, "three-step");
|
||||||
|
_parse_config(session, file, string, SSH_OK);
|
||||||
|
assert_string_equal(session->opts.ProxyCommand,
|
||||||
|
"ssh -l u1 -p 222 -J u2@second:33,u3@third:444 -W '[%h]:%p' first");
|
||||||
|
|
||||||
/* none */
|
/* none */
|
||||||
torture_reset_config(session);
|
torture_reset_config(session);
|
||||||
ssh_options_set(session, SSH_OPTIONS_HOST, "none");
|
ssh_options_set(session, SSH_OPTIONS_HOST, "none");
|
||||||
@@ -2468,80 +2494,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
|
||||||
@@ -2849,6 +2933,23 @@ static void torture_config_jump(void **state)
|
|||||||
printf("%s: EOF\n", __func__);
|
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;
|
||||||
@@ -3003,6 +3104,9 @@ int torture_run_tests(void)
|
|||||||
cmocka_unit_test_setup_teardown(torture_config_jump,
|
cmocka_unit_test_setup_teardown(torture_config_jump,
|
||||||
setup,
|
setup,
|
||||||
teardown),
|
teardown),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_config_invalid,
|
||||||
|
setup,
|
||||||
|
teardown),
|
||||||
};
|
};
|
||||||
|
|
||||||
ssh_init();
|
ssh_init();
|
||||||
|
|||||||
@@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ static void torture_get_user_home_dir(void **state) {
|
|||||||
|
|
||||||
(void) state;
|
(void) state;
|
||||||
|
|
||||||
user = ssh_get_user_home_dir();
|
user = ssh_get_user_home_dir(NULL);
|
||||||
assert_non_null(user);
|
assert_non_null(user);
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
assert_string_equal(user, pwd->pw_dir);
|
assert_string_equal(user, pwd->pw_dir);
|
||||||
@@ -288,7 +288,8 @@ static void torture_path_expand_escape(void **state) {
|
|||||||
const char *s = "%d/%h/%p/by/%r";
|
const char *s = "%d/%h/%p/by/%r";
|
||||||
char *e;
|
char *e;
|
||||||
|
|
||||||
session->opts.sshdir = strdup("guru");
|
/* Set the homedir here to prevent querying the NSS DB */
|
||||||
|
session->opts.homedir = strdup("guru");
|
||||||
session->opts.host = strdup("meditation");
|
session->opts.host = strdup("meditation");
|
||||||
session->opts.port = 0;
|
session->opts.port = 0;
|
||||||
session->opts.username = strdup("root");
|
session->opts.username = strdup("root");
|
||||||
@@ -310,9 +311,10 @@ static void torture_path_expand_known_hosts(void **state) {
|
|||||||
ssh_session session = *state;
|
ssh_session session = *state;
|
||||||
char *tmp;
|
char *tmp;
|
||||||
|
|
||||||
session->opts.sshdir = strdup("/home/guru/.ssh");
|
/* Set the homedir here to prevent querying the NSS DB */
|
||||||
|
session->opts.homedir = strdup("/home/guru");
|
||||||
|
|
||||||
tmp = ssh_path_expand_escape(session, "%d/known_hosts");
|
tmp = ssh_path_expand_escape(session, "%d/.ssh/known_hosts");
|
||||||
assert_non_null(tmp);
|
assert_non_null(tmp);
|
||||||
assert_string_equal(tmp, "/home/guru/.ssh/known_hosts");
|
assert_string_equal(tmp, "/home/guru/.ssh/known_hosts");
|
||||||
free(tmp);
|
free(tmp);
|
||||||
@@ -322,9 +324,10 @@ static void torture_path_expand_percent(void **state) {
|
|||||||
ssh_session session = *state;
|
ssh_session session = *state;
|
||||||
char *tmp;
|
char *tmp;
|
||||||
|
|
||||||
session->opts.sshdir = strdup("/home/guru/.ssh");
|
/* Set the homedir here to prevent querying the NSS DB */
|
||||||
|
session->opts.homedir = strdup("/home/guru");
|
||||||
|
|
||||||
tmp = ssh_path_expand_escape(session, "%d/config%%1");
|
tmp = ssh_path_expand_escape(session, "%d/.ssh/config%%1");
|
||||||
assert_non_null(tmp);
|
assert_non_null(tmp);
|
||||||
assert_string_equal(tmp, "/home/guru/.ssh/config%1");
|
assert_string_equal(tmp, "/home/guru/.ssh/config%1");
|
||||||
free(tmp);
|
free(tmp);
|
||||||
@@ -1249,6 +1252,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[] = {
|
||||||
@@ -1285,6 +1318,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();
|
||||||
|
|||||||
@@ -839,6 +839,7 @@ static void torture_options_get_identity(void **state)
|
|||||||
char *identity = NULL;
|
char *identity = NULL;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
/* This adds an identity to the head of the list and returns */
|
||||||
rc = ssh_options_set(session, SSH_OPTIONS_ADD_IDENTITY, "identity1");
|
rc = ssh_options_set(session, SSH_OPTIONS_ADD_IDENTITY, "identity1");
|
||||||
assert_true(rc == 0);
|
assert_true(rc == 0);
|
||||||
rc = ssh_options_get(session, SSH_OPTIONS_IDENTITY, &identity);
|
rc = ssh_options_get(session, SSH_OPTIONS_IDENTITY, &identity);
|
||||||
@@ -856,6 +857,48 @@ static void torture_options_get_identity(void **state)
|
|||||||
assert_non_null(identity);
|
assert_non_null(identity);
|
||||||
assert_string_equal(identity, "identity2");
|
assert_string_equal(identity, "identity2");
|
||||||
ssh_string_free_char(identity);
|
ssh_string_free_char(identity);
|
||||||
|
|
||||||
|
/* Iterate over all of the identities */
|
||||||
|
rc = ssh_options_get(session, SSH_OPTIONS_NEXT_IDENTITY, &identity);
|
||||||
|
assert_int_equal(rc, SSH_OK);
|
||||||
|
assert_string_equal(identity, "identity2");
|
||||||
|
ssh_string_free_char(identity);
|
||||||
|
|
||||||
|
rc = ssh_options_get(session, SSH_OPTIONS_NEXT_IDENTITY, &identity);
|
||||||
|
assert_int_equal(rc, SSH_OK);
|
||||||
|
assert_string_equal(identity, "identity1");
|
||||||
|
SAFE_FREE(identity);
|
||||||
|
|
||||||
|
/* here are the default identities */
|
||||||
|
rc = ssh_options_get(session, SSH_OPTIONS_NEXT_IDENTITY, &identity);
|
||||||
|
assert_int_equal(rc, SSH_OK);
|
||||||
|
assert_string_equal(identity, "%d/.ssh/id_ed25519");
|
||||||
|
ssh_string_free_char(identity);
|
||||||
|
|
||||||
|
rc = ssh_options_get(session, SSH_OPTIONS_NEXT_IDENTITY, &identity);
|
||||||
|
assert_int_equal(rc, SSH_OK);
|
||||||
|
assert_string_equal(identity, "%d/.ssh/id_ecdsa");
|
||||||
|
ssh_string_free_char(identity);
|
||||||
|
|
||||||
|
rc = ssh_options_get(session, SSH_OPTIONS_NEXT_IDENTITY, &identity);
|
||||||
|
assert_int_equal(rc, SSH_OK);
|
||||||
|
assert_string_equal(identity, "%d/.ssh/id_rsa");
|
||||||
|
ssh_string_free_char(identity);
|
||||||
|
|
||||||
|
#ifdef WITH_FIDO2
|
||||||
|
rc = ssh_options_get(session, SSH_OPTIONS_NEXT_IDENTITY, &identity);
|
||||||
|
assert_int_equal(rc, SSH_OK);
|
||||||
|
assert_string_equal(identity, "%d/.ssh/id_ed25519_sk");
|
||||||
|
ssh_string_free_char(identity);
|
||||||
|
|
||||||
|
rc = ssh_options_get(session, SSH_OPTIONS_NEXT_IDENTITY, &identity);
|
||||||
|
assert_int_equal(rc, SSH_OK);
|
||||||
|
assert_string_equal(identity, "%d/.ssh/id_ecdsa_sk");
|
||||||
|
ssh_string_free_char(identity);
|
||||||
|
#endif /* WITH_FIDO2 */
|
||||||
|
|
||||||
|
rc = ssh_options_get(session, SSH_OPTIONS_NEXT_IDENTITY, &identity);
|
||||||
|
assert_int_equal(rc, SSH_EOF);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void torture_options_set_global_knownhosts(void **state)
|
static void torture_options_set_global_knownhosts(void **state)
|
||||||
@@ -2067,25 +2110,25 @@ static void torture_options_apply (void **state)
|
|||||||
rc = ssh_list_append(awaited_list, id);
|
rc = ssh_list_append(awaited_list, id);
|
||||||
assert_int_equal(rc, SSH_OK);
|
assert_int_equal(rc, SSH_OK);
|
||||||
/* append the defaults; this list is copied from ssh_new@src/session.c */
|
/* append the defaults; this list is copied from ssh_new@src/session.c */
|
||||||
id = ssh_path_expand_escape(session, "%d/id_ed25519");
|
id = ssh_path_expand_escape(session, "%d/.ssh/id_ed25519");
|
||||||
rc = ssh_list_append(awaited_list, id);
|
rc = ssh_list_append(awaited_list, id);
|
||||||
assert_int_equal(rc, SSH_OK);
|
assert_int_equal(rc, SSH_OK);
|
||||||
#ifdef HAVE_ECC
|
#ifdef HAVE_ECC
|
||||||
id = ssh_path_expand_escape(session, "%d/id_ecdsa");
|
id = ssh_path_expand_escape(session, "%d/.ssh/id_ecdsa");
|
||||||
rc = ssh_list_append(awaited_list, id);
|
rc = ssh_list_append(awaited_list, id);
|
||||||
assert_int_equal(rc, SSH_OK);
|
assert_int_equal(rc, SSH_OK);
|
||||||
#endif
|
#endif
|
||||||
id = ssh_path_expand_escape(session, "%d/id_rsa");
|
id = ssh_path_expand_escape(session, "%d/.ssh/id_rsa");
|
||||||
rc = ssh_list_append(awaited_list, id);
|
rc = ssh_list_append(awaited_list, id);
|
||||||
assert_int_equal(rc, SSH_OK);
|
assert_int_equal(rc, SSH_OK);
|
||||||
#ifdef WITH_FIDO2
|
#ifdef WITH_FIDO2
|
||||||
/* Add security key identities */
|
/* Add security key identities */
|
||||||
id = ssh_path_expand_escape(session, "%d/id_ed25519_sk");
|
id = ssh_path_expand_escape(session, "%d/.ssh/id_ed25519_sk");
|
||||||
rc = ssh_list_append(awaited_list, id);
|
rc = ssh_list_append(awaited_list, id);
|
||||||
assert_int_equal(rc, SSH_OK);
|
assert_int_equal(rc, SSH_OK);
|
||||||
|
|
||||||
#ifdef HAVE_ECC
|
#ifdef HAVE_ECC
|
||||||
id = ssh_path_expand_escape(session, "%d/id_ecdsa_sk");
|
id = ssh_path_expand_escape(session, "%d/.ssh/id_ecdsa_sk");
|
||||||
rc = ssh_list_append(awaited_list, id);
|
rc = ssh_list_append(awaited_list, id);
|
||||||
assert_int_equal(rc, SSH_OK);
|
assert_int_equal(rc, SSH_OK);
|
||||||
#endif /* HAVE_ECC */
|
#endif /* HAVE_ECC */
|
||||||
|
|||||||
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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user