Ignore request success and failure message if they are not expected

In https://gitlab.com/libssh/libssh-mirror/-/merge_requests/145#note_463232084
behavior in libssh was identified where it diverges from how for example
OpenSSH behaves. In OpenSSH if a request success of failure message is
received, apart from it being treated as a keepalive message, it is
ignored otherwise.

Libssh does handle the unexpected message and triggers an error
condition internally. This means that with the Dropbear behavior where
it replies to a hostkeys-00@openssh.com message even with a want_reply
= 0 (arguably a bug), libssh enters an error state.

This change makes the libssh behavior match OpenSSH to ignore these
messages. The spec is a bit unclear on whether Dropbear is buggy here or
not, but let's be liberal with the input accepted here in libssh.

Signed-off-by: Dirkjan Bussink <d.bussink@gmail.com>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit f6a2f6190c)
This commit is contained in:
Dirkjan Bussink
2020-12-10 13:20:34 +00:00
committed by Jakub Jelen
parent 761a4d5fa2
commit 0a5b93e479
2 changed files with 112 additions and 18 deletions

View File

@@ -517,12 +517,108 @@ static void torture_packet_filter_check_channel_open(void **state)
assert_int_equal(rc, 0);
}
static void torture_packet_filter_check_channel_success(void **state)
{
int rc;
/* The only condition to accept a CHANNEL_SUCCESS is to be authenticated */
global_state accepted[] = {
{
.flags = COMPARE_SESSION_STATE,
.session = SSH_SESSION_STATE_AUTHENTICATED,
}
};
int accepted_count = 1;
/* Unused */
(void) state;
rc = check_message_in_all_states(accepted, accepted_count,
SSH2_MSG_CHANNEL_SUCCESS);
assert_int_equal(rc, 0);
}
static void torture_packet_filter_check_channel_failure(void **state)
{
int rc;
/* The only condition to accept a CHANNEL_FAILURE is to be authenticated */
global_state accepted[] = {
{
.flags = COMPARE_SESSION_STATE,
.session = SSH_SESSION_STATE_AUTHENTICATED,
}
};
int accepted_count = 1;
/* Unused */
(void) state;
rc = check_message_in_all_states(accepted, accepted_count,
SSH2_MSG_CHANNEL_FAILURE);
assert_int_equal(rc, 0);
}
static void torture_packet_filter_check_request_success(void **state)
{
int rc;
/* The only condition to accept a REQUEST_SUCCESS is to be authenticated */
global_state accepted[] = {
{
.flags = COMPARE_SESSION_STATE,
.session = SSH_SESSION_STATE_AUTHENTICATED,
}
};
int accepted_count = 1;
/* Unused */
(void) state;
rc = check_message_in_all_states(accepted, accepted_count,
SSH2_MSG_REQUEST_SUCCESS);
assert_int_equal(rc, 0);
}
static void torture_packet_filter_check_request_failure(void **state)
{
int rc;
/* The only condition to accept a REQUEST_FAILURE is to be authenticated */
global_state accepted[] = {
{
.flags = COMPARE_SESSION_STATE,
.session = SSH_SESSION_STATE_AUTHENTICATED,
}
};
int accepted_count = 1;
/* Unused */
(void) state;
rc = check_message_in_all_states(accepted, accepted_count,
SSH2_MSG_REQUEST_FAILURE);
assert_int_equal(rc, 0);
}
int torture_run_tests(void)
{
int rc;
struct CMUnitTest tests[] = {
cmocka_unit_test(torture_packet_filter_check_auth_success),
cmocka_unit_test(torture_packet_filter_check_channel_open),
cmocka_unit_test(torture_packet_filter_check_channel_success),
cmocka_unit_test(torture_packet_filter_check_channel_failure),
cmocka_unit_test(torture_packet_filter_check_request_success),
cmocka_unit_test(torture_packet_filter_check_request_failure),
cmocka_unit_test(torture_packet_filter_check_unfiltered),
cmocka_unit_test(torture_packet_filter_check_msg_ext_info)
};