mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-09 09:54:25 +09:00
sftp: Reformat sftp_packet_read()
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit afc14fe003)
This commit is contained in:
167
src/sftp.c
167
src/sftp.c
@@ -313,98 +313,101 @@ int sftp_packet_write(sftp_session sftp, uint8_t type, ssh_buffer payload){
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
sftp_packet sftp_packet_read(sftp_session sftp) {
|
sftp_packet sftp_packet_read(sftp_session sftp)
|
||||||
unsigned char buffer[MAX_BUF_SIZE];
|
{
|
||||||
sftp_packet packet = NULL;
|
unsigned char buffer[MAX_BUF_SIZE];
|
||||||
uint32_t tmp;
|
sftp_packet packet = NULL;
|
||||||
size_t size;
|
uint32_t tmp;
|
||||||
int r, s, is_eof;
|
size_t size;
|
||||||
|
int r, s, is_eof;
|
||||||
|
|
||||||
packet = calloc(1, sizeof(struct sftp_packet_struct));
|
packet = calloc(1, sizeof(struct sftp_packet_struct));
|
||||||
if (packet == NULL) {
|
if (packet == NULL) {
|
||||||
ssh_set_error_oom(sftp->session);
|
ssh_set_error_oom(sftp->session);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
packet->sftp = sftp;
|
packet->sftp = sftp;
|
||||||
packet->payload = ssh_buffer_new();
|
packet->payload = ssh_buffer_new();
|
||||||
if (packet->payload == NULL) {
|
if (packet->payload == NULL) {
|
||||||
ssh_set_error_oom(sftp->session);
|
ssh_set_error_oom(sftp->session);
|
||||||
SAFE_FREE(packet);
|
SAFE_FREE(packet);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
r = ssh_buffer_allocate_size(packet->payload, 4);
|
|
||||||
if (r < 0) {
|
|
||||||
ssh_set_error_oom(sftp->session);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
r=0;
|
|
||||||
do {
|
|
||||||
// read from channel until 4 bytes have been read or an error occurs
|
|
||||||
s=ssh_channel_read(sftp->channel, buffer+r, 4-r, 0);
|
|
||||||
if (s < 0) {
|
|
||||||
goto error;
|
|
||||||
} else if (s == 0) {
|
|
||||||
is_eof = ssh_channel_is_eof(sftp->channel);
|
|
||||||
if (is_eof) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
r += s;
|
|
||||||
}
|
}
|
||||||
} while (r<4);
|
|
||||||
ssh_buffer_add_data(packet->payload, buffer, r);
|
|
||||||
if (ssh_buffer_get_u32(packet->payload, &tmp) != sizeof(uint32_t)) {
|
|
||||||
ssh_set_error(sftp->session, SSH_FATAL, "Short sftp packet!");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
r = ssh_buffer_allocate_size(packet->payload, 4);
|
||||||
r = ssh_channel_read(sftp->channel, buffer, 1, 0);
|
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
|
ssh_set_error_oom(sftp->session);
|
||||||
goto error;
|
goto error;
|
||||||
} else if (s == 0) {
|
}
|
||||||
is_eof = ssh_channel_is_eof(sftp->channel);
|
r = 0;
|
||||||
if (is_eof) {
|
do {
|
||||||
|
// read from channel until 4 bytes have been read or an error occurs
|
||||||
|
s = ssh_channel_read(sftp->channel, buffer + r, 4 - r, 0);
|
||||||
|
if (s < 0) {
|
||||||
|
goto error;
|
||||||
|
} else if (s == 0) {
|
||||||
|
is_eof = ssh_channel_is_eof(sftp->channel);
|
||||||
|
if (is_eof) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
r += s;
|
||||||
|
}
|
||||||
|
} while (r < 4);
|
||||||
|
ssh_buffer_add_data(packet->payload, buffer, r);
|
||||||
|
if (ssh_buffer_get_u32(packet->payload, &tmp) != sizeof(uint32_t)) {
|
||||||
|
ssh_set_error(sftp->session, SSH_FATAL, "Short sftp packet!");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
r = ssh_channel_read(sftp->channel, buffer, 1, 0);
|
||||||
|
if (r < 0) {
|
||||||
|
goto error;
|
||||||
|
} else if (s == 0) {
|
||||||
|
is_eof = ssh_channel_is_eof(sftp->channel);
|
||||||
|
if (is_eof) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (r < 1);
|
||||||
|
ssh_buffer_add_data(packet->payload, buffer, r);
|
||||||
|
ssh_buffer_get_u8(packet->payload, &packet->type);
|
||||||
|
|
||||||
|
size = ntohl(tmp);
|
||||||
|
if (size == 0 || size > UINT32_MAX) {
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
size--;
|
||||||
|
|
||||||
|
r = ssh_buffer_allocate_size(packet->payload, size);
|
||||||
|
if (r < 0) {
|
||||||
|
ssh_set_error_oom(sftp->session);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
while (size > 0 && size < UINT_MAX) {
|
||||||
|
r = ssh_channel_read(sftp->channel,
|
||||||
|
buffer,
|
||||||
|
sizeof(buffer) > size ? size : sizeof(buffer),
|
||||||
|
0);
|
||||||
|
|
||||||
|
if (r < 0) {
|
||||||
|
/* TODO: check if there are cases where an error needs to be set here */
|
||||||
|
goto error;
|
||||||
|
} else if (r == 0) {
|
||||||
|
/* Retry the reading unless the remote was closed */
|
||||||
|
is_eof = ssh_channel_is_eof(sftp->channel);
|
||||||
|
if (is_eof) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
} else if (ssh_buffer_add_data(packet->payload, buffer, r) == SSH_ERROR) {
|
||||||
|
ssh_set_error_oom(sftp->session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
size -= r;
|
||||||
}
|
}
|
||||||
} while (r < 1);
|
|
||||||
ssh_buffer_add_data(packet->payload, buffer, r);
|
|
||||||
ssh_buffer_get_u8(packet->payload, &packet->type);
|
|
||||||
|
|
||||||
size = ntohl(tmp);
|
|
||||||
if (size == 0 || size > UINT32_MAX) {
|
|
||||||
return packet;
|
return packet;
|
||||||
}
|
|
||||||
size--;
|
|
||||||
|
|
||||||
r = ssh_buffer_allocate_size(packet->payload, size);
|
|
||||||
if (r < 0) {
|
|
||||||
ssh_set_error_oom(sftp->session);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
while (size > 0 && size < UINT_MAX) {
|
|
||||||
r=ssh_channel_read(sftp->channel,buffer,
|
|
||||||
sizeof(buffer)>size ? size:sizeof(buffer),0);
|
|
||||||
|
|
||||||
if (r < 0) {
|
|
||||||
/* TODO: check if there are cases where an error needs to be set here */
|
|
||||||
goto error;
|
|
||||||
} else if (r == 0) {
|
|
||||||
/* Retry the reading unless the remote was closed */
|
|
||||||
is_eof = ssh_channel_is_eof(sftp->channel);
|
|
||||||
if (is_eof) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
} else if (ssh_buffer_add_data(packet->payload, buffer, r) == SSH_ERROR) {
|
|
||||||
ssh_set_error_oom(sftp->session);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
size -= r;
|
|
||||||
}
|
|
||||||
|
|
||||||
return packet;
|
|
||||||
error:
|
error:
|
||||||
ssh_buffer_free(packet->payload);
|
ssh_buffer_free(packet->payload);
|
||||||
SAFE_FREE(packet);
|
SAFE_FREE(packet);
|
||||||
|
|||||||
Reference in New Issue
Block a user