sftp: Properly check bounds of incoming packet

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
This commit is contained in:
Jakub Jelen
2023-03-27 11:33:44 +02:00
parent e5a6dc6757
commit baa18d3712
3 changed files with 24 additions and 13 deletions

View File

@@ -52,7 +52,7 @@ int sftp_reply_version(sftp_client_message client_msg);
* *
* @return Length of data decoded. * @return Length of data decoded.
*/ */
int sftp_decode_channel_data_to_packet(sftp_session sftp, void *data); int sftp_decode_channel_data_to_packet(sftp_session sftp, void *data, uint32_t len);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -360,31 +360,42 @@ void sftp_free(sftp_session sftp)
SAFE_FREE(sftp); SAFE_FREE(sftp);
} }
int sftp_decode_channel_data_to_packet(sftp_session sftp, void *data) /* @internal
* Process the incoming data and copy them from the SSH packet buffer to the
* SFTP packet buffer.
* @returns number of decoded bytes.
*/
int
sftp_decode_channel_data_to_packet(sftp_session sftp, void *data, uint32_t len)
{ {
sftp_packet packet = sftp->read_packet; sftp_packet packet = sftp->read_packet;
int nread; int nread;
int payload_len; int payload_len;
int offset; unsigned int data_offset;
int to_read; int to_read;
if (packet->sftp == NULL) { if (packet->sftp == NULL) {
packet->sftp = sftp; packet->sftp = sftp;
} }
packet->type = *((uint8_t *)data + sizeof(uint32_t)); data_offset = sizeof(uint32_t) + sizeof(uint8_t);
payload_len = PULL_BE_U32(data, 0); /* not enough bytes to read */
if (len < data_offset) {
/* We should check the legality of payload length */ return SSH_ERROR;
if (payload_len > MAX_PACKET_LEN || payload_len < 0) { }
payload_len = PULL_BE_U32(data, 0);
packet->type = PULL_BE_U8(data, 4);
/* We should check the legality of payload length */
if (payload_len + sizeof(uint32_t) > len || payload_len < 0) {
return SSH_ERROR; return SSH_ERROR;
} }
offset = sizeof(int) + sizeof(uint8_t);
to_read = payload_len - sizeof(uint8_t); to_read = payload_len - sizeof(uint8_t);
ssh_buffer_add_data(packet->payload, ssh_buffer_add_data(packet->payload,
(void*)((uint8_t *)data + offset), (void*)((uint8_t *)data + data_offset),
payload_len - sizeof(uint8_t)); to_read);
nread = ssh_buffer_get_len(packet->payload); nread = ssh_buffer_get_len(packet->payload);
/* We should check if we copied the whole data */ /* We should check if we copied the whole data */

View File

@@ -1702,7 +1702,7 @@ int
sftp_channel_default_data_callback(UNUSED_PARAM(ssh_session session), sftp_channel_default_data_callback(UNUSED_PARAM(ssh_session session),
UNUSED_PARAM(ssh_channel channel), UNUSED_PARAM(ssh_channel channel),
void *data, void *data,
UNUSED_PARAM(uint32_t len), uint32_t len,
UNUSED_PARAM(int is_stderr), UNUSED_PARAM(int is_stderr),
void *userdata) void *userdata)
{ {
@@ -1718,7 +1718,7 @@ sftp_channel_default_data_callback(UNUSED_PARAM(ssh_session session),
} }
sftp = *sftpp; sftp = *sftpp;
decode_len = sftp_decode_channel_data_to_packet(sftp, data); decode_len = sftp_decode_channel_data_to_packet(sftp, data, len);
if (decode_len == -1) if (decode_len == -1)
return -1; return -1;