Compare commits

...

27 Commits

Author SHA1 Message Date
Samir Benmendil
39a62cef44 tests: suppress leaks from NSS modules
Signed-off-by: Samir Benmendil <me@rmz.io>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit ce45ba8c61)
2026-01-05 16:38:12 +01:00
Jakub Jelen
7969b6de3c Suppress remaining OpenSSL 3.5 memory leaks
Reported as

https://github.com/openssl/openssl/issues/29077

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit b042477f83)
2026-01-05 16:37:46 +01:00
Jakub Jelen
b207e39d28 tests: Adjust valgrind supressions for Fedora 43
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit a94df4bb8f)
2026-01-05 16:37:42 +01:00
Jakub Jelen
6230b24ff5 tests: Test proxyjump configuration parsing
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 82db6a7ab3)
2026-01-05 13:40:22 +01:00
Jakub Jelen
e668b03dd7 tests: Reproducer for missing value to LogLevel
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 163373c9d9)
2026-01-05 13:40:13 +01:00
Jakub Jelen
77ce02d809 config: Allow setting username from configuration
... file, even if it was already set before. The options
level handles what was already set.

The proxyJump implementation sets the username from the proxyjump, which
is setting it to NULL, effectively writing the current username to the
new session, which was not possible to override due to the following check.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 320844669a)
2026-01-05 13:38:49 +01:00
Jakub Jelen
d61b0dc7cc tests: Improve test coverage of comparing certificates
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 701a2155a7)
2026-01-05 13:19:20 +01:00
Jakub Jelen
d12eb770ac pki: Fix comparing public key of certificate
When the first key object is a certificate object, this match will
fall through to the generic key comparison that is unable to handle
the ed25519 keys and fails.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 38f3d158f6)
2026-01-05 13:15:53 +01:00
Jakub Jelen
03b29a6874 pki: Avoild false positive matches when comparing certificates in mbedtls and gcrypt
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 0d5a2652b4)
2026-01-05 13:15:09 +01:00
Jakub Jelen
99957fb561 ssh_known_hosts_get_algorithms: Simplify cleanup ...
...  and prevent memory leak of host_port on memory allocation failure.

Thanks Xiaoke Wang for the report!

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Pavol Žáčik <pzacik@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 9d6df9d0fa)
2026-01-05 13:10:19 +01:00
Jakub Jelen
3e9175e66a server: Check strdup allocation failure
Thanks Xiaoke Wang for the report!

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Pavol Žáčik <pzacik@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit ee180c660e)
2026-01-05 13:09:59 +01:00
Jakub Jelen
bf295abb5b tests: Remove the -E which is overridden by followed -E on ctest CLI
The threads_pki_rsa was running and working under valgrind for some
time already without anyone noticing this syntax does not work.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 950abbbd81)
2026-01-05 13:07:08 +01:00
Jakub Jelen
7f14df3eac tests: Avoid needless pthread_exit()
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit b9c6701c68)
2026-01-05 13:06:56 +01:00
Pavol Žáčik
c206e5d84e client: Reset session packet state on disconnect
When reusing session structures for multiple
connections, the packet state could be SIZE_READ
before disconnect, causing initial packets of the
next connection to be misinterpreted.

Signed-off-by: Pavol Žáčik <pzacik@redhat.com>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit 41b8b3326c)
2026-01-05 13:06:31 +01:00
Jakub Jelen
274b8f19b3 connector: Fix default connector flags
Originally reported by Jeremy Cross <jcross@beyondtrust.com> in #461

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit c932790b82)
2026-01-05 13:05:30 +01:00
Jakub Jelen
39a88d62c9 connector: Reformat
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 8a0aa17bca)
2026-01-05 13:05:02 +01:00
Francesco Rollo
94f12090b5 fix(bind): Remove code duplication in ssh_bind_listen
Signed-off-by: Francesco Rollo <eferollo@gmail.com>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit c94e2efcf1)
2026-01-05 13:04:10 +01:00
Jakub Jelen
301d0e16df Bump version to 0.11.3
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
2025-09-09 10:01:48 +02:00
Jakub Jelen
c182a21e11 poll: Use is_locked helper where possible
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit df4e907dff)
2025-08-14 11:02:39 +02:00
Philippe Antoine
3a28fbe5c6 socket: do not free poll object if it is locked
As it may a cause a use after free if `send` fails when
ssh_poll_ctx_dopoll does its callback
ssh_poll_ctx_dopoll still wants to use the poll object later

Signed-off-by: Philippe Antoine <p.antoine@catenacyber.fr>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit c99261437f)
2025-08-14 11:02:39 +02:00
Andreas Schneider
65f363c9e3 CVE-2025-8114: Fix NULL pointer dereference after allocation failure
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit 53ac23ded4)
2025-08-14 11:02:39 +02:00
Jakub Jelen
1c763e29d1 CVE-2025-8277: mbedtls: Avoid leaking ecdh keys
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit ffed80f8c0)
2025-08-14 11:02:39 +02:00
Jakub Jelen
7d85085d2a tests: Invoke all combinations of wrong guesses during rekey
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit d357a9f3e2)
2025-08-14 11:02:39 +02:00
Jakub Jelen
8e4d67aa9e CVE-2025-8277: ecdh: Free previously allocated pubkeys
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit c9d95ab0c7)
2025-08-14 11:02:39 +02:00
Francesco Rollo
266174a6d3 CVE-2025-8277: Fix memory leak of unused ephemeral key pair after client's wrong KEX guess
Signed-off-by: Francesco Rollo <eferollo@gmail.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit ccff22d378)
2025-08-14 11:02:39 +02:00
Jakub Jelen
87db2659ec CVE-2025-8277: packet: Adjust packet filter to work when DH-GEX is guessed wrongly
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 4310a696f2)
2025-08-14 11:02:39 +02:00
Jakub Jelen
0fad4e6307 tests: Enable all key exchange methods in ssh_ping
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 771e19a7a9)
2025-08-14 11:02:39 +02:00
34 changed files with 1034 additions and 167 deletions

View File

@@ -1,6 +1,15 @@
CHANGELOG
=========
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

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.12.0)
cmake_minimum_required(VERSION 3.14.0)
# Specify search path for CMake modules to be loaded by include()
# and find_package()
@@ -9,7 +9,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")
include(DefineCMakeDefaults)
include(DefineCompilerFlags)
project(libssh VERSION 0.11.2 LANGUAGES C)
project(libssh VERSION 0.11.3 LANGUAGES C)
# global needed variable
set(APPLICATION_NAME ${PROJECT_NAME})
@@ -21,7 +21,7 @@ set(APPLICATION_NAME ${PROJECT_NAME})
# Increment AGE. Set REVISION to 0
# If the source code was changed, but there were no interface changes:
# Increment REVISION.
set(LIBRARY_VERSION "4.10.2")
set(LIBRARY_VERSION "4.10.3")
set(LIBRARY_SOVERSION "4")
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked

View File

@@ -157,6 +157,7 @@ void ssh_poll_ctx_free(ssh_poll_ctx ctx);
int ssh_poll_ctx_add(ssh_poll_ctx ctx, ssh_poll_handle p);
int ssh_poll_ctx_add_socket (ssh_poll_ctx ctx, struct ssh_socket_struct *s);
void ssh_poll_ctx_remove(ssh_poll_ctx ctx, ssh_poll_handle p);
bool ssh_poll_is_locked(ssh_poll_handle p);
int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout);
ssh_poll_ctx ssh_poll_get_default_ctx(ssh_session session);
int ssh_event_add_poll(ssh_event event, ssh_poll_handle p);

View File

@@ -1 +1 @@
4.10.2
4.10.3

View 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

View File

@@ -218,28 +218,12 @@ static int ssh_bind_import_keys(ssh_bind sshbind) {
return SSH_OK;
}
int ssh_bind_listen(ssh_bind sshbind) {
int ssh_bind_listen(ssh_bind sshbind)
{
const char *host = NULL;
socket_t fd;
int rc;
/* Apply global bind configurations, if it hasn't been applied before */
rc = ssh_bind_options_parse_config(sshbind, NULL);
if (rc != 0) {
ssh_set_error(sshbind, SSH_FATAL,"Could not parse global config");
return SSH_ERROR;
}
/* Set default hostkey paths if no hostkey was found before */
if (sshbind->ecdsakey == NULL &&
sshbind->rsakey == NULL &&
sshbind->ed25519key == NULL) {
sshbind->ecdsakey = strdup("/etc/ssh/ssh_host_ecdsa_key");
sshbind->rsakey = strdup("/etc/ssh/ssh_host_rsa_key");
sshbind->ed25519key = strdup("/etc/ssh/ssh_host_ed25519_key");
}
/* Apply global bind configurations, if it hasn't been applied before */
rc = ssh_bind_options_parse_config(sshbind, NULL);
if (rc != 0) {
@@ -289,10 +273,10 @@ int ssh_bind_listen(ssh_bind sshbind) {
}
sshbind->bindfd = fd;
} else {
SSH_LOG(SSH_LOG_DEBUG, "Using app-provided bind socket");
}
return 0;
} else {
SSH_LOG(SSH_LOG_DEBUG, "Using app-provided bind socket");
}
return 0;
}
int ssh_bind_set_callbacks(ssh_bind sshbind, ssh_bind_callbacks callbacks, void *userdata)

View File

@@ -836,6 +836,7 @@ error:
session->opts.fd = SSH_INVALID_SOCKET;
session->session_state = SSH_SESSION_STATE_DISCONNECTED;
session->pending_call_state = SSH_PENDING_CALL_NONE;
session->packet_state = PACKET_STATE_INIT;
while ((it = ssh_list_get_iterator(session->channels)) != NULL) {
ssh_channel_do_free(ssh_iterator_value(ssh_channel, it));

View File

@@ -1066,13 +1066,11 @@ ssh_config_parse_line(ssh_session session,
}
break;
case SOC_USERNAME:
if (session->opts.username == NULL) {
p = ssh_config_get_str_tok(&s, NULL);
if (p && *parsing) {
p = ssh_config_get_str_tok(&s, NULL);
if (p && *parsing) {
ssh_options_set(session, SSH_OPTIONS_USER, p);
}
}
break;
}
break;
case SOC_IDENTITY:
p = ssh_config_get_str_tok(&s, NULL);
if (p && *parsing) {

View File

@@ -166,7 +166,7 @@ int ssh_connector_set_out_channel(ssh_connector connector,
/* Fallback to default value for invalid flags */
if (!(flags & SSH_CONNECTOR_STDOUT) && !(flags & SSH_CONNECTOR_STDERR)) {
connector->in_flags = SSH_CONNECTOR_STDOUT;
connector->out_flags = SSH_CONNECTOR_STDOUT;
}
return ssh_add_channel_callbacks(channel, &connector->out_channel_cb);
@@ -381,15 +381,13 @@ ssh_connector_fd_out_cb(ssh_connector connector)
*
* @returns 0
*/
static int ssh_connector_fd_cb(ssh_poll_handle p,
static int ssh_connector_fd_cb(UNUSED_PARAM(ssh_poll_handle p),
socket_t fd,
int revents,
void *userdata)
{
ssh_connector connector = userdata;
(void)p;
if (revents & POLLERR) {
ssh_connector_except(connector, fd);
} else if((revents & (POLLIN|POLLHUP)) && fd == connector->in_fd) {
@@ -419,7 +417,7 @@ static int ssh_connector_fd_cb(ssh_poll_handle p,
* @returns Amount of data bytes consumed
*/
static int ssh_connector_channel_data_cb(ssh_session session,
ssh_channel channel,
UNUSED_PARAM(ssh_channel channel),
void *data,
uint32_t len,
int is_stderr,
@@ -429,10 +427,6 @@ static int ssh_connector_channel_data_cb(ssh_session session,
int w;
uint32_t window;
(void) session;
(void) channel;
(void) is_stderr;
SSH_LOG(SSH_LOG_TRACE,"connector data on channel");
if (is_stderr && !(connector->in_flags & SSH_CONNECTOR_STDERR)) {
@@ -510,10 +504,11 @@ static int ssh_connector_channel_data_cb(ssh_session session,
*
* @returns Amount of data bytes consumed
*/
static int ssh_connector_channel_write_wontblock_cb(ssh_session session,
ssh_channel channel,
uint32_t bytes,
void *userdata)
static int
ssh_connector_channel_write_wontblock_cb(ssh_session session,
UNUSED_PARAM(ssh_channel channel),
uint32_t bytes,
void *userdata)
{
ssh_connector connector = userdata;
uint8_t buffer[CHUNKSIZE];

View File

@@ -407,6 +407,11 @@ int ssh_dh_init_common(struct ssh_crypto_struct *crypto)
struct dh_ctx *ctx = NULL;
int rc;
/* Cleanup any previously allocated dh_ctx */
if (crypto->dh_ctx != NULL) {
ssh_dh_cleanup(crypto);
}
ctx = calloc(1, sizeof(*ctx));
if (ctx == NULL) {
return SSH_ERROR;

View File

@@ -237,6 +237,11 @@ int ssh_dh_init_common(struct ssh_crypto_struct *crypto)
struct dh_ctx *ctx = NULL;
int rc;
/* Cleanup any previously allocated dh_ctx */
if (crypto->dh_ctx != NULL) {
ssh_dh_cleanup(crypto);
}
ctx = calloc(1, sizeof(*ctx));
if (ctx == NULL) {
return SSH_ERROR;

View File

@@ -191,6 +191,17 @@ static ssh_string ssh_ecdh_generate(ssh_session session)
#endif /* OPENSSL_VERSION_NUMBER */
return NULL;
}
/* Free any previously allocated privkey */
if (session->next_crypto->ecdh_privkey != NULL) {
#if OPENSSL_VERSION_NUMBER < 0x30000000L
EC_KEY_free(session->next_crypto->ecdh_privkey);
#else
EVP_PKEY_free(session->next_crypto->ecdh_privkey);
#endif
session->next_crypto->ecdh_privkey = NULL;
}
session->next_crypto->ecdh_privkey = key;
return pubkey_string;
}
@@ -219,6 +230,7 @@ int ssh_client_ecdh_init(ssh_session session)
return SSH_ERROR;
}
ssh_string_free(session->next_crypto->ecdh_client_pubkey);
session->next_crypto->ecdh_client_pubkey = client_pubkey;
/* register the packet callbacks */

View File

@@ -101,8 +101,15 @@ int ssh_client_ecdh_init(ssh_session session)
goto out;
}
/* Free any previously allocated privkey */
if (session->next_crypto->ecdh_privkey != NULL) {
gcry_sexp_release(session->next_crypto->ecdh_privkey);
session->next_crypto->ecdh_privkey = NULL;
}
session->next_crypto->ecdh_privkey = key;
key = NULL;
SSH_STRING_FREE(session->next_crypto->ecdh_client_pubkey);
session->next_crypto->ecdh_client_pubkey = client_pubkey;
client_pubkey = NULL;

View File

@@ -70,6 +70,12 @@ int ssh_client_ecdh_init(ssh_session session)
return SSH_ERROR;
}
/* Free any previously allocated privkey */
if (session->next_crypto->ecdh_privkey != NULL) {
mbedtls_ecp_keypair_free(session->next_crypto->ecdh_privkey);
SAFE_FREE(session->next_crypto->ecdh_privkey);
}
session->next_crypto->ecdh_privkey = malloc(sizeof(mbedtls_ecp_keypair));
if (session->next_crypto->ecdh_privkey == NULL) {
return SSH_ERROR;
@@ -110,6 +116,7 @@ int ssh_client_ecdh_init(ssh_session session)
goto out;
}
SSH_STRING_FREE(session->next_crypto->ecdh_client_pubkey);
session->next_crypto->ecdh_client_pubkey = client_pubkey;
client_pubkey = NULL;

View File

@@ -1487,6 +1487,8 @@ int ssh_make_sessionid(ssh_session session)
ssh_log_hexdump("hash buffer", ssh_buffer_get(buf), ssh_buffer_get_len(buf));
#endif
/* Set rc for the following switch statement in case we goto error. */
rc = SSH_ERROR;
switch (session->next_crypto->kex_type) {
case SSH_KEX_DH_GROUP1_SHA1:
case SSH_KEX_DH_GROUP14_SHA1:
@@ -1546,6 +1548,7 @@ int ssh_make_sessionid(ssh_session session)
session->next_crypto->secret_hash);
break;
}
/* During the first kex, secret hash and session ID are equal. However, after
* a key re-exchange, a new secret hash is calculated. This hash will not replace
* but complement existing session id.
@@ -1554,6 +1557,7 @@ int ssh_make_sessionid(ssh_session session)
session->next_crypto->session_id = malloc(session->next_crypto->digest_len);
if (session->next_crypto->session_id == NULL) {
ssh_set_error_oom(session);
rc = SSH_ERROR;
goto error;
}
memcpy(session->next_crypto->session_id, session->next_crypto->secret_hash,

View File

@@ -376,25 +376,23 @@ struct ssh_list *ssh_known_hosts_get_algorithms(ssh_session session)
}
}
host_port = ssh_session_get_host_port(session);
if (host_port == NULL) {
return NULL;
}
list = ssh_list_new();
if (list == NULL) {
ssh_set_error_oom(session);
SAFE_FREE(host_port);
return NULL;
}
host_port = ssh_session_get_host_port(session);
if (host_port == NULL) {
goto error;
}
rc = ssh_known_hosts_read_entries(host_port,
session->opts.knownhosts,
&entry_list);
if (rc != 0) {
ssh_list_free(entry_list);
ssh_list_free(list);
return NULL;
SAFE_FREE(host_port);
goto error;
}
rc = ssh_known_hosts_read_entries(host_port,
@@ -402,21 +400,16 @@ struct ssh_list *ssh_known_hosts_get_algorithms(ssh_session session)
&entry_list);
SAFE_FREE(host_port);
if (rc != 0) {
ssh_list_free(entry_list);
ssh_list_free(list);
return NULL;
goto error;
}
if (entry_list == NULL) {
ssh_list_free(list);
return NULL;
goto error;
}
count = ssh_list_count(entry_list);
if (count == 0) {
ssh_list_free(list);
ssh_list_free(entry_list);
return NULL;
goto error;
}
for (it = ssh_list_get_iterator(entry_list);
@@ -460,6 +453,7 @@ struct ssh_list *ssh_known_hosts_get_algorithms(ssh_session session)
return list;
error:
ssh_list_free(entry_list);
ssh_list_free(list);
return NULL;
}

View File

@@ -294,6 +294,7 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
* or session_state == SSH_SESSION_STATE_INITIAL_KEX
* - dh_handshake_state == DH_STATE_INIT
* or dh_handshake_state == DH_STATE_INIT_SENT (re-exchange)
* or dh_handshake_state == DH_STATE_REQUEST_SENT (dh-gex)
* or dh_handshake_state == DH_STATE_FINISHED (re-exchange)
*
* Transitions:
@@ -313,6 +314,7 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
if ((session->dh_handshake_state != DH_STATE_INIT) &&
(session->dh_handshake_state != DH_STATE_INIT_SENT) &&
(session->dh_handshake_state != DH_STATE_REQUEST_SENT) &&
(session->dh_handshake_state != DH_STATE_FINISHED))
{
rc = SSH_PACKET_DENIED;

View File

@@ -701,8 +701,8 @@ int ssh_key_cmp(const ssh_key k1,
ssh_buffer_get_len(k1->cert));
}
if (k1->type == SSH_KEYTYPE_ED25519 ||
k1->type == SSH_KEYTYPE_SK_ED25519) {
if (ssh_key_type_plain(k1->type) == SSH_KEYTYPE_ED25519 ||
ssh_key_type_plain(k1->type) == SSH_KEYTYPE_SK_ED25519) {
return pki_ed25519_key_cmp(k1, k2, what);
}

View File

@@ -1355,7 +1355,7 @@ int pki_key_compare(const ssh_key k1,
case SSH_KEYTYPE_SK_ED25519:
case SSH_KEYTYPE_SK_ED25519_CERT01:
/* ed25519 keys handled globally */
return 0;
return 1;
case SSH_KEYTYPE_ECDSA_P256:
case SSH_KEYTYPE_ECDSA_P256_CERT01:
case SSH_KEYTYPE_ECDSA_P384:

View File

@@ -782,7 +782,7 @@ int pki_key_compare(const ssh_key k1, const ssh_key k2, enum ssh_keycmp_e what)
case SSH_KEYTYPE_ED25519:
case SSH_KEYTYPE_SK_ED25519:
/* ed25519 keys handled globally */
rc = 0;
rc = 1;
break;
default:
rc = 1;

View File

@@ -422,7 +422,7 @@ void ssh_poll_set_events(ssh_poll_handle p, short events)
{
p->events = events;
if (p->ctx != NULL) {
if (p->lock_cnt == 0) {
if (!ssh_poll_is_locked(p)) {
p->ctx->pollfds[p->x.idx].events = events;
} else if (!(p->ctx->pollfds[p->x.idx].events & POLLOUT)) {
/* if locked, allow only setting POLLOUT to prevent recursive
@@ -669,6 +669,20 @@ void ssh_poll_ctx_remove(ssh_poll_ctx ctx, ssh_poll_handle p)
}
}
/**
* @brief Returns if a poll object is locked.
*
* @param p Pointer to an already allocated poll object.
* @returns true if the poll object is locked; false otherwise.
*/
bool ssh_poll_is_locked(ssh_poll_handle p)
{
if (p == NULL) {
return false;
}
return p->lock_cnt > 0;
}
/**
* @brief Poll all the sockets associated through a poll object with a
* poll context. If any of the events are set after the poll, the
@@ -703,7 +717,7 @@ int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout)
* output buffer */
for (i = 0; i < ctx->polls_used; i++) {
/* The lock allows only POLLOUT events: drop the rest */
if (ctx->pollptrs[i]->lock_cnt > 0) {
if (ssh_poll_is_locked(ctx->pollptrs[i])) {
ctx->pollfds[i].events &= POLLOUT;
}
}

View File

@@ -495,6 +495,11 @@ static size_t callback_receive_banner(const void *data, size_t len, void *user)
buffer[i] = '\0';
str = strdup(buffer);
if (str == NULL) {
session->session_state = SSH_SESSION_STATE_ERROR;
ssh_set_error_oom(session);
return 0;
}
/* number of bytes read */
processed = i + 1;
session->clientbanner = str;

View File

@@ -478,7 +478,7 @@ void ssh_socket_close(ssh_socket s)
#endif
}
if (s->poll_handle != NULL) {
if (s->poll_handle != NULL && !ssh_poll_is_locked(s->poll_handle)) {
ssh_poll_free(s->poll_handle);
s->poll_handle = NULL;
}

View File

@@ -181,7 +181,10 @@ void crypto_free(struct ssh_crypto_struct *crypto)
#endif /* OPENSSL_VERSION_NUMBER */
#elif defined HAVE_GCRYPT_ECC
gcry_sexp_release(crypto->ecdh_privkey);
#endif
#elif defined HAVE_LIBMBEDCRYPTO
mbedtls_ecp_keypair_free(crypto->ecdh_privkey);
SAFE_FREE(crypto->ecdh_privkey);
#endif /* HAVE_LIBGCRYPT */
crypto->ecdh_privkey = NULL;
}
#endif

View File

@@ -105,6 +105,7 @@ add_subdirectory(unittests)
# OpenSSH Capabilities are required for all unit tests
find_program(SSH_EXECUTABLE NAMES ssh)
if (SSH_EXECUTABLE)
file(SIZE ${SSH_EXECUTABLE} SSH_EXECUTABLE_SIZE)
execute_process(COMMAND ${SSH_EXECUTABLE} -V ERROR_VARIABLE OPENSSH_VERSION_STR)
string(REGEX REPLACE "^.*OpenSSH_([0-9]+).[0-9].*$" "\\1" OPENSSH_VERSION_MAJOR "${OPENSSH_VERSION_STR}")
string(REGEX REPLACE "^.*OpenSSH_[0-9]+.([0-9]).*$" "\\1" OPENSSH_VERSION_MINOR "${OPENSSH_VERSION_STR}")
@@ -372,10 +373,10 @@ if (FUZZ_TESTING)
endif()
add_custom_target(test_memcheck
# FIXME: The threads_pki_rsa test is skipped under valgrind as it times out
# FIXME: The pkd_hello_i1 test is skipped under valgrind as it times out
# Passing suppression file is also stupid so lets go with override here:
# https://stackoverflow.com/a/56116311
COMMAND ${CMAKE_CTEST_COMMAND} -E torture_threads_pki_rsa -E pkd_hello_i1
COMMAND ${CMAKE_CTEST_COMMAND} -E pkd_hello_i1
--output-on-failure --force-new-ctest-process --test-action memcheck
--overwrite MemoryCheckSuppressionFile=${CMAKE_SOURCE_DIR}/tests/valgrind.supp
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}")

View File

@@ -31,6 +31,7 @@
#include "libssh/priv.h"
#include "libssh/session.h"
#include "libssh/crypto.h"
#include "libssh/token.h"
#include <errno.h>
#include <sys/types.h>
@@ -96,6 +97,7 @@ static int session_teardown(void **state)
struct torture_state *s = *state;
ssh_free(s->ssh.session);
s->ssh.session = NULL;
return 0;
}
@@ -148,7 +150,7 @@ static void torture_rekey_default(void **state)
ssh_disconnect(s->ssh.session);
}
static void sanity_check_session(void **state)
static void sanity_check_session_size(void **state, uint64_t rekey_limit)
{
struct torture_state *s = *state;
struct ssh_crypto_struct *c = NULL;
@@ -156,9 +158,9 @@ static void sanity_check_session(void **state)
c = s->ssh.session->current_crypto;
assert_non_null(c);
assert_int_equal(c->in_cipher->max_blocks,
bytes / c->in_cipher->blocksize);
rekey_limit / c->in_cipher->blocksize);
assert_int_equal(c->out_cipher->max_blocks,
bytes / c->out_cipher->blocksize);
rekey_limit / c->out_cipher->blocksize);
/* when strict kex is used, the newkeys reset the sequence number */
if ((s->ssh.session->flags & SSH_SESSION_FLAG_KEX_STRICT) != 0) {
assert_int_equal(c->out_cipher->packets, s->ssh.session->send_seq);
@@ -170,6 +172,10 @@ static void sanity_check_session(void **state)
assert_true(c->in_cipher->packets < s->ssh.session->recv_seq);
}
}
static void sanity_check_session(void **state)
{
sanity_check_session_size(state, bytes);
}
/* We lower the rekey limits manually and check that the rekey
* really happens when sending data
@@ -275,7 +281,7 @@ static int session_setup_sftp_client(void **state)
/* To trigger rekey by receiving data, the easiest thing is probably to
* use sftp
*/
static void torture_rekey_recv(void **state)
static void torture_rekey_recv_size(void **state, uint64_t rekey_limit)
{
struct torture_state *s = *state;
struct ssh_crypto_struct *c = NULL;
@@ -290,7 +296,7 @@ static void torture_rekey_recv(void **state)
mode_t mask;
int rc;
sanity_check_session(state);
sanity_check_session_size(state, rekey_limit);
/* Copy the initial secret hash = session_id so we know we changed keys later */
c = s->ssh.session->current_crypto;
assert_non_null(c);
@@ -324,8 +330,10 @@ static void torture_rekey_recv(void **state)
/* The rekey limit was restored in the new crypto to the same value */
c = s->ssh.session->current_crypto;
assert_int_equal(c->in_cipher->max_blocks, bytes / c->in_cipher->blocksize);
assert_int_equal(c->out_cipher->max_blocks, bytes / c->out_cipher->blocksize);
assert_int_equal(c->in_cipher->max_blocks,
rekey_limit / c->in_cipher->blocksize);
assert_int_equal(c->out_cipher->max_blocks,
rekey_limit / c->out_cipher->blocksize);
/* Check that the secret hash is different than initially */
assert_memory_not_equal(secret_hash, c->secret_hash, c->digest_len);
free(secret_hash);
@@ -333,6 +341,11 @@ static void torture_rekey_recv(void **state)
torture_sftp_close(s->ssh.tsftp);
ssh_disconnect(s->ssh.session);
}
static void torture_rekey_recv(void **state)
{
torture_rekey_recv_size(state, bytes);
}
#endif /* WITH_SFTP */
/* Rekey time requires rekey after specified time and is off by default.
@@ -836,6 +849,81 @@ static void torture_rekey_guess_wrong_recv(void **state)
torture_rekey_recv(state);
}
static void torture_rekey_guess_all_combinations(void **state)
{
struct torture_state *s = *state;
char sshd_config[256] = "";
char client_kex[256] = "";
const char *supported = NULL;
struct ssh_tokens_st *s_tok = NULL;
uint64_t rekey_limit = 0;
int rc, i, j;
/* The rekey limit is 1/2 of the transferred file size so we will likely get
* 2 rekeys per test, which still runs for acceptable time */
rekey_limit = atoll(SSH_EXECUTABLE_SIZE);
rekey_limit /= 2;
if (ssh_fips_mode()) {
supported = ssh_kex_get_fips_methods(SSH_KEX);
} else {
supported = ssh_kex_get_supported_method(SSH_KEX);
}
assert_non_null(supported);
s_tok = ssh_tokenize(supported, ',');
assert_non_null(s_tok);
for (i = 0; s_tok->tokens[i]; i++) {
/* Skip algorithms not supported by the OpenSSH server */
if (strstr(OPENSSH_KEX, s_tok->tokens[i]) == NULL) {
SSH_LOG(SSH_LOG_INFO, "Server: %s [skipping]", s_tok->tokens[i]);
continue;
}
SSH_LOG(SSH_LOG_INFO, "Server: %s", s_tok->tokens[i]);
snprintf(sshd_config,
sizeof(sshd_config),
"KexAlgorithms %s",
s_tok->tokens[i]);
/* This sets an only supported kex algorithm that we do not have as
* a first option in the client */
torture_update_sshd_config(state, sshd_config);
for (j = 0; s_tok->tokens[j]; j++) {
if (i == j) {
continue;
}
session_setup(state);
/* Make the client send the first_kex_packet_follows flag during key
* exchange as well as during the rekey */
s->ssh.session->send_first_kex_follows = true;
rc = ssh_options_set(s->ssh.session,
SSH_OPTIONS_REKEY_DATA,
&rekey_limit);
assert_ssh_return_code(s->ssh.session, rc);
/* Client kex preference will have the second of the pair and the
* server one as a second to negotiate on the second attempt */
snprintf(client_kex,
sizeof(client_kex),
"%s,%s",
s_tok->tokens[j],
s_tok->tokens[i]);
SSH_LOG(SSH_LOG_INFO, "Client: %s", client_kex);
rc = ssh_options_set(s->ssh.session,
SSH_OPTIONS_KEY_EXCHANGE,
client_kex);
assert_ssh_return_code(s->ssh.session, rc);
session_setup_sftp(state);
torture_rekey_recv_size(state, rekey_limit);
session_teardown(state);
}
}
ssh_tokens_free(s_tok);
}
#endif /* WITH_SFTP */
int torture_run_tests(void) {
@@ -905,6 +993,7 @@ int torture_run_tests(void) {
cmocka_unit_test_setup_teardown(torture_rekey_guess_wrong_recv,
session_setup,
session_teardown),
cmocka_unit_test(torture_rekey_guess_all_combinations),
#endif /* WITH_SFTP */
};

View File

@@ -27,6 +27,7 @@ int main(int argc, char **argv)
const char *banner = NULL;
ssh_session session = NULL;
const char *hostkeys = NULL;
const char *kex = NULL;
int rc = 1;
bool process_config = false;
@@ -67,6 +68,13 @@ int main(int argc, char **argv)
goto out;
}
/* Enable all supported kex algorithms */
kex = ssh_kex_get_supported_method(SSH_KEX);
rc = ssh_options_set(session, SSH_OPTIONS_KEY_EXCHANGE, kex);
if (rc < 0) {
goto out;
}
rc = ssh_connect(session);
if (rc != SSH_OK) {
fprintf(stderr, "Connection failed : %s\n", ssh_get_error(session));

View File

@@ -65,6 +65,7 @@
#cmakedefine NCAT_EXECUTABLE "${NCAT_EXECUTABLE}"
#cmakedefine SSHD_EXECUTABLE "${SSHD_EXECUTABLE}"
#cmakedefine SSH_EXECUTABLE "${SSH_EXECUTABLE}"
#cmakedefine SSH_EXECUTABLE_SIZE "${SSH_EXECUTABLE_SIZE}"
#cmakedefine DROPBEAR_EXECUTABLE "${DROPBEAR_EXECUTABLE}"
#cmakedefine WITH_TIMEOUT ${WITH_TIMEOUT}
#cmakedefine TIMEOUT_EXECUTABLE "${TIMEOUT_EXECUTABLE}"

View File

@@ -53,6 +53,8 @@ extern LIBSSH_THREAD int ssh_log_level;
#define LIBSSH_TEST_NONEWLINEONELINE "libssh_test_NoNewLineOneline.tmp"
#define LIBSSH_TEST_RECURSIVE_INCLUDE "libssh_test_recursive_include.tmp"
#define LIBSSH_TESTCONFIG_MATCH_COMPLEX "libssh_test_match_complex.tmp"
#define LIBSSH_TESTCONFIG_LOGLEVEL_MISSING "libssh_test_loglevel_missing.tmp"
#define LIBSSH_TESTCONFIG_JUMP "libssh_test_jump.tmp"
#define LIBSSH_TESTCONFIG_STRING1 \
"User "USERNAME"\nInclude "LIBSSH_TESTCONFIG2"\n\n"
@@ -243,6 +245,26 @@ extern LIBSSH_THREAD int ssh_log_level;
"\tForwardAgent yes\n" \
"\tHostName complex-match\n"
#define LIBSSH_TESTCONFIG_LOGLEVEL_MISSING_STRING "LogLevel\n"
#define LIBSSH_TESTCONFIG_JUMP_STRING \
"# The jump host\n" \
"Host ub-jumphost\n" \
" HostName 1xxxxxx\n" \
" User ubuntu\n" \
" IdentityFile ~/of/temp-libssh.pem\n" \
" Port 23\n" \
" LogLevel DEBUG3\n" \
"\n" \
"# Cisco Router through Jump Host\n" \
"Host cisco-router\n" \
" HostName xx.xxxxxxxxx\n" \
" User username\n" \
" ProxyJump ub-jumphost\n" \
" Port 5555\n" \
" #RequiredRSASize 512\n" \
" PasswordAuthentication yes\n" \
" LogLevel DEBUG3\n"
/**
* @brief helper function loading configuration from either file or string
*/
@@ -293,6 +315,8 @@ static int setup_config_files(void **state)
unlink(LIBSSH_TEST_NONEWLINEEND);
unlink(LIBSSH_TEST_NONEWLINEONELINE);
unlink(LIBSSH_TESTCONFIG_MATCH_COMPLEX);
unlink(LIBSSH_TESTCONFIG_LOGLEVEL_MISSING);
unlink(LIBSSH_TESTCONFIG_JUMP);
torture_write_file(LIBSSH_TESTCONFIG1,
LIBSSH_TESTCONFIG_STRING1);
@@ -361,6 +385,10 @@ static int setup_config_files(void **state)
/* Match complex combinations */
torture_write_file(LIBSSH_TESTCONFIG_MATCH_COMPLEX,
LIBSSH_TESTCONFIG_MATCH_COMPLEX_STRING);
torture_write_file(LIBSSH_TESTCONFIG_LOGLEVEL_MISSING,
LIBSSH_TESTCONFIG_LOGLEVEL_MISSING_STRING);
torture_write_file(LIBSSH_TESTCONFIG_JUMP,
LIBSSH_TESTCONFIG_JUMP_STRING);
return 0;
}
@@ -390,6 +418,8 @@ static int teardown_config_files(void **state)
unlink(LIBSSH_TEST_NONEWLINEEND);
unlink(LIBSSH_TEST_NONEWLINEONELINE);
unlink(LIBSSH_TESTCONFIG_MATCH_COMPLEX);
unlink(LIBSSH_TESTCONFIG_LOGLEVEL_MISSING);
unlink(LIBSSH_TESTCONFIG_JUMP);
return 0;
}
@@ -2617,6 +2647,112 @@ static void torture_config_match_complex(void **state)
ssh_string_free_char(v);
}
/* Missing value to LogLevel configuration option
*/
static void torture_config_loglevel_missing_value(void **state)
{
ssh_session session = *state;
ssh_options_set(session, SSH_OPTIONS_HOST, "Bar");
_parse_config(session, LIBSSH_TESTCONFIG_LOGLEVEL_MISSING, NULL, SSH_OK);
}
static int before_connection(ssh_session jump_session, void *user)
{
char *v = NULL;
int ret;
(void)user;
/* During the connection, we force parsing the same configuration file
* (would be normally parsed automatically during the connection itself)
*/
ret = ssh_config_parse_file(jump_session, LIBSSH_TESTCONFIG_JUMP);
assert_return_code(ret, errno);
/* Test the variable presence */
ret = ssh_options_get(jump_session, SSH_OPTIONS_HOST, &v);
assert_return_code(ret, errno);
assert_string_equal(v, "1xxxxxx");
ssh_string_free_char(v);
ret = ssh_options_get(jump_session, SSH_OPTIONS_USER, &v);
assert_return_code(ret, errno);
assert_string_equal(v, "ubuntu");
ssh_string_free_char(v);
assert_int_equal(jump_session->opts.port, 23);
/* Fail the connection -- we are in unit tests so it would fail anyway */
return 1;
}
static int verify_knownhost(ssh_session jump_session, void *user)
{
(void)jump_session;
(void)user;
return 0;
}
static int authenticate(ssh_session jump_session, void *user)
{
(void)jump_session;
(void)user;
return 0;
}
/* Reproducer for complex proxy jump
*/
static void torture_config_jump(void **state)
{
ssh_session session = *state;
struct ssh_jump_callbacks_struct c = {
.before_connection = before_connection,
.verify_knownhost = verify_knownhost,
.authenticate = authenticate,
};
char *v = NULL;
int ret;
ssh_options_set(session, SSH_OPTIONS_HOST, "cisco-router");
_parse_config(session, LIBSSH_TESTCONFIG_JUMP, NULL, SSH_OK);
/* Test the variable presence */
ret = ssh_options_get(session, SSH_OPTIONS_HOST, &v);
assert_return_code(ret, errno);
assert_string_equal(v, "xx.xxxxxxxxx");
ssh_string_free_char(v);
ret = ssh_options_get(session, SSH_OPTIONS_USER, &v);
assert_return_code(ret, errno);
assert_string_equal(v, "username");
ssh_string_free_char(v);
assert_int_equal(session->opts.port, 5555);
/* At this point, the configuration file is not parsed for the jump host so
* we are getting just the the hostname -- the port and username will get
* pulled during the session connecting to this host */
assert_int_equal(ssh_list_count(session->opts.proxy_jumps), 1);
helper_proxy_jump_check(session->opts.proxy_jumps->root,
"ub-jumphost",
NULL,
NULL);
/* Set up the callbacks -- they should verify we are going to connect to the
* right host */
ret = ssh_options_set(session, SSH_OPTIONS_PROXYJUMP_CB_LIST_APPEND, &c);
assert_ssh_return_code(session, ret);
ret = ssh_connect(session);
assert_ssh_return_code_equal(session, ret, SSH_ERROR);
printf("%s: EOF\n", __func__);
}
int torture_run_tests(void)
{
int rc;
@@ -2713,6 +2849,12 @@ int torture_run_tests(void)
setup, teardown),
cmocka_unit_test_setup_teardown(torture_config_match_complex,
setup, teardown),
cmocka_unit_test_setup_teardown(torture_config_loglevel_missing_value,
setup,
teardown),
cmocka_unit_test_setup_teardown(torture_config_jump,
setup,
teardown),
};

View File

@@ -367,10 +367,14 @@ static void torture_pki_ecdsa_publickey_from_privatekey(void **state)
static void torture_pki_ecdsa_import_cert_file(void **state)
{
int rc;
ssh_key pubkey = NULL;
ssh_key privkey = NULL;
ssh_key cert = NULL;
enum ssh_keytypes_e type;
enum ssh_keytypes_e type, exp_cert_type;
struct pki_st *test_state = *((struct pki_st **)state);
exp_cert_type = test_state->type + 3;
/* Importing public key as cert should fail */
rc = ssh_pki_import_cert_file(LIBSSH_ECDSA_TESTKEY ".pub", &cert);
assert_int_equal(rc, SSH_ERROR);
@@ -380,13 +384,78 @@ static void torture_pki_ecdsa_import_cert_file(void **state)
assert_int_equal(rc, 0);
assert_non_null(cert);
rc = ssh_pki_import_pubkey_file(LIBSSH_ECDSA_TESTKEY ".pub", &pubkey);
assert_return_code(rc, errno);
assert_non_null(pubkey);
type = ssh_key_type(cert);
assert_int_equal(type, test_state->type+3);
assert_int_equal(type, exp_cert_type);
rc = ssh_key_is_public(cert);
assert_int_equal(rc, 1);
/* Import matching private key file and verify the pubkey matches */
rc = ssh_pki_import_privkey_file(LIBSSH_ECDSA_TESTKEY,
NULL,
NULL,
NULL,
&privkey);
assert_return_code(rc, errno);
assert_non_null(privkey);
type = ssh_key_type(privkey);
assert_true(type == test_state->type);
/* Basic sanity. */
rc = ssh_pki_copy_cert_to_privkey(NULL, privkey);
assert_int_equal(rc, SSH_ERROR);
rc = ssh_pki_copy_cert_to_privkey(pubkey, NULL);
assert_int_equal(rc, SSH_ERROR);
/* A public key doesn't have a cert, copy should fail. */
assert_null(pubkey->cert);
rc = ssh_pki_copy_cert_to_privkey(pubkey, privkey);
assert_int_equal(rc, SSH_ERROR);
/* Copying the cert to non-cert keys should work fine. */
rc = ssh_pki_copy_cert_to_privkey(cert, pubkey);
assert_return_code(rc, errno);
assert_non_null(pubkey->cert);
rc = ssh_pki_copy_cert_to_privkey(cert, privkey);
assert_return_code(rc, errno);
assert_non_null(privkey->cert);
assert_true(privkey->cert_type == exp_cert_type);
assert_int_equal(ssh_key_cmp(privkey, cert, SSH_KEY_CMP_PUBLIC), 0);
assert_int_equal(ssh_key_cmp(cert, privkey, SSH_KEY_CMP_PUBLIC), 0);
/* The private key's cert is already set, another copy should fail. */
rc = ssh_pki_copy_cert_to_privkey(cert, privkey);
assert_int_equal(rc, SSH_ERROR);
SSH_KEY_FREE(privkey);
SSH_KEY_FREE(pubkey);
/* Generate different key and try to assign it this certificate */
rc = ssh_pki_generate(test_state->type, 256, &privkey);
assert_return_code(rc, errno);
assert_non_null(privkey);
rc = ssh_pki_export_privkey_to_pubkey(privkey, &pubkey);
assert_return_code(rc, errno);
assert_non_null(pubkey);
rc = ssh_pki_copy_cert_to_privkey(cert, privkey);
assert_int_equal(rc, SSH_ERROR);
rc = ssh_pki_copy_cert_to_privkey(cert, pubkey);
assert_int_equal(rc, SSH_ERROR);
assert_int_equal(ssh_key_cmp(privkey, cert, SSH_KEY_CMP_PUBLIC), 1);
assert_int_equal(ssh_key_cmp(cert, privkey, SSH_KEY_CMP_PUBLIC), 1);
SSH_KEY_FREE(cert);
SSH_KEY_FREE(privkey);
SSH_KEY_FREE(pubkey);
}
static void torture_pki_ecdsa_publickey_base64(void **state)

View File

@@ -312,6 +312,8 @@ static void torture_pki_ed25519_publickey_from_privatekey(void **state)
static void torture_pki_ed25519_import_cert_file(void **state)
{
int rc;
ssh_key pubkey = NULL;
ssh_key privkey = NULL;
ssh_key cert = NULL;
enum ssh_keytypes_e type;
@@ -323,16 +325,88 @@ static void torture_pki_ed25519_import_cert_file(void **state)
assert_null(cert);
rc = ssh_pki_import_cert_file(LIBSSH_ED25519_TESTKEY "-cert.pub", &cert);
assert_true(rc == 0);
assert_return_code(rc, errno);
assert_non_null(cert);
rc = ssh_pki_import_pubkey_file(LIBSSH_ED25519_TESTKEY ".pub", &pubkey);
assert_return_code(rc, errno);
assert_non_null(pubkey);
type = ssh_key_type(cert);
assert_true(type == SSH_KEYTYPE_ED25519_CERT01);
rc = ssh_key_is_public(cert);
assert_true(rc == 1);
assert_int_equal(rc, 1);
/* Skip test if in FIPS mode */
if (ssh_fips_mode()) {
SSH_KEY_FREE(cert);
SSH_KEY_FREE(pubkey);
skip();
}
/* Import matching private key file and verify the pubkey matches */
rc = ssh_pki_import_privkey_file(LIBSSH_ED25519_TESTKEY,
NULL,
NULL,
NULL,
&privkey);
assert_return_code(rc, errno);
assert_non_null(privkey);
type = ssh_key_type(privkey);
assert_true(type == SSH_KEYTYPE_ED25519);
/* Basic sanity. */
rc = ssh_pki_copy_cert_to_privkey(NULL, privkey);
assert_int_equal(rc, SSH_ERROR);
rc = ssh_pki_copy_cert_to_privkey(pubkey, NULL);
assert_int_equal(rc, SSH_ERROR);
/* A public key doesn't have a cert, copy should fail. */
assert_null(pubkey->cert);
rc = ssh_pki_copy_cert_to_privkey(pubkey, privkey);
assert_int_equal(rc, SSH_ERROR);
/* Copying the cert to non-cert keys should work fine. */
rc = ssh_pki_copy_cert_to_privkey(cert, pubkey);
assert_return_code(rc, errno);
assert_non_null(pubkey->cert);
rc = ssh_pki_copy_cert_to_privkey(cert, privkey);
assert_return_code(rc, errno);
assert_non_null(privkey->cert);
assert_true(privkey->cert_type == SSH_KEYTYPE_ED25519_CERT01);
assert_int_equal(ssh_key_cmp(privkey, cert, SSH_KEY_CMP_PUBLIC), 0);
assert_int_equal(ssh_key_cmp(cert, privkey, SSH_KEY_CMP_PUBLIC), 0);
/* The private key's cert is already set, another copy should fail. */
rc = ssh_pki_copy_cert_to_privkey(cert, privkey);
assert_int_equal(rc, SSH_ERROR);
SSH_KEY_FREE(privkey);
SSH_KEY_FREE(pubkey);
/* Generate different key and try to assign it this certificate */
rc = ssh_pki_generate(SSH_KEYTYPE_ED25519, 0, &privkey);
assert_return_code(rc, errno);
assert_non_null(privkey);
rc = ssh_pki_export_privkey_to_pubkey(privkey, &pubkey);
assert_return_code(rc, errno);
assert_non_null(pubkey);
rc = ssh_pki_copy_cert_to_privkey(cert, privkey);
assert_int_equal(rc, SSH_ERROR);
rc = ssh_pki_copy_cert_to_privkey(cert, pubkey);
assert_int_equal(rc, SSH_ERROR);
assert_int_equal(ssh_key_cmp(privkey, cert, SSH_KEY_CMP_PUBLIC), 1);
assert_int_equal(ssh_key_cmp(cert, privkey, SSH_KEY_CMP_PUBLIC), 1);
SSH_KEY_FREE(cert);
SSH_KEY_FREE(privkey);
SSH_KEY_FREE(pubkey);
}
static void torture_pki_ed25519_publickey_base64(void **state)

View File

@@ -373,6 +373,7 @@ static void torture_pki_rsa_copy_cert_to_privkey(void **state)
ssh_key pubkey = NULL;
ssh_key privkey = NULL;
ssh_key cert = NULL;
enum ssh_keytypes_e type;
(void)state; /* unused */
@@ -389,6 +390,13 @@ static void torture_pki_rsa_copy_cert_to_privkey(void **state)
assert_return_code(rc, errno);
assert_non_null(pubkey);
type = ssh_key_type(cert);
assert_true(type == SSH_KEYTYPE_RSA_CERT01);
rc = ssh_key_is_public(cert);
assert_int_equal(rc, 1);
/* Import matching private key file and verify the pubkey matches */
rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_RSA, 0),
passphrase,
NULL,
@@ -397,6 +405,9 @@ static void torture_pki_rsa_copy_cert_to_privkey(void **state)
assert_return_code(rc, errno);
assert_non_null(privkey);
type = ssh_key_type(privkey);
assert_true(type == SSH_KEYTYPE_RSA);
/* Basic sanity. */
rc = ssh_pki_copy_cert_to_privkey(NULL, privkey);
assert_int_equal(rc, SSH_ERROR);
@@ -416,6 +427,10 @@ static void torture_pki_rsa_copy_cert_to_privkey(void **state)
rc = ssh_pki_copy_cert_to_privkey(cert, privkey);
assert_return_code(rc, errno);
assert_non_null(privkey->cert);
assert_true(privkey->cert_type == SSH_KEYTYPE_RSA_CERT01);
assert_int_equal(ssh_key_cmp(privkey, cert, SSH_KEY_CMP_PUBLIC), 0);
assert_int_equal(ssh_key_cmp(cert, privkey, SSH_KEY_CMP_PUBLIC), 0);
/* The private key's cert is already set, another copy should fail. */
rc = ssh_pki_copy_cert_to_privkey(cert, privkey);
@@ -437,6 +452,9 @@ static void torture_pki_rsa_copy_cert_to_privkey(void **state)
rc = ssh_pki_copy_cert_to_privkey(cert, pubkey);
assert_int_equal(rc, SSH_ERROR);
assert_int_equal(ssh_key_cmp(privkey, cert, SSH_KEY_CMP_PUBLIC), 1);
assert_int_equal(ssh_key_cmp(cert, privkey, SSH_KEY_CMP_PUBLIC), 1);
SSH_KEY_FREE(cert);
SSH_KEY_FREE(privkey);
SSH_KEY_FREE(pubkey);

View File

@@ -58,14 +58,8 @@ static int run_on_threads(void *(*func)(void *))
}
for (i = 0; i < NUM_THREADS; ++i) {
void *p = NULL;
uint64_t *result;
rc = pthread_join(threads[i], &p);
rc = pthread_join(threads[i], NULL);
assert_int_equal(rc, 0);
result = (uint64_t *)p;
assert_null(result);
}
return rc;
@@ -164,7 +158,7 @@ static void *thread_pki_rsa_import_pubkey_file(void *threadid)
SSH_KEY_FREE(pubkey);
pthread_exit(NULL);
return NULL;
}
static void torture_pki_rsa_import_pubkey_file(void **state)
@@ -197,8 +191,7 @@ static void *thread_pki_rsa_import_privkey_base64_NULL_key(void *threadid)
NULL,
NULL);
assert_true(rc == -1);
pthread_exit(NULL);
return NULL;
}
static void torture_pki_rsa_import_privkey_base64_NULL_key(void **state){
@@ -225,7 +218,8 @@ static void *thread_pki_rsa_import_privkey_base64_NULL_str(void *threadid)
assert_true(rc == -1);
SSH_KEY_FREE(key);
pthread_exit(NULL);
return NULL;
}
static void torture_pki_rsa_import_privkey_base64_NULL_str(void **state){
@@ -267,7 +261,7 @@ static void *thread_pki_rsa_import_privkey_base64(void *threadid)
free(key_str);
SSH_KEY_FREE(key);
pthread_exit(NULL);
return NULL;
}
static void torture_pki_rsa_import_privkey_base64(void **state)
@@ -310,7 +304,8 @@ static void *thread_pki_rsa_publickey_from_privatekey(void *threadid)
SSH_KEY_FREE(key);
SSH_KEY_FREE(pubkey);
pthread_exit(NULL);
return NULL;
}
static void torture_pki_rsa_publickey_from_privatekey(void **state)
@@ -383,7 +378,8 @@ static void *thread_pki_rsa_copy_cert_to_privkey(void *threadid)
SSH_KEY_FREE(cert);
SSH_KEY_FREE(privkey);
SSH_KEY_FREE(pubkey);
pthread_exit(NULL);
return NULL;
}
static void torture_pki_rsa_copy_cert_to_privkey(void **state)
@@ -416,7 +412,8 @@ static void *thread_pki_rsa_import_cert_file(void *threadid)
assert_true(rc == 1);
SSH_KEY_FREE(cert);
pthread_exit(NULL);
return NULL;
}
static void torture_pki_rsa_import_cert_file(void **state)
@@ -467,7 +464,8 @@ static void *thread_pki_rsa_publickey_base64(void *threadid)
free(b64_key);
free(key_buf);
SSH_KEY_FREE(key);
pthread_exit(NULL);
return NULL;
}
static void torture_pki_rsa_publickey_base64(void **state)
@@ -531,7 +529,8 @@ static void *thread_pki_rsa_duplicate_key(void *threadid)
SSH_KEY_FREE(privkey_dup);
SSH_STRING_FREE_CHAR(b64_key);
SSH_STRING_FREE_CHAR(b64_key_gen);
pthread_exit(NULL);
return NULL;
}
static void torture_pki_rsa_duplicate_key(void **state)
@@ -614,7 +613,8 @@ static void *thread_pki_rsa_generate_key(void *threadid)
SSH_KEY_FREE(pubkey);
ssh_free(session);
pthread_exit(NULL);
return NULL;
}
static void torture_pki_rsa_generate_key(void **state)
@@ -672,7 +672,8 @@ static void *thread_pki_rsa_import_privkey_base64_passphrase(void *threadid)
assert_true(rc == -1);
SSH_KEY_FREE(key);
#endif
pthread_exit(NULL);
return NULL;
}
static void torture_pki_rsa_import_privkey_base64_passphrase(void **state)
@@ -723,14 +724,8 @@ static void torture_mixed(void **state)
for (f = 0; f < NUM_TESTS; f++) {
for (i = 0; i < NUM_THREADS; ++i) {
void *p = NULL;
uint64_t *result = NULL;
rc = pthread_join(threads[f][i], &p);
rc = pthread_join(threads[f][i], NULL);
assert_int_equal(rc, 0);
result = (uint64_t *)p;
assert_null(result);
}
}
}

View File

@@ -140,6 +140,40 @@
fun:FIPS_mode_set
fun:OPENSSL_init_library
}
{
Threads + Failed PEM decoder do not play well openssl/openssl#29077
Memcheck:Leak
match-leak-kinds: definite
fun:malloc
fun:CRYPTO_malloc
fun:CRYPTO_zalloc
fun:ossl_rcu_read_lock
fun:module_find
fun:module_run
fun:CONF_modules_load
fun:CONF_modules_load_file_ex
fun:ossl_config_int
fun:ossl_config_int
fun:ossl_init_config
fun:ossl_init_config_ossl_
fun:__pthread_once_slow.isra.0
fun:pthread_once@@GLIBC_2.34
fun:CRYPTO_THREAD_run_once
fun:OPENSSL_init_crypto
fun:ossl_provider_doall_activated
fun:ossl_algorithm_do_all
fun:ossl_method_construct.constprop.0
fun:inner_evp_generic_fetch.constprop.0
fun:evp_generic_do_all
fun:EVP_KEYMGMT_do_all_provided
fun:ossl_decoder_ctx_setup_for_pkey
fun:OSSL_DECODER_CTX_new_for_pkey
fun:pem_read_bio_key_decoder
fun:pem_read_bio_key
fun:PEM_read_bio_PrivateKey_ex
fun:pki_private_key_from_base64
...
}
# Cmocka
{
This looks like leak from cmocka when the forked server is not properly terminated
@@ -207,65 +241,12 @@
Memcheck:Leak
match-leak-kinds: reachable
fun:malloc
fun:malloc
fun:strdup
fun:_dl_load_cache_lookup
fun:_dl_map_object
fun:dl_open_worker_begin
fun:_dl_catch_exception
fun:dl_open_worker
fun:_dl_catch_exception
fun:_dl_open
fun:do_dlopen
fun:_dl_catch_exception
fun:_dl_catch_error
fun:dlerror_run
fun:__libc_dlopen_mode
fun:module_load
fun:__nss_module_get_function
fun:getaddrinfo
...
fun:krb5_sname_to_principal
...
fun:gss_init_sec_context
fun:ssh_packet_userauth_gssapi_response
fun:ssh_packet_process
fun:ssh_packet_socket_callback
fun:ssh_socket_pollcallback
fun:ssh_poll_ctx_dopoll
fun:ssh_handle_packets
fun:ssh_handle_packets_termination
fun:ssh_userauth_get_response
fun:ssh_userauth_gssapi
fun:torture_gssapi_auth_server_identity
...
fun:_cmocka_run_group_tests
fun:torture_run_tests
fun:main
}
{
Reachable memory from getaddrinfo
Memcheck:Leak
match-leak-kinds: reachable
...
fun:__nss_module_get_function
...
fun:getaddrinfo
...
fun:krb5_sname_to_principal
...
fun:gss_init_sec_context
fun:ssh_packet_userauth_gssapi_response
fun:ssh_packet_process
fun:ssh_packet_socket_callback
fun:ssh_socket_pollcallback
fun:ssh_poll_ctx_dopoll
fun:ssh_handle_packets
fun:ssh_handle_packets_termination
fun:ssh_userauth_get_response
fun:ssh_userauth_gssapi
fun:torture_gssapi_auth_server_identity
fun:torture_*
...
fun:_cmocka_run_group_tests
fun:torture_run_tests
@@ -290,13 +271,11 @@
fun:malloc
...
fun:krb5_gss_save_error_string
fun:UnknownInlinedFun
...
fun:acquire_cred_context.isra.0
fun:acquire_cred_from.isra.0
fun:gss_add_cred_from
fun:gss_acquire_cred_from
...
fun:gss_acquire_cred
}
{
error string from gss init sec context
@@ -305,7 +284,7 @@
fun:malloc
...
fun:krb5_gss_save_error_string
fun:UnknownInlinedFun
...
fun:krb5_gss_init_sec_context_ext
fun:krb5_gss_init_sec_context
fun:gss_init_sec_context