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>
This commit is contained in:
Dirkjan Bussink
2020-12-10 13:20:34 +00:00
committed by Andreas Schneider
parent 3c33c39455
commit f6a2f6190c
2 changed files with 112 additions and 18 deletions

View File

@@ -688,10 +688,12 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
/*
* States required:
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
* - session->global_req_state == SSH_CHANNEL_REQ_STATE_PENDING
*
* Transitions:
* - session->global_req_state == SSH_CHANNEL_REQ_STATE_ACCEPTED
* - From channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING
* - To channel->request_state = SSH_CHANNEL_REQ_STATE_ACCEPTED
*
* If not in a pending state, message is ignored in the callback handler.
* */
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
@@ -699,21 +701,18 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
break;
}
if (session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING) {
rc = SSH_PACKET_DENIED;
break;
}
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_REQUEST_FAILURE: // 82
/*
* States required:
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
* - session->global_req_state == SSH_CHANNEL_REQ_STATE_PENDING
*
* Transitions:
* - session->global_req_state == SSH_CHANNEL_REQ_STATE_DENIED
* - From channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING
* - To channel->request_state = SSH_CHANNEL_REQ_STATE_ACCEPTED
*
* If not in a pending state, message is ignored in the callback handler.
* */
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
@@ -721,11 +720,6 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
break;
}
if (session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING) {
rc = SSH_PACKET_DENIED;
break;
}
rc = SSH_PACKET_ALLOWED;
break;
case SSH2_MSG_CHANNEL_OPEN: // 90
@@ -878,10 +872,12 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
/*
* States required:
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
* - channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING
*
* Transitions:
* - channel->request_state = SSH_CHANNEL_REQ_STATE_ACCEPTED
* - From channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING
* - To channel->request_state = SSH_CHANNEL_REQ_STATE_ACCEPTED
*
* If not in a pending state, message is ignored in the callback handler.
* */
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
@@ -895,10 +891,12 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
/*
* States required:
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
* - channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING
*
* Transitions:
* - channel->request_state = SSH_CHANNEL_REQ_STATE_DENIED
* - From channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING
* - To channel->request_state = SSH_CHANNEL_REQ_STATE_ACCEPTED
*
* If not in a pending state, message is ignored in the callback handler.
* */
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {