sftp.c | sftp.c | |||
---|---|---|---|---|
skipping to change at line 36 | skipping to change at line 36 | |||
#include <errno.h> | #include <errno.h> | |||
#include <fcntl.h> | #include <fcntl.h> | |||
#include <stdlib.h> | #include <stdlib.h> | |||
#include <string.h> | #include <string.h> | |||
#include <sys/types.h> | #include <sys/types.h> | |||
#include <sys/stat.h> | #include <sys/stat.h> | |||
#ifndef _WIN32 | #ifndef _WIN32 | |||
#include <arpa/inet.h> | #include <arpa/inet.h> | |||
#else | ||||
#define S_IFSOCK 0140000 | ||||
#define S_IFLNK 0120000 | ||||
#ifdef _MSC_VER | ||||
#define S_IFBLK 0060000 | ||||
#define S_IFIFO 0010000 | ||||
#endif | ||||
#endif | #endif | |||
#include "libssh/priv.h" | #include "libssh/priv.h" | |||
#include "libssh/ssh2.h" | #include "libssh/ssh2.h" | |||
#include "libssh/sftp.h" | #include "libssh/sftp.h" | |||
#include "libssh/buffer.h" | ||||
#include "libssh/channels.h" | ||||
#include "libssh/session.h" | ||||
#include "libssh/misc.h" | ||||
#ifdef WITH_SFTP | #ifdef WITH_SFTP | |||
#define sftp_enter_function() _enter_function(sftp->channel->session) | #define sftp_enter_function() _enter_function(sftp->channel->session) | |||
#define sftp_leave_function() _leave_function(sftp->channel->session) | #define sftp_leave_function() _leave_function(sftp->channel->session) | |||
struct sftp_ext_struct { | ||||
unsigned int count; | ||||
char **name; | ||||
char **data; | ||||
}; | ||||
/* functions */ | /* functions */ | |||
static int sftp_enqueue(SFTP_SESSION *session, SFTP_MESSAGE *msg); | static int sftp_enqueue(sftp_session session, sftp_message msg); | |||
static void sftp_message_free(SFTP_MESSAGE *msg); | static void sftp_message_free(sftp_message msg); | |||
static void sftp_set_error(SFTP_SESSION *sftp, int errnum); | static void sftp_set_error(sftp_session sftp, int errnum); | |||
static void status_msg_free(STATUS_MESSAGE *status); | static void status_msg_free(sftp_status_message status); | |||
static sftp_ext sftp_ext_new(void) { | ||||
sftp_ext ext; | ||||
ext = malloc(sizeof(struct sftp_ext_struct)); | ||||
if (ext == NULL) { | ||||
return NULL; | ||||
} | ||||
ZERO_STRUCTP(ext); | ||||
SFTP_SESSION *sftp_new(SSH_SESSION *session){ | return ext; | |||
SFTP_SESSION *sftp; | } | |||
static void sftp_ext_free(sftp_ext ext) { | ||||
unsigned int i; | ||||
if (ext == NULL) { | ||||
return; | ||||
} | ||||
if (ext->count) { | ||||
for (i = 0; i < ext->count; i++) { | ||||
SAFE_FREE(ext->name[i]); | ||||
SAFE_FREE(ext->data[i]); | ||||
} | ||||
SAFE_FREE(ext->name); | ||||
SAFE_FREE(ext->data); | ||||
} | ||||
SAFE_FREE(ext); | ||||
} | ||||
sftp_session sftp_new(ssh_session session){ | ||||
sftp_session sftp; | ||||
enter_function(); | enter_function(); | |||
if (session == NULL) { | if (session == NULL) { | |||
leave_function(); | leave_function(); | |||
return NULL; | return NULL; | |||
} | } | |||
sftp = malloc(sizeof(SFTP_SESSION)); | sftp = malloc(sizeof(struct sftp_session_struct)); | |||
if (sftp == NULL) { | if (sftp == NULL) { | |||
ssh_set_error_oom(session); | ||||
leave_function(); | leave_function(); | |||
return NULL; | return NULL; | |||
} | } | |||
memset(sftp,0,sizeof(SFTP_SESSION)); | ZERO_STRUCTP(sftp); | |||
sftp->ext = sftp_ext_new(); | ||||
if (sftp->ext == NULL) { | ||||
ssh_set_error_oom(session); | ||||
SAFE_FREE(sftp); | ||||
sftp_leave_function(); | ||||
return NULL; | ||||
} | ||||
sftp->session = session; | sftp->session = session; | |||
sftp->channel = channel_new(session); | sftp->channel = channel_new(session); | |||
if (sftp->channel == NULL) { | if (sftp->channel == NULL) { | |||
SAFE_FREE(sftp); | SAFE_FREE(sftp); | |||
leave_function(); | leave_function(); | |||
return NULL; | return NULL; | |||
} | } | |||
if (channel_open_session(sftp->channel)) { | if (channel_open_session(sftp->channel)) { | |||
skipping to change at line 96 | skipping to change at line 154 | |||
sftp_free(sftp); | sftp_free(sftp); | |||
leave_function(); | leave_function(); | |||
return NULL; | return NULL; | |||
} | } | |||
leave_function(); | leave_function(); | |||
return sftp; | return sftp; | |||
} | } | |||
#ifdef WITH_SERVER | #ifdef WITH_SERVER | |||
SFTP_SESSION *sftp_server_new(SSH_SESSION *session, CHANNEL *chan){ | sftp_session sftp_server_new(ssh_session session, ssh_channel chan){ | |||
SFTP_SESSION *sftp = NULL; | sftp_session sftp = NULL; | |||
sftp = malloc(sizeof(SFTP_SESSION)); | sftp = malloc(sizeof(struct sftp_session_struct)); | |||
if (sftp == NULL) { | if (sftp == NULL) { | |||
ssh_set_error_oom(session); | ||||
return NULL; | return NULL; | |||
} | } | |||
ZERO_STRUCTP(sftp); | ZERO_STRUCTP(sftp); | |||
sftp->session = session; | sftp->session = session; | |||
sftp->channel = chan; | sftp->channel = chan; | |||
return sftp; | return sftp; | |||
} | } | |||
int sftp_server_init(SFTP_SESSION *sftp){ | int sftp_server_init(sftp_session sftp){ | |||
struct ssh_session *session = sftp->session; | ssh_session session = sftp->session; | |||
SFTP_PACKET *packet = NULL; | sftp_packet packet = NULL; | |||
BUFFER *reply = NULL; | ssh_buffer reply = NULL; | |||
u32 version; | uint32_t version; | |||
sftp_enter_function(); | sftp_enter_function(); | |||
packet = sftp_packet_read(sftp); | packet = sftp_packet_read(sftp); | |||
if (packet == NULL) { | if (packet == NULL) { | |||
sftp_leave_function(); | sftp_leave_function(); | |||
return -1; | return -1; | |||
} | } | |||
if (packet->type != SSH_FXP_INIT) { | if (packet->type != SSH_FXP_INIT) { | |||
skipping to change at line 146 | skipping to change at line 205 | |||
buffer_get_u32(packet->payload, &version); | buffer_get_u32(packet->payload, &version); | |||
version = ntohl(version); | version = ntohl(version); | |||
ssh_log(session, SSH_LOG_PACKET, "Client version: %d", version); | ssh_log(session, SSH_LOG_PACKET, "Client version: %d", version); | |||
sftp->client_version = version; | sftp->client_version = version; | |||
sftp_packet_free(packet); | sftp_packet_free(packet); | |||
reply = buffer_new(); | reply = buffer_new(); | |||
if (reply == NULL) { | if (reply == NULL) { | |||
ssh_set_error_oom(session); | ||||
sftp_leave_function(); | sftp_leave_function(); | |||
return -1; | return -1; | |||
} | } | |||
if (buffer_add_u32(reply, ntohl(LIBSFTP_VERSION)) < 0) { | if (buffer_add_u32(reply, ntohl(LIBSFTP_VERSION)) < 0) { | |||
ssh_set_error_oom(session); | ||||
buffer_free(reply); | buffer_free(reply); | |||
sftp_leave_function(); | sftp_leave_function(); | |||
return -1; | return -1; | |||
} | } | |||
if (sftp_packet_write(sftp, SSH_FXP_VERSION, reply) < 0) { | if (sftp_packet_write(sftp, SSH_FXP_VERSION, reply) < 0) { | |||
buffer_free(reply); | buffer_free(reply); | |||
sftp_leave_function(); | sftp_leave_function(); | |||
return -1; | return -1; | |||
} | } | |||
skipping to change at line 176 | skipping to change at line 237 | |||
sftp->version = LIBSFTP_VERSION; | sftp->version = LIBSFTP_VERSION; | |||
} else { | } else { | |||
sftp->version=version; | sftp->version=version; | |||
} | } | |||
sftp_leave_function(); | sftp_leave_function(); | |||
return 0; | return 0; | |||
} | } | |||
#endif /* WITH_SERVER */ | #endif /* WITH_SERVER */ | |||
void sftp_free(SFTP_SESSION *sftp){ | void sftp_free(sftp_session sftp){ | |||
struct request_queue *ptr; | sftp_request_queue ptr; | |||
if (sftp == NULL) { | if (sftp == NULL) { | |||
return; | return; | |||
} | } | |||
channel_send_eof(sftp->channel); | channel_send_eof(sftp->channel); | |||
ptr = sftp->queue; | ptr = sftp->queue; | |||
while(ptr) { | while(ptr) { | |||
struct request_queue *old; | sftp_request_queue old; | |||
sftp_message_free(ptr->message); | sftp_message_free(ptr->message); | |||
old = ptr->next; | old = ptr->next; | |||
SAFE_FREE(ptr); | SAFE_FREE(ptr); | |||
ptr = old; | ptr = old; | |||
} | } | |||
channel_free(sftp->channel); | channel_free(sftp->channel); | |||
memset(sftp, 0, sizeof(*sftp)); | sftp_ext_free(sftp->ext); | |||
ZERO_STRUCTP(sftp); | ||||
SAFE_FREE(sftp); | SAFE_FREE(sftp); | |||
} | } | |||
int sftp_packet_write(SFTP_SESSION *sftp,u8 type, BUFFER *payload){ | int sftp_packet_write(sftp_session sftp, uint8_t type, ssh_buffer payload){ | |||
int size; | int size; | |||
if (buffer_prepend_data(payload, &type, sizeof(u8)) < 0) { | if (buffer_prepend_data(payload, &type, sizeof(uint8_t)) < 0) { | |||
ssh_set_error_oom(sftp->session); | ||||
return -1; | return -1; | |||
} | } | |||
size = htonl(buffer_get_len(payload)); | size = htonl(buffer_get_len(payload)); | |||
if (buffer_prepend_data(payload, &size, sizeof(u32)) < 0) { | if (buffer_prepend_data(payload, &size, sizeof(uint32_t)) < 0) { | |||
ssh_set_error_oom(sftp->session); | ||||
return -1; | return -1; | |||
} | } | |||
size = channel_write(sftp->channel, buffer_get(payload), | size = channel_write(sftp->channel, buffer_get(payload), | |||
buffer_get_len(payload)); | buffer_get_len(payload)); | |||
if (size < 0) { | if (size < 0) { | |||
return -1; | return -1; | |||
} else if((u32) size != buffer_get_len(payload)) { | } else if((uint32_t) size != buffer_get_len(payload)) { | |||
ssh_log(sftp->session, SSH_LOG_PACKET, | ssh_log(sftp->session, SSH_LOG_PACKET, | |||
"Had to write %d bytes, wrote only %d", | "Had to write %d bytes, wrote only %d", | |||
buffer_get_len(payload), | buffer_get_len(payload), | |||
size); | size); | |||
} | } | |||
return size; | return size; | |||
} | } | |||
SFTP_PACKET *sftp_packet_read(SFTP_SESSION *sftp) { | sftp_packet sftp_packet_read(sftp_session sftp) { | |||
SFTP_PACKET *packet = NULL; | sftp_packet packet = NULL; | |||
u32 size; | uint32_t size; | |||
sftp_enter_function(); | sftp_enter_function(); | |||
packet = malloc(sizeof(SFTP_PACKET)); | packet = malloc(sizeof(struct sftp_packet_struct)); | |||
if (packet == NULL) { | if (packet == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
return NULL; | return NULL; | |||
} | } | |||
packet->sftp = sftp; | packet->sftp = sftp; | |||
packet->payload = buffer_new(); | packet->payload = buffer_new(); | |||
if (packet->payload == NULL) { | if (packet->payload == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
SAFE_FREE(packet); | SAFE_FREE(packet); | |||
return NULL; | return NULL; | |||
} | } | |||
if (channel_read_buffer(sftp->channel, packet->payload, 4, 0) <= 0) { | if (channel_read_buffer(sftp->channel, packet->payload, 4, 0) <= 0) { | |||
buffer_free(packet->payload); | buffer_free(packet->payload); | |||
SAFE_FREE(packet); | SAFE_FREE(packet); | |||
sftp_leave_function(); | sftp_leave_function(); | |||
return NULL; | return NULL; | |||
} | } | |||
if (buffer_get_u32(packet->payload, &size) < 0) { | if (buffer_get_u32(packet->payload, &size) != sizeof(uint32_t)) { | |||
ssh_set_error(sftp->session, SSH_FATAL, "Short sftp packet!"); | ||||
buffer_free(packet->payload); | buffer_free(packet->payload); | |||
SAFE_FREE(packet); | SAFE_FREE(packet); | |||
sftp_leave_function(); | sftp_leave_function(); | |||
return NULL; | return NULL; | |||
} | } | |||
size = ntohl(size); | size = ntohl(size); | |||
if (channel_read_buffer(sftp->channel, packet->payload, 1, 0) <= 0) { | if (channel_read_buffer(sftp->channel, packet->payload, 1, 0) <= 0) { | |||
/* TODO: check if there are cases where an error needs to be set here * / | ||||
buffer_free(packet->payload); | buffer_free(packet->payload); | |||
SAFE_FREE(packet); | SAFE_FREE(packet); | |||
sftp_leave_function(); | sftp_leave_function(); | |||
return NULL; | return NULL; | |||
} | } | |||
buffer_get_u8(packet->payload, &packet->type); | buffer_get_u8(packet->payload, &packet->type); | |||
if (size > 1) { | if (size > 1) { | |||
if (channel_read_buffer(sftp->channel, packet->payload, size - 1, 0) <= 0) { | if (channel_read_buffer(sftp->channel, packet->payload, size - 1, 0) <= 0) { | |||
/* TODO: check if there are cases where an error needs to be set here */ | ||||
buffer_free(packet->payload); | buffer_free(packet->payload); | |||
SAFE_FREE(packet); | SAFE_FREE(packet); | |||
sftp_leave_function(); | sftp_leave_function(); | |||
return NULL; | return NULL; | |||
} | } | |||
} | } | |||
sftp_leave_function(); | sftp_leave_function(); | |||
return packet; | return packet; | |||
} | } | |||
static void sftp_set_error(SFTP_SESSION *sftp, int errnum) { | static void sftp_set_error(sftp_session sftp, int errnum) { | |||
if (sftp != NULL) { | if (sftp != NULL) { | |||
sftp->errnum = errnum; | sftp->errnum = errnum; | |||
} | } | |||
} | } | |||
/* Get the last sftp error */ | /* Get the last sftp error */ | |||
int sftp_get_error(SFTP_SESSION *sftp) { | int sftp_get_error(sftp_session sftp) { | |||
if (sftp == NULL) { | if (sftp == NULL) { | |||
return -1; | return -1; | |||
} | } | |||
return sftp->errnum; | return sftp->errnum; | |||
} | } | |||
static SFTP_MESSAGE *sftp_message_new(SFTP_SESSION *sftp){ | static sftp_message sftp_message_new(sftp_session sftp){ | |||
SFTP_MESSAGE *msg = NULL; | sftp_message msg = NULL; | |||
sftp_enter_function(); | sftp_enter_function(); | |||
msg = malloc(sizeof(SFTP_MESSAGE)); | msg = malloc(sizeof(struct sftp_message_struct)); | |||
if (msg == NULL) { | if (msg == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
return NULL; | return NULL; | |||
} | } | |||
ZERO_STRUCTP(msg); | ZERO_STRUCTP(msg); | |||
msg->payload = buffer_new(); | msg->payload = buffer_new(); | |||
if (msg->payload == NULL) { | if (msg->payload == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
SAFE_FREE(msg); | SAFE_FREE(msg); | |||
return NULL; | return NULL; | |||
} | } | |||
msg->sftp = sftp; | msg->sftp = sftp; | |||
sftp_leave_function(); | sftp_leave_function(); | |||
return msg; | return msg; | |||
} | } | |||
static void sftp_message_free(SFTP_MESSAGE *msg) { | static void sftp_message_free(sftp_message msg) { | |||
SFTP_SESSION *sftp; | sftp_session sftp; | |||
if (msg == NULL) { | if (msg == NULL) { | |||
return; | return; | |||
} | } | |||
sftp = msg->sftp; | sftp = msg->sftp; | |||
sftp_enter_function(); | sftp_enter_function(); | |||
buffer_free(msg->payload); | buffer_free(msg->payload); | |||
SAFE_FREE(msg); | SAFE_FREE(msg); | |||
sftp_leave_function(); | sftp_leave_function(); | |||
} | } | |||
static SFTP_MESSAGE *sftp_get_message(SFTP_PACKET *packet) { | static sftp_message sftp_get_message(sftp_packet packet) { | |||
SFTP_SESSION *sftp = packet->sftp; | sftp_session sftp = packet->sftp; | |||
SFTP_MESSAGE *msg = NULL; | sftp_message msg = NULL; | |||
sftp_enter_function(); | sftp_enter_function(); | |||
msg = sftp_message_new(sftp); | msg = sftp_message_new(sftp); | |||
if (msg == NULL) { | if (msg == NULL) { | |||
sftp_leave_function(); | sftp_leave_function(); | |||
return NULL; | return NULL; | |||
} | } | |||
msg->sftp = packet->sftp; | msg->sftp = packet->sftp; | |||
msg->packet_type = packet->type; | msg->packet_type = packet->type; | |||
if ((packet->type != SSH_FXP_STATUS) && (packet->type!=SSH_FXP_HANDLE) && | if ((packet->type != SSH_FXP_STATUS) && (packet->type!=SSH_FXP_HANDLE) && | |||
(packet->type != SSH_FXP_DATA) && (packet->type != SSH_FXP_ATTRS) && | (packet->type != SSH_FXP_DATA) && (packet->type != SSH_FXP_ATTRS) && | |||
(packet->type != SSH_FXP_NAME)) { | (packet->type != SSH_FXP_NAME) && (packet->type != SSH_FXP_EXTENDED_R EPLY)) { | |||
ssh_set_error(packet->sftp->session, SSH_FATAL, | ssh_set_error(packet->sftp->session, SSH_FATAL, | |||
"Unknown packet type %d", packet->type); | "Unknown packet type %d", packet->type); | |||
sftp_message_free(msg); | sftp_message_free(msg); | |||
sftp_leave_function(); | sftp_leave_function(); | |||
return NULL; | return NULL; | |||
} | } | |||
if (buffer_get_u32(packet->payload, &msg->id) != sizeof(u32)) { | if (buffer_get_u32(packet->payload, &msg->id) != sizeof(uint32_t)) { | |||
ssh_set_error(packet->sftp->session, SSH_FATAL, | ssh_set_error(packet->sftp->session, SSH_FATAL, | |||
"Invalid packet %d: no ID", packet->type); | "Invalid packet %d: no ID", packet->type); | |||
sftp_message_free(msg); | sftp_message_free(msg); | |||
sftp_leave_function(); | sftp_leave_function(); | |||
return NULL; | return NULL; | |||
} | } | |||
ssh_log(packet->sftp->session, SSH_LOG_PACKET, | ssh_log(packet->sftp->session, SSH_LOG_PACKET, | |||
"Packet with id %d type %d", | "Packet with id %d type %d", | |||
msg->id, | msg->id, | |||
msg->packet_type); | msg->packet_type); | |||
if (buffer_add_data(msg->payload, buffer_get_rest(packet->payload), | if (buffer_add_data(msg->payload, buffer_get_rest(packet->payload), | |||
buffer_get_rest_len(packet->payload)) < 0) { | buffer_get_rest_len(packet->payload)) < 0) { | |||
ssh_set_error_oom(sftp->session); | ||||
sftp_message_free(msg); | sftp_message_free(msg); | |||
sftp_leave_function(); | sftp_leave_function(); | |||
return NULL; | return NULL; | |||
} | } | |||
sftp_leave_function(); | sftp_leave_function(); | |||
return msg; | return msg; | |||
} | } | |||
static int sftp_read_and_dispatch(SFTP_SESSION *sftp) { | static int sftp_read_and_dispatch(sftp_session sftp) { | |||
SFTP_PACKET *packet = NULL; | sftp_packet packet = NULL; | |||
SFTP_MESSAGE *msg = NULL; | sftp_message msg = NULL; | |||
sftp_enter_function(); | sftp_enter_function(); | |||
packet = sftp_packet_read(sftp); | packet = sftp_packet_read(sftp); | |||
if (packet == NULL) { | if (packet == NULL) { | |||
sftp_leave_function(); | sftp_leave_function(); | |||
return -1; /* something nasty happened reading the packet */ | return -1; /* something nasty happened reading the packet */ | |||
} | } | |||
msg = sftp_get_message(packet); | msg = sftp_get_message(packet); | |||
skipping to change at line 409 | skipping to change at line 481 | |||
if (sftp_enqueue(sftp, msg) < 0) { | if (sftp_enqueue(sftp, msg) < 0) { | |||
sftp_message_free(msg); | sftp_message_free(msg); | |||
sftp_leave_function(); | sftp_leave_function(); | |||
return -1; | return -1; | |||
} | } | |||
sftp_leave_function(); | sftp_leave_function(); | |||
return 0; | return 0; | |||
} | } | |||
void sftp_packet_free(SFTP_PACKET *packet) { | void sftp_packet_free(sftp_packet packet) { | |||
if (packet == NULL) { | if (packet == NULL) { | |||
return; | return; | |||
} | } | |||
buffer_free(packet->payload); | buffer_free(packet->payload); | |||
free(packet); | free(packet); | |||
} | } | |||
/* Initialize the sftp session with the server. */ | /* Initialize the sftp session with the server. */ | |||
int sftp_init(SFTP_SESSION *sftp) { | int sftp_init(sftp_session sftp) { | |||
SFTP_PACKET *packet = NULL; | sftp_packet packet = NULL; | |||
BUFFER *buffer = NULL; | ssh_buffer buffer = NULL; | |||
STRING *ext_name_s = NULL; | ssh_string ext_name_s = NULL; | |||
STRING *ext_data_s = NULL; | ssh_string ext_data_s = NULL; | |||
char *ext_name = NULL; | char *ext_name = NULL; | |||
char *ext_data = NULL; | char *ext_data = NULL; | |||
u32 version = htonl(LIBSFTP_VERSION); | uint32_t version = htonl(LIBSFTP_VERSION); | |||
sftp_enter_function(); | sftp_enter_function(); | |||
buffer = buffer_new(); | buffer = buffer_new(); | |||
if (buffer == NULL) { | if (buffer == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
sftp_leave_function(); | sftp_leave_function(); | |||
return -1; | return -1; | |||
} | } | |||
if ((buffer_add_u32(buffer, version) < 0) || | if (buffer_add_u32(buffer, version) < 0) { | |||
sftp_packet_write(sftp, SSH_FXP_INIT, buffer) < 0) { | ssh_set_error_oom(sftp->session); | |||
buffer_free(buffer); | ||||
sftp_leave_function(); | ||||
return -1; | ||||
} | ||||
if (sftp_packet_write(sftp, SSH_FXP_INIT, buffer) < 0) { | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
sftp_leave_function(); | sftp_leave_function(); | |||
return -1; | return -1; | |||
} | } | |||
buffer_free(buffer); | buffer_free(buffer); | |||
packet = sftp_packet_read(sftp); | packet = sftp_packet_read(sftp); | |||
if (packet == NULL) { | if (packet == NULL) { | |||
sftp_leave_function(); | sftp_leave_function(); | |||
return -1; | return -1; | |||
} | } | |||
if (packet->type != SSH_FXP_VERSION) { | if (packet->type != SSH_FXP_VERSION) { | |||
ssh_set_error(sftp->session, SSH_FATAL, | ssh_set_error(sftp->session, SSH_FATAL, | |||
"Received a %d messages instead of SSH_FXP_VERSION", packet->type); | "Received a %d messages instead of SSH_FXP_VERSION", packet->type); | |||
sftp_packet_free(packet); | sftp_packet_free(packet); | |||
sftp_leave_function(); | sftp_leave_function(); | |||
return -1; | return -1; | |||
} | } | |||
buffer_get_u32(packet->payload,&version); | /* TODO: are we sure there are 4 bytes ready? */ | |||
buffer_get_u32(packet->payload, &version); | ||||
version = ntohl(version); | version = ntohl(version); | |||
ssh_log(sftp->session, SSH_LOG_RARE, | ||||
"SFTP server version %d", | ||||
version); | ||||
ext_name_s = buffer_get_ssh_string(packet->payload); | ext_name_s = buffer_get_ssh_string(packet->payload); | |||
ext_data_s = buffer_get_ssh_string(packet->payload); | while (ext_name_s != NULL) { | |||
if (ext_name_s == NULL || (ext_data_s == NULL)) { | int count = sftp->ext->count; | |||
string_free(ext_name_s); | char **tmp; | |||
string_free(ext_data_s); | ||||
ssh_log(sftp->session, SSH_LOG_RARE, | ext_data_s = buffer_get_ssh_string(packet->payload); | |||
"SFTP server version %d", version); | if (ext_data_s == NULL) { | |||
} else { | string_free(ext_name_s); | |||
break; | ||||
} | ||||
ext_name = string_to_char(ext_name_s); | ext_name = string_to_char(ext_name_s); | |||
ext_data = string_to_char(ext_data_s); | ext_data = string_to_char(ext_data_s); | |||
if (ext_name == NULL || ext_data == NULL) { | ||||
ssh_set_error_oom(sftp->session); | ||||
SAFE_FREE(ext_name); | ||||
SAFE_FREE(ext_data); | ||||
string_free(ext_name_s); | ||||
string_free(ext_data_s); | ||||
return -1; | ||||
} | ||||
ssh_log(sftp->session, SSH_LOG_RARE, | ||||
"SFTP server extension: %s, version: %s", | ||||
ext_name, ext_data); | ||||
if (ext_name != NULL || ext_data != NULL) { | count++; | |||
ssh_log(sftp->session, SSH_LOG_RARE, | tmp = realloc(sftp->ext->name, count * sizeof(char *)); | |||
"SFTP server version %d (%s,%s)", | if (tmp == NULL) { | |||
version, ext_name, ext_data); | ssh_set_error_oom(sftp->session); | |||
} else { | SAFE_FREE(ext_name); | |||
ssh_log(sftp->session, SSH_LOG_RARE, | SAFE_FREE(ext_data); | |||
"SFTP server version %d", version); | string_free(ext_name_s); | |||
string_free(ext_data_s); | ||||
return -1; | ||||
} | ||||
tmp[count - 1] = ext_name; | ||||
sftp->ext->name = tmp; | ||||
tmp = realloc(sftp->ext->data, count * sizeof(char *)); | ||||
if (tmp == NULL) { | ||||
ssh_set_error_oom(sftp->session); | ||||
SAFE_FREE(ext_name); | ||||
SAFE_FREE(ext_data); | ||||
string_free(ext_name_s); | ||||
string_free(ext_data_s); | ||||
return -1; | ||||
} | } | |||
SAFE_FREE(ext_name); | tmp[count - 1] = ext_data; | |||
SAFE_FREE(ext_data); | sftp->ext->data = tmp; | |||
sftp->ext->count = count; | ||||
string_free(ext_name_s); | ||||
string_free(ext_data_s); | ||||
ext_name_s = buffer_get_ssh_string(packet->payload); | ||||
} | } | |||
string_free(ext_name_s); | ||||
string_free(ext_data_s); | ||||
sftp_packet_free(packet); | sftp_packet_free(packet); | |||
sftp->version = sftp->server_version = version; | sftp->version = sftp->server_version = version; | |||
sftp_leave_function(); | sftp_leave_function(); | |||
return 0; | return 0; | |||
} | } | |||
static REQUEST_QUEUE *request_queue_new(SFTP_MESSAGE *msg) { | unsigned int sftp_extensions_get_count(sftp_session sftp) { | |||
REQUEST_QUEUE *queue = NULL; | if (sftp == NULL || sftp->ext == NULL) { | |||
return 0; | ||||
} | ||||
return sftp->ext->count; | ||||
} | ||||
queue = malloc(sizeof(REQUEST_QUEUE)); | const char *sftp_extensions_get_name(sftp_session sftp, unsigned int idx) { | |||
if (sftp == NULL) | ||||
return NULL; | ||||
if (sftp->ext == NULL || sftp->ext->name == NULL) { | ||||
ssh_set_error_invalid(sftp->session, __FUNCTION__); | ||||
return NULL; | ||||
} | ||||
if (idx > sftp->ext->count) { | ||||
ssh_set_error_invalid(sftp->session, __FUNCTION__); | ||||
return NULL; | ||||
} | ||||
return sftp->ext->name[idx]; | ||||
} | ||||
const char *sftp_extensions_get_data(sftp_session sftp, unsigned int idx) { | ||||
if (sftp == NULL) | ||||
return NULL; | ||||
if (sftp->ext == NULL || sftp->ext->name == NULL) { | ||||
ssh_set_error_invalid(sftp->session, __FUNCTION__); | ||||
return NULL; | ||||
} | ||||
if (idx > sftp->ext->count) { | ||||
ssh_set_error_invalid(sftp->session, __FUNCTION__); | ||||
return NULL; | ||||
} | ||||
return sftp->ext->data[idx]; | ||||
} | ||||
int sftp_extension_supported(sftp_session sftp, const char *name, | ||||
const char *data) { | ||||
int i, n; | ||||
n = sftp_extensions_get_count(sftp); | ||||
for (i = 0; i < n; i++) { | ||||
if (strcmp(sftp_extensions_get_name(sftp, i), name) == 0 && | ||||
strcmp(sftp_extensions_get_data(sftp, i), data) == 0) { | ||||
return 1; | ||||
} | ||||
} | ||||
return 0; | ||||
} | ||||
static sftp_request_queue request_queue_new(sftp_message msg) { | ||||
sftp_request_queue queue = NULL; | ||||
queue = malloc(sizeof(struct sftp_request_queue_struct)); | ||||
if (queue == NULL) { | if (queue == NULL) { | |||
ssh_set_error_oom(msg->sftp->session); | ||||
return NULL; | return NULL; | |||
} | } | |||
ZERO_STRUCTP(queue); | ZERO_STRUCTP(queue); | |||
queue->message = msg; | queue->message = msg; | |||
return queue; | return queue; | |||
} | } | |||
static void request_queue_free(REQUEST_QUEUE *queue) { | static void request_queue_free(sftp_request_queue queue) { | |||
if (queue == NULL) { | if (queue == NULL) { | |||
return; | return; | |||
} | } | |||
ZERO_STRUCTP(queue); | ZERO_STRUCTP(queue); | |||
SAFE_FREE(queue); | SAFE_FREE(queue); | |||
} | } | |||
static int sftp_enqueue(SFTP_SESSION *sftp, SFTP_MESSAGE *msg) { | static int sftp_enqueue(sftp_session sftp, sftp_message msg) { | |||
REQUEST_QUEUE *queue = NULL; | sftp_request_queue queue = NULL; | |||
REQUEST_QUEUE *ptr; | sftp_request_queue ptr; | |||
queue = request_queue_new(msg); | queue = request_queue_new(msg); | |||
if (queue == NULL) { | if (queue == NULL) { | |||
return -1; | return -1; | |||
} | } | |||
ssh_log(sftp->session, SSH_LOG_PACKET, | ssh_log(sftp->session, SSH_LOG_PACKET, | |||
"Queued msg type %d id %d", | "Queued msg type %d id %d", | |||
msg->id, msg->packet_type); | msg->id, msg->packet_type); | |||
skipping to change at line 547 | skipping to change at line 719 | |||
ptr->next = queue; /* add it on bottom */ | ptr->next = queue; /* add it on bottom */ | |||
} | } | |||
return 0; | return 0; | |||
} | } | |||
/* | /* | |||
* Pulls of a message from the queue based on the ID. | * Pulls of a message from the queue based on the ID. | |||
* Returns NULL if no message has been found. | * Returns NULL if no message has been found. | |||
*/ | */ | |||
static SFTP_MESSAGE *sftp_dequeue(SFTP_SESSION *sftp, u32 id){ | static sftp_message sftp_dequeue(sftp_session sftp, uint32_t id){ | |||
REQUEST_QUEUE *prev = NULL; | sftp_request_queue prev = NULL; | |||
REQUEST_QUEUE *queue; | sftp_request_queue queue; | |||
SFTP_MESSAGE *msg; | sftp_message msg; | |||
if(sftp->queue == NULL) { | if(sftp->queue == NULL) { | |||
return NULL; | return NULL; | |||
} | } | |||
queue = sftp->queue; | queue = sftp->queue; | |||
while (queue) { | while (queue) { | |||
if(queue->message->id == id) { | if(queue->message->id == id) { | |||
/* remove from queue */ | /* remove from queue */ | |||
if (prev == NULL) { | if (prev == NULL) { | |||
skipping to change at line 585 | skipping to change at line 757 | |||
} | } | |||
return NULL; | return NULL; | |||
} | } | |||
/* | /* | |||
* Assigns a new SFTP ID for new requests and assures there is no collision | * Assigns a new SFTP ID for new requests and assures there is no collision | |||
* between them. | * between them. | |||
* Returns a new ID ready to use in a request | * Returns a new ID ready to use in a request | |||
*/ | */ | |||
static inline u32 sftp_get_new_id(SFTP_SESSION *session) { | static inline uint32_t sftp_get_new_id(sftp_session session) { | |||
return ++session->id_counter; | return ++session->id_counter; | |||
} | } | |||
static STATUS_MESSAGE *parse_status_msg(SFTP_MESSAGE *msg){ | static sftp_status_message parse_status_msg(sftp_message msg){ | |||
STATUS_MESSAGE *status; | sftp_status_message status; | |||
if (msg->packet_type != SSH_FXP_STATUS) { | if (msg->packet_type != SSH_FXP_STATUS) { | |||
ssh_set_error(msg->sftp->session, SSH_FATAL, | ssh_set_error(msg->sftp->session, SSH_FATAL, | |||
"Not a ssh_fxp_status message passed in!"); | "Not a ssh_fxp_status message passed in!"); | |||
return NULL; | return NULL; | |||
} | } | |||
status = malloc(sizeof(STATUS_MESSAGE)); | status = malloc(sizeof(struct sftp_status_message_struct)); | |||
if (status == NULL) { | if (status == NULL) { | |||
ssh_set_error_oom(msg->sftp->session); | ||||
return NULL; | return NULL; | |||
} | } | |||
ZERO_STRUCTP(status); | ZERO_STRUCTP(status); | |||
status->id = msg->id; | status->id = msg->id; | |||
if ((buffer_get_u32(msg->payload,&status->status) != 4) || | if (buffer_get_u32(msg->payload,&status->status) != 4){ | |||
(status->error = buffer_get_ssh_string(msg->payload)) == NULL || | ||||
(status->lang = buffer_get_ssh_string(msg->payload)) == NULL) { | ||||
string_free(status->error); | ||||
/* status->lang never get allocated if something failed */ | ||||
SAFE_FREE(status); | SAFE_FREE(status); | |||
ssh_set_error(msg->sftp->session, SSH_FATAL, | ssh_set_error(msg->sftp->session, SSH_FATAL, | |||
"Invalid SSH_FXP_STATUS message"); | "Invalid SSH_FXP_STATUS message"); | |||
return NULL; | return NULL; | |||
} | } | |||
status->error = buffer_get_ssh_string(msg->payload); | ||||
status->lang = buffer_get_ssh_string(msg->payload); | ||||
if(status->error == NULL || status->lang == NULL){ | ||||
if(msg->sftp->version >=3){ | ||||
/* These are mandatory from version 3 */ | ||||
string_free(status->error); | ||||
/* status->lang never get allocated if something failed */ | ||||
SAFE_FREE(status); | ||||
ssh_set_error(msg->sftp->session, SSH_FATAL, | ||||
"Invalid SSH_FXP_STATUS message"); | ||||
return NULL; | ||||
} | ||||
} | ||||
status->status = ntohl(status->status); | status->status = ntohl(status->status); | |||
status->errormsg = string_to_char(status->error); | if(status->error) | |||
status->langmsg = string_to_char(status->lang); | status->errormsg = string_to_char(status->error); | |||
else | ||||
status->errormsg = strdup("No error message in packet"); | ||||
if(status->lang) | ||||
status->langmsg = string_to_char(status->lang); | ||||
else | ||||
status->langmsg = strdup(""); | ||||
if (status->errormsg == NULL || status->langmsg == NULL) { | if (status->errormsg == NULL || status->langmsg == NULL) { | |||
ssh_set_error_oom(msg->sftp->session); | ||||
status_msg_free(status); | status_msg_free(status); | |||
return NULL; | return NULL; | |||
} | } | |||
return status; | return status; | |||
} | } | |||
static void status_msg_free(STATUS_MESSAGE *status){ | static void status_msg_free(sftp_status_message status){ | |||
if (status == NULL) { | if (status == NULL) { | |||
return; | return; | |||
} | } | |||
string_free(status->error); | string_free(status->error); | |||
string_free(status->lang); | string_free(status->lang); | |||
SAFE_FREE(status->errormsg); | SAFE_FREE(status->errormsg); | |||
SAFE_FREE(status->langmsg); | SAFE_FREE(status->langmsg); | |||
SAFE_FREE(status); | SAFE_FREE(status); | |||
} | } | |||
static SFTP_FILE *parse_handle_msg(SFTP_MESSAGE *msg){ | static sftp_file parse_handle_msg(sftp_message msg){ | |||
SFTP_FILE *file; | sftp_file file; | |||
if(msg->packet_type != SSH_FXP_HANDLE) { | if(msg->packet_type != SSH_FXP_HANDLE) { | |||
ssh_set_error(msg->sftp->session, SSH_FATAL, | ssh_set_error(msg->sftp->session, SSH_FATAL, | |||
"Not a ssh_fxp_handle message passed in!"); | "Not a ssh_fxp_handle message passed in!"); | |||
return NULL; | return NULL; | |||
} | } | |||
file = malloc(sizeof(SFTP_FILE)); | file = malloc(sizeof(struct sftp_file_struct)); | |||
if (file == NULL) { | if (file == NULL) { | |||
ssh_set_error_oom(msg->sftp->session); | ||||
return NULL; | return NULL; | |||
} | } | |||
ZERO_STRUCTP(file); | ZERO_STRUCTP(file); | |||
file->handle = buffer_get_ssh_string(msg->payload); | file->handle = buffer_get_ssh_string(msg->payload); | |||
if (file->handle == NULL) { | if (file->handle == NULL) { | |||
ssh_set_error(msg->sftp->session, SSH_FATAL, | ssh_set_error(msg->sftp->session, SSH_FATAL, | |||
"Invalid SSH_FXP_HANDLE message"); | "Invalid SSH_FXP_HANDLE message"); | |||
SAFE_FREE(file); | SAFE_FREE(file); | |||
return NULL; | return NULL; | |||
} | } | |||
file->sftp = msg->sftp; | file->sftp = msg->sftp; | |||
file->offset = 0; | file->offset = 0; | |||
file->eof = 0; | file->eof = 0; | |||
return file; | return file; | |||
} | } | |||
/* Open a directory */ | /* Open a directory */ | |||
SFTP_DIR *sftp_opendir(SFTP_SESSION *sftp, const char *path){ | sftp_dir sftp_opendir(sftp_session sftp, const char *path){ | |||
SFTP_MESSAGE *msg = NULL; | sftp_message msg = NULL; | |||
SFTP_FILE *file = NULL; | sftp_file file = NULL; | |||
SFTP_DIR *dir = NULL; | sftp_dir dir = NULL; | |||
STATUS_MESSAGE *status; | sftp_status_message status; | |||
STRING *path_s; | ssh_string path_s; | |||
BUFFER *payload; | ssh_buffer payload; | |||
u32 id; | uint32_t id; | |||
payload = buffer_new(); | payload = buffer_new(); | |||
if (payload == NULL) { | if (payload == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
return NULL; | return NULL; | |||
} | } | |||
path_s = string_from_char(path); | path_s = string_from_char(path); | |||
if (path_s == NULL) { | if (path_s == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
buffer_free(payload); | buffer_free(payload); | |||
return NULL; | return NULL; | |||
} | } | |||
id = sftp_get_new_id(sftp); | id = sftp_get_new_id(sftp); | |||
if (buffer_add_u32(payload, id) < 0 || | if (buffer_add_u32(payload, id) < 0 || | |||
buffer_add_ssh_string(payload, path_s) < 0) { | buffer_add_ssh_string(payload, path_s) < 0) { | |||
ssh_set_error_oom(sftp->session); | ||||
buffer_free(payload); | buffer_free(payload); | |||
string_free(path_s); | string_free(path_s); | |||
return NULL; | return NULL; | |||
} | } | |||
string_free(path_s); | string_free(path_s); | |||
if (sftp_packet_write(sftp, SSH_FXP_OPENDIR, payload) < 0) { | if (sftp_packet_write(sftp, SSH_FXP_OPENDIR, payload) < 0) { | |||
buffer_free(payload); | buffer_free(payload); | |||
return NULL; | return NULL; | |||
} | } | |||
skipping to change at line 729 | skipping to change at line 922 | |||
} | } | |||
sftp_set_error(sftp, status->status); | sftp_set_error(sftp, status->status); | |||
ssh_set_error(sftp->session, SSH_REQUEST_DENIED, | ssh_set_error(sftp->session, SSH_REQUEST_DENIED, | |||
"SFTP server: %s", status->errormsg); | "SFTP server: %s", status->errormsg); | |||
status_msg_free(status); | status_msg_free(status); | |||
return NULL; | return NULL; | |||
case SSH_FXP_HANDLE: | case SSH_FXP_HANDLE: | |||
file = parse_handle_msg(msg); | file = parse_handle_msg(msg); | |||
sftp_message_free(msg); | sftp_message_free(msg); | |||
if (file != NULL) { | if (file != NULL) { | |||
dir = malloc(sizeof(SFTP_DIR)); | dir = malloc(sizeof(struct sftp_dir_struct)); | |||
if (dir == NULL) { | if (dir == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
return NULL; | return NULL; | |||
} | } | |||
ZERO_STRUCTP(dir); | ZERO_STRUCTP(dir); | |||
dir->sftp = sftp; | dir->sftp = sftp; | |||
dir->name = strdup(path); | dir->name = strdup(path); | |||
if (dir->name == NULL) { | if (dir->name == NULL) { | |||
SAFE_FREE(dir); | SAFE_FREE(dir); | |||
SAFE_FREE(file); | SAFE_FREE(file); | |||
return NULL; | return NULL; | |||
skipping to change at line 760 | skipping to change at line 954 | |||
} | } | |||
return NULL; | return NULL; | |||
} | } | |||
/* | /* | |||
* Parse the attributes from a payload from some messages. It is coded on | * Parse the attributes from a payload from some messages. It is coded on | |||
* baselines from the protocol version 4. | * baselines from the protocol version 4. | |||
* This code is more or less dead but maybe we need it in future. | * This code is more or less dead but maybe we need it in future. | |||
*/ | */ | |||
static SFTP_ATTRIBUTES *sftp_parse_attr_4(SFTP_SESSION *sftp, BUFFER *buf, | static sftp_attributes sftp_parse_attr_4(sftp_session sftp, ssh_buffer buf, | |||
int expectnames) { | int expectnames) { | |||
SFTP_ATTRIBUTES *attr; | sftp_attributes attr; | |||
STRING *owner = NULL; | ssh_string owner = NULL; | |||
STRING *group = NULL; | ssh_string group = NULL; | |||
u32 flags = 0; | uint32_t flags = 0; | |||
int ok = 0; | int ok = 0; | |||
/* unused member variable */ | /* unused member variable */ | |||
(void) expectnames; | (void) expectnames; | |||
attr = malloc(sizeof(SFTP_ATTRIBUTES)); | attr = malloc(sizeof(struct sftp_attributes_struct)); | |||
if (attr == NULL) { | if (attr == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
return NULL; | return NULL; | |||
} | } | |||
ZERO_STRUCTP(attr); | ZERO_STRUCTP(attr); | |||
/* This isn't really a loop, but it is like a try..catch.. */ | /* This isn't really a loop, but it is like a try..catch.. */ | |||
do { | do { | |||
if (buffer_get_u32(buf, &flags) != 4) { | if (buffer_get_u32(buf, &flags) != 4) { | |||
break; | break; | |||
} | } | |||
skipping to change at line 810 | skipping to change at line 1005 | |||
break; | break; | |||
} | } | |||
} | } | |||
if (flags & SSH_FILEXFER_ATTR_PERMISSIONS) { | if (flags & SSH_FILEXFER_ATTR_PERMISSIONS) { | |||
if (buffer_get_u32(buf, &attr->permissions) != 4) { | if (buffer_get_u32(buf, &attr->permissions) != 4) { | |||
break; | break; | |||
} | } | |||
attr->permissions = ntohl(attr->permissions); | attr->permissions = ntohl(attr->permissions); | |||
#ifndef _WIN32 | ||||
/* FIXME on windows! */ | /* FIXME on windows! */ | |||
switch (attr->permissions & S_IFMT) { | switch (attr->permissions & S_IFMT) { | |||
case S_IFSOCK: | case S_IFSOCK: | |||
case S_IFBLK: | case S_IFBLK: | |||
case S_IFCHR: | case S_IFCHR: | |||
case S_IFIFO: | case S_IFIFO: | |||
attr->type = SSH_FILEXFER_TYPE_SPECIAL; | attr->type = SSH_FILEXFER_TYPE_SPECIAL; | |||
break; | break; | |||
case S_IFLNK: | case S_IFLNK: | |||
attr->type = SSH_FILEXFER_TYPE_SYMLINK; | attr->type = SSH_FILEXFER_TYPE_SYMLINK; | |||
skipping to change at line 832 | skipping to change at line 1026 | |||
case S_IFREG: | case S_IFREG: | |||
attr->type = SSH_FILEXFER_TYPE_REGULAR; | attr->type = SSH_FILEXFER_TYPE_REGULAR; | |||
break; | break; | |||
case S_IFDIR: | case S_IFDIR: | |||
attr->type = SSH_FILEXFER_TYPE_DIRECTORY; | attr->type = SSH_FILEXFER_TYPE_DIRECTORY; | |||
break; | break; | |||
default: | default: | |||
attr->type = SSH_FILEXFER_TYPE_UNKNOWN; | attr->type = SSH_FILEXFER_TYPE_UNKNOWN; | |||
break; | break; | |||
} | } | |||
#endif /* _WIN32 */ | ||||
} | } | |||
if (flags & SSH_FILEXFER_ATTR_ACCESSTIME) { | if (flags & SSH_FILEXFER_ATTR_ACCESSTIME) { | |||
if (buffer_get_u64(buf, &attr->atime64) != 8) { | if (buffer_get_u64(buf, &attr->atime64) != 8) { | |||
break; | break; | |||
} | } | |||
attr->atime64 = ntohll(attr->atime64); | attr->atime64 = ntohll(attr->atime64); | |||
} | } | |||
if (flags & SSH_FILEXFER_ATTR_SUBSECOND_TIMES) { | if (flags & SSH_FILEXFER_ATTR_SUBSECOND_TIMES) { | |||
skipping to change at line 921 | skipping to change at line 1114 | |||
SAFE_FREE(attr); | SAFE_FREE(attr); | |||
ssh_set_error(sftp->session, SSH_FATAL, "Invalid ATTR structure"); | ssh_set_error(sftp->session, SSH_FATAL, "Invalid ATTR structure"); | |||
return NULL; | return NULL; | |||
} | } | |||
return attr; | return attr; | |||
} | } | |||
/* Version 3 code. it is the only one really supported (the draft for the 4 misses clarifications) */ | /* sftp version 0-3 code. It is different from the v4 */ | |||
/* maybe a paste of the draft is better than the code */ | /* maybe a paste of the draft is better than the code */ | |||
/* | /* | |||
uint32 flags | uint32 flags | |||
uint64 size present only if flag SSH_FILEXFER_ATTR_SIZE | uint64 size present only if flag SSH_FILEXFER_ATTR_SIZE | |||
uint32 uid present only if flag SSH_FILEXFER_ATTR_UIDG ID | uint32 uid present only if flag SSH_FILEXFER_ATTR_UIDG ID | |||
uint32 gid present only if flag SSH_FILEXFER_ATTR_UIDG ID | uint32 gid present only if flag SSH_FILEXFER_ATTR_UIDG ID | |||
uint32 permissions present only if flag SSH_FILEXFER_ATTR_PERM ISSIONS | uint32 permissions present only if flag SSH_FILEXFER_ATTR_PERM ISSIONS | |||
uint32 atime present only if flag SSH_FILEXFER_ACMODTIME | uint32 atime present only if flag SSH_FILEXFER_ACMODTIME | |||
uint32 mtime present only if flag SSH_FILEXFER_ACMODTIME | uint32 mtime present only if flag SSH_FILEXFER_ACMODTIME | |||
uint32 extended_count present only if flag SSH_FILEXFER_ATTR_EXTE NDED | uint32 extended_count present only if flag SSH_FILEXFER_ATTR_EXTE NDED | |||
string extended_type | string extended_type | |||
string extended_data | string extended_data | |||
... more extended data (extended_type - extended_data pairs), | ... more extended data (extended_type - extended_data pairs), | |||
so that number of pairs equals extended_count */ | so that number of pairs equals extended_count */ | |||
static SFTP_ATTRIBUTES *sftp_parse_attr_3(SFTP_SESSION *sftp, BUFFER *buf, | static sftp_attributes sftp_parse_attr_3(sftp_session sftp, ssh_buffer buf, | |||
int expectname) { | int expectname) { | |||
STRING *longname = NULL; | ssh_string longname = NULL; | |||
STRING *name = NULL; | ssh_string name = NULL; | |||
SFTP_ATTRIBUTES *attr; | sftp_attributes attr; | |||
u32 flags = 0; | uint32_t flags = 0; | |||
int ok = 0; | int ok = 0; | |||
attr = malloc(sizeof(SFTP_ATTRIBUTES)); | attr = malloc(sizeof(struct sftp_attributes_struct)); | |||
if (attr == NULL) { | if (attr == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
return NULL; | return NULL; | |||
} | } | |||
ZERO_STRUCTP(attr); | ZERO_STRUCTP(attr); | |||
/* This isn't really a loop, but it is like a try..catch.. */ | /* This isn't really a loop, but it is like a try..catch.. */ | |||
do { | do { | |||
if (expectname) { | if (expectname) { | |||
if ((name = buffer_get_ssh_string(buf)) == NULL || | if ((name = buffer_get_ssh_string(buf)) == NULL || | |||
(attr->name = string_to_char(name)) == NULL) { | (attr->name = string_to_char(name)) == NULL) { | |||
break; | break; | |||
skipping to change at line 968 | skipping to change at line 1162 | |||
ssh_log(sftp->session, SSH_LOG_RARE, "Name: %s", attr->name); | ssh_log(sftp->session, SSH_LOG_RARE, "Name: %s", attr->name); | |||
if ((longname=buffer_get_ssh_string(buf)) == NULL || | if ((longname=buffer_get_ssh_string(buf)) == NULL || | |||
(attr->longname=string_to_char(longname)) == NULL) { | (attr->longname=string_to_char(longname)) == NULL) { | |||
break; | break; | |||
} | } | |||
string_free(longname); | string_free(longname); | |||
} | } | |||
if (buffer_get_u32(buf, &flags) != sizeof(u32)) { | if (buffer_get_u32(buf, &flags) != sizeof(uint32_t)) { | |||
break; | break; | |||
} | } | |||
flags = ntohl(flags); | flags = ntohl(flags); | |||
attr->flags = flags; | attr->flags = flags; | |||
ssh_log(sftp->session, SSH_LOG_RARE, | ssh_log(sftp->session, SSH_LOG_RARE, | |||
"Flags: %.8lx\n", (long unsigned int) flags); | "Flags: %.8lx\n", (long unsigned int) flags); | |||
if (flags & SSH_FILEXFER_ATTR_SIZE) { | if (flags & SSH_FILEXFER_ATTR_SIZE) { | |||
if(buffer_get_u64(buf, &attr->size) != sizeof(u64)) { | if(buffer_get_u64(buf, &attr->size) != sizeof(uint64_t)) { | |||
break; | break; | |||
} | } | |||
attr->size = ntohll(attr->size); | attr->size = ntohll(attr->size); | |||
ssh_log(sftp->session, SSH_LOG_RARE, | ssh_log(sftp->session, SSH_LOG_RARE, | |||
"Size: %llu\n", | "Size: %llu\n", | |||
(long long unsigned int) attr->size); | (long long unsigned int) attr->size); | |||
} | } | |||
if (flags & SSH_FILEXFER_ATTR_UIDGID) { | if (flags & SSH_FILEXFER_ATTR_UIDGID) { | |||
if (buffer_get_u32(buf, &attr->uid) != sizeof(u32)) { | if (buffer_get_u32(buf, &attr->uid) != sizeof(uint32_t)) { | |||
break; | break; | |||
} | } | |||
if (buffer_get_u32(buf, &attr->gid) != sizeof(u32)) { | if (buffer_get_u32(buf, &attr->gid) != sizeof(uint32_t)) { | |||
break; | break; | |||
} | } | |||
attr->uid = ntohl(attr->uid); | attr->uid = ntohl(attr->uid); | |||
attr->gid = ntohl(attr->gid); | attr->gid = ntohl(attr->gid); | |||
} | } | |||
if (flags & SSH_FILEXFER_ATTR_PERMISSIONS) { | if (flags & SSH_FILEXFER_ATTR_PERMISSIONS) { | |||
if (buffer_get_u32(buf, &attr->permissions) != sizeof(u32)) { | if (buffer_get_u32(buf, &attr->permissions) != sizeof(uint32_t)) { | |||
break; | break; | |||
} | } | |||
attr->permissions = ntohl(attr->permissions); | attr->permissions = ntohl(attr->permissions); | |||
#ifndef _WIN32 | ||||
/* FIXME on windows */ | ||||
switch (attr->permissions & S_IFMT) { | switch (attr->permissions & S_IFMT) { | |||
case S_IFSOCK: | case S_IFSOCK: | |||
case S_IFBLK: | case S_IFBLK: | |||
case S_IFCHR: | case S_IFCHR: | |||
case S_IFIFO: | case S_IFIFO: | |||
attr->type = SSH_FILEXFER_TYPE_SPECIAL; | attr->type = SSH_FILEXFER_TYPE_SPECIAL; | |||
break; | break; | |||
case S_IFLNK: | case S_IFLNK: | |||
attr->type = SSH_FILEXFER_TYPE_SYMLINK; | attr->type = SSH_FILEXFER_TYPE_SYMLINK; | |||
break; | break; | |||
case S_IFREG: | case S_IFREG: | |||
attr->type = SSH_FILEXFER_TYPE_REGULAR; | attr->type = SSH_FILEXFER_TYPE_REGULAR; | |||
break; | break; | |||
case S_IFDIR: | case S_IFDIR: | |||
attr->type = SSH_FILEXFER_TYPE_DIRECTORY; | attr->type = SSH_FILEXFER_TYPE_DIRECTORY; | |||
break; | break; | |||
default: | default: | |||
attr->type = SSH_FILEXFER_TYPE_UNKNOWN; | attr->type = SSH_FILEXFER_TYPE_UNKNOWN; | |||
break; | break; | |||
} | } | |||
#endif /* _WIN32 */ | ||||
} | } | |||
if (flags & SSH_FILEXFER_ATTR_ACMODTIME) { | if (flags & SSH_FILEXFER_ATTR_ACMODTIME) { | |||
if (buffer_get_u32(buf, &attr->atime) != sizeof(u32)) { | if (buffer_get_u32(buf, &attr->atime) != sizeof(uint32_t)) { | |||
break; | break; | |||
} | } | |||
attr->atime = ntohl(attr->atime); | attr->atime = ntohl(attr->atime); | |||
if (buffer_get_u32(buf, &attr->mtime) != sizeof(u32)) { | if (buffer_get_u32(buf, &attr->mtime) != sizeof(uint32_t)) { | |||
break; | break; | |||
} | } | |||
attr->mtime = ntohl(attr->mtime); | attr->mtime = ntohl(attr->mtime); | |||
} | } | |||
if (flags & SSH_FILEXFER_ATTR_EXTENDED) { | if (flags & SSH_FILEXFER_ATTR_EXTENDED) { | |||
if (buffer_get_u32(buf, &attr->extended_count) != sizeof(u32)) { | if (buffer_get_u32(buf, &attr->extended_count) != sizeof(uint32_t)) { | |||
break; | break; | |||
} | } | |||
attr->extended_count = ntohl(attr->extended_count); | attr->extended_count = ntohl(attr->extended_count); | |||
while (attr->extended_count && | while (attr->extended_count && | |||
(attr->extended_type = buffer_get_ssh_string(buf)) | (attr->extended_type = buffer_get_ssh_string(buf)) | |||
&& (attr->extended_data = buffer_get_ssh_string(buf))) { | && (attr->extended_data = buffer_get_ssh_string(buf))) { | |||
attr->extended_count--; | attr->extended_count--; | |||
} | } | |||
skipping to change at line 1078 | skipping to change at line 1269 | |||
ssh_set_error(sftp->session, SSH_FATAL, "Invalid ATTR structure"); | ssh_set_error(sftp->session, SSH_FATAL, "Invalid ATTR structure"); | |||
return NULL; | return NULL; | |||
} | } | |||
/* everything went smoothly */ | /* everything went smoothly */ | |||
return attr; | return attr; | |||
} | } | |||
/* FIXME is this really needed as a public function? */ | /* FIXME is this really needed as a public function? */ | |||
int buffer_add_attributes(BUFFER *buffer, SFTP_ATTRIBUTES *attr) { | int buffer_add_attributes(ssh_buffer buffer, sftp_attributes attr) { | |||
u32 flags = (attr ? attr->flags : 0); | uint32_t flags = (attr ? attr->flags : 0); | |||
flags &= (SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_UIDGID | | flags &= (SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_UIDGID | | |||
SSH_FILEXFER_ATTR_PERMISSIONS | SSH_FILEXFER_ATTR_ACMODTIME); | SSH_FILEXFER_ATTR_PERMISSIONS | SSH_FILEXFER_ATTR_ACMODTIME); | |||
if (buffer_add_u32(buffer, htonl(flags)) < 0) { | if (buffer_add_u32(buffer, htonl(flags)) < 0) { | |||
return -1; | return -1; | |||
} | } | |||
if (attr) { | if (attr) { | |||
if (flags & SSH_FILEXFER_ATTR_SIZE) { | if (flags & SSH_FILEXFER_ATTR_SIZE) { | |||
skipping to change at line 1119 | skipping to change at line 1310 | |||
if (buffer_add_u32(buffer, htonl(attr->atime)) < 0 || | if (buffer_add_u32(buffer, htonl(attr->atime)) < 0 || | |||
buffer_add_u32(buffer, htonl(attr->mtime)) < 0) { | buffer_add_u32(buffer, htonl(attr->mtime)) < 0) { | |||
return -1; | return -1; | |||
} | } | |||
} | } | |||
} | } | |||
return 0; | return 0; | |||
} | } | |||
SFTP_ATTRIBUTES *sftp_parse_attr(SFTP_SESSION *session, BUFFER *buf, | sftp_attributes sftp_parse_attr(sftp_session session, ssh_buffer buf, | |||
int expectname) { | int expectname) { | |||
switch(session->version) { | switch(session->version) { | |||
case 4: | case 4: | |||
return sftp_parse_attr_4(session, buf, expectname); | return sftp_parse_attr_4(session, buf, expectname); | |||
case 3: | case 3: | |||
case 2: | ||||
case 1: | ||||
case 0: | ||||
return sftp_parse_attr_3(session, buf, expectname); | return sftp_parse_attr_3(session, buf, expectname); | |||
default: | default: | |||
ssh_set_error(session->session, SSH_FATAL, | ssh_set_error(session->session, SSH_FATAL, | |||
"Version %d unsupported by client", session->server_version); | "Version %d unsupported by client", session->server_version); | |||
return NULL; | return NULL; | |||
} | } | |||
return NULL; | return NULL; | |||
} | } | |||
/* Get the version of the SFTP protocol supported by the server */ | /* Get the version of the SFTP protocol supported by the server */ | |||
int sftp_server_version(SFTP_SESSION *sftp) { | int sftp_server_version(sftp_session sftp) { | |||
return sftp->server_version; | return sftp->server_version; | |||
} | } | |||
/* Get a single file attributes structure of a directory. */ | /* Get a single file attributes structure of a directory. */ | |||
SFTP_ATTRIBUTES *sftp_readdir(SFTP_SESSION *sftp, SFTP_DIR *dir) { | sftp_attributes sftp_readdir(sftp_session sftp, sftp_dir dir) { | |||
SFTP_MESSAGE *msg = NULL; | sftp_message msg = NULL; | |||
STATUS_MESSAGE *status; | sftp_status_message status; | |||
SFTP_ATTRIBUTES *attr; | sftp_attributes attr; | |||
BUFFER *payload; | ssh_buffer payload; | |||
u32 id; | uint32_t id; | |||
if (dir->buffer == NULL) { | if (dir->buffer == NULL) { | |||
payload = buffer_new(); | payload = buffer_new(); | |||
if (payload == NULL) { | if (payload == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
return NULL; | return NULL; | |||
} | } | |||
id = sftp_get_new_id(sftp); | id = sftp_get_new_id(sftp); | |||
if (buffer_add_u32(payload, id) < 0 || | if (buffer_add_u32(payload, id) < 0 || | |||
buffer_add_ssh_string(payload, dir->handle) < 0) { | buffer_add_ssh_string(payload, dir->handle) < 0) { | |||
ssh_set_error_oom(sftp->session); | ||||
buffer_free(payload); | buffer_free(payload); | |||
return NULL; | return NULL; | |||
} | } | |||
if (sftp_packet_write(sftp, SSH_FXP_READDIR, payload) < 0) { | if (sftp_packet_write(sftp, SSH_FXP_READDIR, payload) < 0) { | |||
buffer_free(payload); | buffer_free(payload); | |||
return NULL; | return NULL; | |||
} | } | |||
buffer_free(payload); | buffer_free(payload); | |||
skipping to change at line 1243 | skipping to change at line 1439 | |||
dir->count--; | dir->count--; | |||
if (dir->count == 0) { | if (dir->count == 0) { | |||
buffer_free(dir->buffer); | buffer_free(dir->buffer); | |||
dir->buffer = NULL; | dir->buffer = NULL; | |||
} | } | |||
return attr; | return attr; | |||
} | } | |||
/* Tell if the directory has reached EOF (End Of File). */ | /* Tell if the directory has reached EOF (End Of File). */ | |||
int sftp_dir_eof(SFTP_DIR *dir) { | int sftp_dir_eof(sftp_dir dir) { | |||
return dir->eof; | return dir->eof; | |||
} | } | |||
/* Free a SFTP_ATTRIBUTE handle */ | /* Free a SFTP_ATTRIBUTE handle */ | |||
void sftp_attributes_free(SFTP_ATTRIBUTES *file){ | void sftp_attributes_free(sftp_attributes file){ | |||
if (file == NULL) { | if (file == NULL) { | |||
return; | return; | |||
} | } | |||
string_free(file->acl); | string_free(file->acl); | |||
string_free(file->extended_data); | string_free(file->extended_data); | |||
string_free(file->extended_type); | string_free(file->extended_type); | |||
SAFE_FREE(file->name); | SAFE_FREE(file->name); | |||
SAFE_FREE(file->longname); | SAFE_FREE(file->longname); | |||
SAFE_FREE(file->group); | SAFE_FREE(file->group); | |||
SAFE_FREE(file->owner); | SAFE_FREE(file->owner); | |||
SAFE_FREE(file); | SAFE_FREE(file); | |||
} | } | |||
static int sftp_handle_close(SFTP_SESSION *sftp, STRING *handle) { | static int sftp_handle_close(sftp_session sftp, ssh_string handle) { | |||
STATUS_MESSAGE *status; | sftp_status_message status; | |||
SFTP_MESSAGE *msg = NULL; | sftp_message msg = NULL; | |||
BUFFER *buffer = NULL; | ssh_buffer buffer = NULL; | |||
u32 id; | uint32_t id; | |||
buffer = buffer_new(); | buffer = buffer_new(); | |||
if (buffer == NULL) { | if (buffer == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
return -1; | return -1; | |||
} | } | |||
id = sftp_get_new_id(sftp); | id = sftp_get_new_id(sftp); | |||
if (buffer_add_u32(buffer, id) < 0 || | if (buffer_add_u32(buffer, id) < 0 || | |||
buffer_add_ssh_string(buffer, handle) < 0 || | buffer_add_ssh_string(buffer, handle) < 0) { | |||
sftp_packet_write(sftp, SSH_FXP_CLOSE ,buffer) < 0) { | ssh_set_error_oom(sftp->session); | |||
buffer_free(buffer); | ||||
return -1; | ||||
} | ||||
if (sftp_packet_write(sftp, SSH_FXP_CLOSE ,buffer) < 0) { | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
return -1; | return -1; | |||
} | } | |||
buffer_free(buffer); | buffer_free(buffer); | |||
while (msg == NULL) { | while (msg == NULL) { | |||
if (sftp_read_and_dispatch(sftp) < 0) { | if (sftp_read_and_dispatch(sftp) < 0) { | |||
/* something nasty has happened */ | /* something nasty has happened */ | |||
return -1; | return -1; | |||
} | } | |||
skipping to change at line 1322 | skipping to change at line 1523 | |||
return -1; | return -1; | |||
default: | default: | |||
ssh_set_error(sftp->session, SSH_FATAL, | ssh_set_error(sftp->session, SSH_FATAL, | |||
"Received message %d during sftp_handle_close!", msg->packet_type ); | "Received message %d during sftp_handle_close!", msg->packet_type ); | |||
sftp_message_free(msg); | sftp_message_free(msg); | |||
} | } | |||
return -1; | return -1; | |||
} | } | |||
int sftp_file_close(SFTP_FILE *file) { | ||||
return sftp_close(file); | ||||
} | ||||
/* Close an open file handle. */ | /* Close an open file handle. */ | |||
int sftp_close(SFTP_FILE *file){ | int sftp_close(sftp_file file){ | |||
int err = SSH_NO_ERROR; | int err = SSH_NO_ERROR; | |||
SAFE_FREE(file->name); | SAFE_FREE(file->name); | |||
if (file->handle){ | if (file->handle){ | |||
err = sftp_handle_close(file->sftp,file->handle); | err = sftp_handle_close(file->sftp,file->handle); | |||
string_free(file->handle); | string_free(file->handle); | |||
} | } | |||
/* FIXME: check server response and implement errno */ | /* FIXME: check server response and implement errno */ | |||
SAFE_FREE(file); | SAFE_FREE(file); | |||
return err; | return err; | |||
} | } | |||
int sftp_dir_close(SFTP_DIR *dir) { | ||||
return sftp_closedir(dir); | ||||
} | ||||
/* Close an open directory. */ | /* Close an open directory. */ | |||
int sftp_closedir(SFTP_DIR *dir){ | int sftp_closedir(sftp_dir dir){ | |||
int err = SSH_NO_ERROR; | int err = SSH_NO_ERROR; | |||
SAFE_FREE(dir->name); | SAFE_FREE(dir->name); | |||
if (dir->handle) { | if (dir->handle) { | |||
err = sftp_handle_close(dir->sftp, dir->handle); | err = sftp_handle_close(dir->sftp, dir->handle); | |||
string_free(dir->handle); | string_free(dir->handle); | |||
} | } | |||
/* FIXME: check server response and implement errno */ | /* FIXME: check server response and implement errno */ | |||
buffer_free(dir->buffer); | buffer_free(dir->buffer); | |||
SAFE_FREE(dir); | SAFE_FREE(dir); | |||
return err; | return err; | |||
} | } | |||
/* Open a file on the server. */ | /* Open a file on the server. */ | |||
SFTP_FILE *sftp_open(SFTP_SESSION *sftp, const char *file, int flags, | sftp_file sftp_open(sftp_session sftp, const char *file, int flags, | |||
mode_t mode) { | mode_t mode) { | |||
SFTP_MESSAGE *msg = NULL; | sftp_message msg = NULL; | |||
STATUS_MESSAGE *status; | sftp_status_message status; | |||
SFTP_ATTRIBUTES attr; | struct sftp_attributes_struct attr; | |||
SFTP_FILE *handle; | sftp_file handle; | |||
STRING *filename; | ssh_string filename; | |||
BUFFER *buffer; | ssh_buffer buffer; | |||
u32 sftp_flags = 0; | uint32_t sftp_flags = 0; | |||
u32 id; | uint32_t id; | |||
buffer = buffer_new(); | buffer = buffer_new(); | |||
if (buffer == NULL) { | if (buffer == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
return NULL; | return NULL; | |||
} | } | |||
filename = string_from_char(file); | filename = string_from_char(file); | |||
if (filename == NULL) { | if (filename == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
return NULL; | return NULL; | |||
} | } | |||
ZERO_STRUCT(attr); | ZERO_STRUCT(attr); | |||
attr.permissions = mode; | attr.permissions = mode; | |||
attr.flags = SSH_FILEXFER_ATTR_PERMISSIONS; | attr.flags = SSH_FILEXFER_ATTR_PERMISSIONS; | |||
if (flags == O_RDONLY) | if (flags == O_RDONLY) | |||
sftp_flags |= SSH_FXF_READ; /* if any of the other flag is set, | sftp_flags |= SSH_FXF_READ; /* if any of the other flag is set, | |||
skipping to change at line 1401 | skipping to change at line 1596 | |||
if (flags & O_WRONLY) | if (flags & O_WRONLY) | |||
sftp_flags |= SSH_FXF_WRITE; | sftp_flags |= SSH_FXF_WRITE; | |||
if (flags & O_RDWR) | if (flags & O_RDWR) | |||
sftp_flags |= (SSH_FXF_WRITE | SSH_FXF_READ); | sftp_flags |= (SSH_FXF_WRITE | SSH_FXF_READ); | |||
if (flags & O_CREAT) | if (flags & O_CREAT) | |||
sftp_flags |= SSH_FXF_CREAT; | sftp_flags |= SSH_FXF_CREAT; | |||
if (flags & O_TRUNC) | if (flags & O_TRUNC) | |||
sftp_flags |= SSH_FXF_TRUNC; | sftp_flags |= SSH_FXF_TRUNC; | |||
if (flags & O_EXCL) | if (flags & O_EXCL) | |||
sftp_flags |= SSH_FXF_EXCL; | sftp_flags |= SSH_FXF_EXCL; | |||
ssh_log(sftp->session,SSH_LOG_PACKET,"Opening file %s with sftp flags %x" ,file,sftp_flags); | ||||
id = sftp_get_new_id(sftp); | id = sftp_get_new_id(sftp); | |||
if (buffer_add_u32(buffer, id) < 0 || | if (buffer_add_u32(buffer, id) < 0 || | |||
buffer_add_ssh_string(buffer, filename) < 0) { | buffer_add_ssh_string(buffer, filename) < 0) { | |||
ssh_set_error_oom(sftp->session); | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
string_free(filename); | string_free(filename); | |||
return NULL; | return NULL; | |||
} | } | |||
string_free(filename); | string_free(filename); | |||
if (buffer_add_u32(buffer, htonl(sftp_flags)) < 0 || | if (buffer_add_u32(buffer, htonl(sftp_flags)) < 0 || | |||
buffer_add_attributes(buffer, &attr) < 0 || | buffer_add_attributes(buffer, &attr) < 0) { | |||
sftp_packet_write(sftp, SSH_FXP_OPEN, buffer) < 0) { | ssh_set_error_oom(sftp->session); | |||
buffer_free(buffer); | ||||
return NULL; | ||||
} | ||||
if (sftp_packet_write(sftp, SSH_FXP_OPEN, buffer) < 0) { | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
return NULL; | return NULL; | |||
} | } | |||
buffer_free(buffer); | buffer_free(buffer); | |||
while (msg == NULL) { | while (msg == NULL) { | |||
if (sftp_read_and_dispatch(sftp) < 0) { | if (sftp_read_and_dispatch(sftp) < 0) { | |||
/* something nasty has happened */ | /* something nasty has happened */ | |||
return NULL; | return NULL; | |||
} | } | |||
skipping to change at line 1453 | skipping to change at line 1653 | |||
return handle; | return handle; | |||
default: | default: | |||
ssh_set_error(sftp->session, SSH_FATAL, | ssh_set_error(sftp->session, SSH_FATAL, | |||
"Received message %d during open!", msg->packet_type); | "Received message %d during open!", msg->packet_type); | |||
sftp_message_free(msg); | sftp_message_free(msg); | |||
} | } | |||
return NULL; | return NULL; | |||
} | } | |||
void sftp_file_set_nonblocking(SFTP_FILE *handle){ | void sftp_file_set_nonblocking(sftp_file handle){ | |||
handle->nonblocking=1; | handle->nonblocking=1; | |||
} | } | |||
void sftp_file_set_blocking(SFTP_FILE *handle){ | void sftp_file_set_blocking(sftp_file handle){ | |||
handle->nonblocking=0; | handle->nonblocking=0; | |||
} | } | |||
/* Read from a file using an opened sftp file handle. */ | /* Read from a file using an opened sftp file handle. */ | |||
ssize_t sftp_read(SFTP_FILE *handle, void *buf, size_t count) { | ssize_t sftp_read(sftp_file handle, void *buf, size_t count) { | |||
SFTP_SESSION *sftp = handle->sftp; | sftp_session sftp = handle->sftp; | |||
SFTP_MESSAGE *msg = NULL; | sftp_message msg = NULL; | |||
STATUS_MESSAGE *status; | sftp_status_message status; | |||
STRING *datastring; | ssh_string datastring; | |||
BUFFER *buffer; | ssh_buffer buffer; | |||
int id; | int id; | |||
if (handle->eof) { | if (handle->eof) { | |||
return 0; | return 0; | |||
} | } | |||
buffer = buffer_new(); | buffer = buffer_new(); | |||
if (buffer == NULL) { | if (buffer == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
return -1; | return -1; | |||
} | } | |||
id = sftp_get_new_id(handle->sftp); | id = sftp_get_new_id(handle->sftp); | |||
if (buffer_add_u32(buffer, id) < 0 || | if (buffer_add_u32(buffer, id) < 0 || | |||
buffer_add_ssh_string(buffer, handle->handle) < 0 || | buffer_add_ssh_string(buffer, handle->handle) < 0 || | |||
buffer_add_u64(buffer, htonll(handle->offset)) < 0 || | buffer_add_u64(buffer, htonll(handle->offset)) < 0 || | |||
buffer_add_u32(buffer,htonl(count)) < 0 || | buffer_add_u32(buffer,htonl(count)) < 0) { | |||
sftp_packet_write(handle->sftp, SSH_FXP_READ, buffer) < 0) { | ssh_set_error_oom(sftp->session); | |||
buffer_free(buffer); | ||||
return -1; | ||||
} | ||||
if (sftp_packet_write(handle->sftp, SSH_FXP_READ, buffer) < 0) { | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
return -1; | return -1; | |||
} | } | |||
buffer_free(buffer); | buffer_free(buffer); | |||
while (msg == NULL) { | while (msg == NULL) { | |||
if (handle->nonblocking) { | if (handle->nonblocking) { | |||
if (channel_poll(handle->sftp->channel, 0) == 0) { | if (channel_poll(handle->sftp->channel, 0) == 0) { | |||
/* we cannot block */ | /* we cannot block */ | |||
return 0; | return 0; | |||
skipping to change at line 1541 | skipping to change at line 1746 | |||
if (string_len(datastring) > count) { | if (string_len(datastring) > count) { | |||
ssh_set_error(sftp->session, SSH_FATAL, | ssh_set_error(sftp->session, SSH_FATAL, | |||
"Received a too big DATA packet from sftp server: " | "Received a too big DATA packet from sftp server: " | |||
"%zu and asked for %zu", | "%zu and asked for %zu", | |||
string_len(datastring), count); | string_len(datastring), count); | |||
string_free(datastring); | string_free(datastring); | |||
return -1; | return -1; | |||
} | } | |||
count = string_len(datastring); | count = string_len(datastring); | |||
handle->offset += count; | handle->offset += count; | |||
memcpy(buf, datastring->string, count); | memcpy(buf, string_data(datastring), count); | |||
string_free(datastring); | string_free(datastring); | |||
return count; | return count; | |||
default: | default: | |||
ssh_set_error(sftp->session, SSH_FATAL, | ssh_set_error(sftp->session, SSH_FATAL, | |||
"Received message %d during read!", msg->packet_type); | "Received message %d during read!", msg->packet_type); | |||
sftp_message_free(msg); | sftp_message_free(msg); | |||
return -1; | return -1; | |||
} | } | |||
return -1; /* not reached */ | return -1; /* not reached */ | |||
} | } | |||
/* Start an asynchronous read from a file using an opened sftp file handle. */ | /* Start an asynchronous read from a file using an opened sftp file handle. */ | |||
int sftp_async_read_begin(SFTP_FILE *file, u32 len){ | int sftp_async_read_begin(sftp_file file, uint32_t len){ | |||
SFTP_SESSION *sftp = file->sftp; | sftp_session sftp = file->sftp; | |||
BUFFER *buffer; | ssh_buffer buffer; | |||
u32 id; | uint32_t id; | |||
sftp_enter_function(); | sftp_enter_function(); | |||
buffer = buffer_new(); | buffer = buffer_new(); | |||
if (buffer == NULL) { | if (buffer == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
return -1; | return -1; | |||
} | } | |||
id = sftp_get_new_id(sftp); | id = sftp_get_new_id(sftp); | |||
if (buffer_add_u32(buffer, id) < 0 || | if (buffer_add_u32(buffer, id) < 0 || | |||
buffer_add_ssh_string(buffer, file->handle) < 0 || | buffer_add_ssh_string(buffer, file->handle) < 0 || | |||
buffer_add_u64(buffer, htonll(file->offset)) < 0 || | buffer_add_u64(buffer, htonll(file->offset)) < 0 || | |||
buffer_add_u32(buffer, htonl(len)) < 0 || | buffer_add_u32(buffer, htonl(len)) < 0) { | |||
sftp_packet_write(sftp, SSH_FXP_READ, buffer) < 0) { | ssh_set_error_oom(sftp->session); | |||
buffer_free(buffer); | ||||
return -1; | ||||
} | ||||
if (sftp_packet_write(sftp, SSH_FXP_READ, buffer) < 0) { | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
return -1; | return -1; | |||
} | } | |||
buffer_free(buffer); | buffer_free(buffer); | |||
file->offset += len; /* assume we'll read len bytes */ | file->offset += len; /* assume we'll read len bytes */ | |||
sftp_leave_function(); | sftp_leave_function(); | |||
return id; | return id; | |||
} | } | |||
/* Wait for an asynchronous read to complete and save the data. */ | /* Wait for an asynchronous read to complete and save the data. */ | |||
int sftp_async_read(SFTP_FILE *file, void *data, u32 size, u32 id){ | int sftp_async_read(sftp_file file, void *data, uint32_t size, uint32_t id) | |||
SFTP_SESSION *sftp = file->sftp; | { | |||
SFTP_MESSAGE *msg = NULL; | sftp_session sftp = file->sftp; | |||
STATUS_MESSAGE *status; | sftp_message msg = NULL; | |||
STRING *datastring; | sftp_status_message status; | |||
ssh_string datastring; | ||||
int err = SSH_OK; | int err = SSH_OK; | |||
u32 len; | uint32_t len; | |||
sftp_enter_function(); | sftp_enter_function(); | |||
if (file->eof) { | if (file->eof) { | |||
sftp_leave_function(); | sftp_leave_function(); | |||
return 0; | return 0; | |||
} | } | |||
/* handle an existing request */ | /* handle an existing request */ | |||
while (msg == NULL) { | while (msg == NULL) { | |||
skipping to change at line 1660 | skipping to change at line 1870 | |||
"%zu and asked for %u", | "%zu and asked for %u", | |||
string_len(datastring), size); | string_len(datastring), size); | |||
string_free(datastring); | string_free(datastring); | |||
sftp_leave_function(); | sftp_leave_function(); | |||
return SSH_ERROR; | return SSH_ERROR; | |||
} | } | |||
len = string_len(datastring); | len = string_len(datastring); | |||
//handle->offset+=len; | //handle->offset+=len; | |||
/* We already have set the offset previously. All we can do is warn t hat the expected len | /* We already have set the offset previously. All we can do is warn t hat the expected len | |||
* and effective lengths are different */ | * and effective lengths are different */ | |||
memcpy(data, datastring->string, len); | memcpy(data, string_data(datastring), len); | |||
string_free(datastring); | string_free(datastring); | |||
sftp_leave_function(); | sftp_leave_function(); | |||
return len; | return len; | |||
default: | default: | |||
ssh_set_error(sftp->session,SSH_FATAL,"Received message %d during rea d!",msg->packet_type); | ssh_set_error(sftp->session,SSH_FATAL,"Received message %d during rea d!",msg->packet_type); | |||
sftp_message_free(msg); | sftp_message_free(msg); | |||
sftp_leave_function(); | sftp_leave_function(); | |||
return SSH_ERROR; | return SSH_ERROR; | |||
} | } | |||
sftp_leave_function(); | sftp_leave_function(); | |||
return SSH_ERROR; | return SSH_ERROR; | |||
} | } | |||
ssize_t sftp_write(SFTP_FILE *file, const void *buf, size_t count) { | ssize_t sftp_write(sftp_file file, const void *buf, size_t count) { | |||
SFTP_SESSION *sftp = file->sftp; | sftp_session sftp = file->sftp; | |||
SFTP_MESSAGE *msg = NULL; | sftp_message msg = NULL; | |||
STATUS_MESSAGE *status; | sftp_status_message status; | |||
STRING *datastring; | ssh_string datastring; | |||
BUFFER *buffer; | ssh_buffer buffer; | |||
u32 id; | uint32_t id; | |||
int len; | int len; | |||
int packetlen; | int packetlen; | |||
buffer = buffer_new(); | buffer = buffer_new(); | |||
if (buffer == NULL) { | if (buffer == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
return -1; | return -1; | |||
} | } | |||
datastring = string_new(count); | datastring = string_new(count); | |||
if (datastring == NULL) { | if (datastring == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
return -1; | return -1; | |||
} | } | |||
string_fill(datastring, buf, count); | string_fill(datastring, buf, count); | |||
id = sftp_get_new_id(file->sftp); | id = sftp_get_new_id(file->sftp); | |||
if (buffer_add_u32(buffer, id) < 0 || | if (buffer_add_u32(buffer, id) < 0 || | |||
buffer_add_ssh_string(buffer, file->handle) < 0 || | buffer_add_ssh_string(buffer, file->handle) < 0 || | |||
buffer_add_u64(buffer, htonll(file->offset)) < 0 || | buffer_add_u64(buffer, htonll(file->offset)) < 0 || | |||
buffer_add_ssh_string(buffer, datastring) < 0) { | buffer_add_ssh_string(buffer, datastring) < 0) { | |||
ssh_set_error_oom(sftp->session); | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
string_free(datastring); | string_free(datastring); | |||
return -1; | return -1; | |||
} | } | |||
string_free(datastring); | string_free(datastring); | |||
len = sftp_packet_write(file->sftp, SSH_FXP_WRITE, buffer); | len = sftp_packet_write(file->sftp, SSH_FXP_WRITE, buffer); | |||
packetlen=buffer_get_len(buffer); | packetlen=buffer_get_len(buffer); | |||
buffer_free(buffer); | buffer_free(buffer); | |||
if (len < 0) { | if (len < 0) { | |||
return -1; | return -1; | |||
skipping to change at line 1757 | skipping to change at line 1970 | |||
ssh_set_error(sftp->session, SSH_FATAL, | ssh_set_error(sftp->session, SSH_FATAL, | |||
"Received message %d during write!", msg->packet_type); | "Received message %d during write!", msg->packet_type); | |||
sftp_message_free(msg); | sftp_message_free(msg); | |||
return -1; | return -1; | |||
} | } | |||
return -1; /* not reached */ | return -1; /* not reached */ | |||
} | } | |||
/* Seek to a specific location in a file. */ | /* Seek to a specific location in a file. */ | |||
int sftp_seek(SFTP_FILE *file, u32 new_offset) { | int sftp_seek(sftp_file file, uint32_t new_offset) { | |||
if (file == NULL) { | if (file == NULL) { | |||
return -1; | return -1; | |||
} | } | |||
file->offset = new_offset; | file->offset = new_offset; | |||
return 0; | return 0; | |||
} | } | |||
int sftp_seek64(SFTP_FILE *file, u64 new_offset) { | int sftp_seek64(sftp_file file, uint64_t new_offset) { | |||
if (file == NULL) { | if (file == NULL) { | |||
return -1; | return -1; | |||
} | } | |||
file->offset = new_offset; | file->offset = new_offset; | |||
return 0; | return 0; | |||
} | } | |||
/* Report current byte position in file. */ | /* Report current byte position in file. */ | |||
unsigned long sftp_tell(SFTP_FILE *file) { | unsigned long sftp_tell(sftp_file file) { | |||
return (unsigned long)file->offset; | return (unsigned long)file->offset; | |||
} | } | |||
/* Report current byte position in file. */ | /* Report current byte position in file. */ | |||
u64 sftp_tell64(SFTP_FILE *file) { | uint64_t sftp_tell64(sftp_file file) { | |||
return (u64)file->offset; | return (uint64_t) file->offset; | |||
} | } | |||
/* Rewinds the position of the file pointer to the beginning of the file.*/ | /* Rewinds the position of the file pointer to the beginning of the file.*/ | |||
void sftp_rewind(SFTP_FILE *file) { | void sftp_rewind(sftp_file file) { | |||
file->offset = 0; | file->offset = 0; | |||
} | } | |||
/* deprecated */ | ||||
int sftp_rm(SFTP_SESSION *sftp, const char *file) { | ||||
return sftp_unlink(sftp, file); | ||||
} | ||||
/* code written by Nick */ | /* code written by Nick */ | |||
int sftp_unlink(SFTP_SESSION *sftp, const char *file) { | int sftp_unlink(sftp_session sftp, const char *file) { | |||
STATUS_MESSAGE *status = NULL; | sftp_status_message status = NULL; | |||
SFTP_MESSAGE *msg = NULL; | sftp_message msg = NULL; | |||
STRING *filename; | ssh_string filename; | |||
BUFFER *buffer; | ssh_buffer buffer; | |||
u32 id; | uint32_t id; | |||
buffer = buffer_new(); | buffer = buffer_new(); | |||
if (buffer == NULL) { | if (buffer == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
return -1; | return -1; | |||
} | } | |||
filename = string_from_char(file); | filename = string_from_char(file); | |||
if (filename == NULL) { | if (filename == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
return -1; | return -1; | |||
} | } | |||
id = sftp_get_new_id(sftp); | id = sftp_get_new_id(sftp); | |||
if (buffer_add_u32(buffer, id) < 0 || | if (buffer_add_u32(buffer, id) < 0 || | |||
buffer_add_ssh_string(buffer, filename) < 0 || | buffer_add_ssh_string(buffer, filename) < 0) { | |||
sftp_packet_write(sftp, SSH_FXP_REMOVE, buffer) < 0) { | ssh_set_error_oom(sftp->session); | |||
buffer_free(buffer); | ||||
string_free(filename); | ||||
} | ||||
if (sftp_packet_write(sftp, SSH_FXP_REMOVE, buffer) < 0) { | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
string_free(filename); | string_free(filename); | |||
} | } | |||
string_free(filename); | string_free(filename); | |||
buffer_free(buffer); | buffer_free(buffer); | |||
while (msg == NULL) { | while (msg == NULL) { | |||
if (sftp_read_and_dispatch(sftp)) { | if (sftp_read_and_dispatch(sftp)) { | |||
return -1; | return -1; | |||
} | } | |||
skipping to change at line 1866 | skipping to change at line 2080 | |||
} else { | } else { | |||
ssh_set_error(sftp->session,SSH_FATAL, | ssh_set_error(sftp->session,SSH_FATAL, | |||
"Received message %d when attempting to remove file", msg->packet_t ype); | "Received message %d when attempting to remove file", msg->packet_t ype); | |||
sftp_message_free(msg); | sftp_message_free(msg); | |||
} | } | |||
return -1; | return -1; | |||
} | } | |||
/* code written by Nick */ | /* code written by Nick */ | |||
int sftp_rmdir(SFTP_SESSION *sftp, const char *directory) { | int sftp_rmdir(sftp_session sftp, const char *directory) { | |||
STATUS_MESSAGE *status = NULL; | sftp_status_message status = NULL; | |||
SFTP_MESSAGE *msg = NULL; | sftp_message msg = NULL; | |||
STRING *filename; | ssh_string filename; | |||
BUFFER *buffer; | ssh_buffer buffer; | |||
u32 id; | uint32_t id; | |||
buffer = buffer_new(); | buffer = buffer_new(); | |||
if (buffer == NULL) { | if (buffer == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
return -1; | return -1; | |||
} | } | |||
filename = string_from_char(directory); | filename = string_from_char(directory); | |||
if (filename == NULL) { | if (filename == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
return -1; | return -1; | |||
} | } | |||
id = sftp_get_new_id(sftp); | id = sftp_get_new_id(sftp); | |||
if (buffer_add_u32(buffer, id) < 0 || | if (buffer_add_u32(buffer, id) < 0 || | |||
buffer_add_ssh_string(buffer, filename) < 0 || | buffer_add_ssh_string(buffer, filename) < 0) { | |||
sftp_packet_write(sftp, SSH_FXP_RMDIR, buffer) < 0) { | ssh_set_error_oom(sftp->session); | |||
buffer_free(buffer); | ||||
string_free(filename); | ||||
return -1; | ||||
} | ||||
if (sftp_packet_write(sftp, SSH_FXP_RMDIR, buffer) < 0) { | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
string_free(filename); | string_free(filename); | |||
return -1; | return -1; | |||
} | } | |||
buffer_free(buffer); | buffer_free(buffer); | |||
string_free(filename); | string_free(filename); | |||
while (msg == NULL) { | while (msg == NULL) { | |||
if (sftp_read_and_dispatch(sftp) < 0) { | if (sftp_read_and_dispatch(sftp) < 0) { | |||
return -1; | return -1; | |||
skipping to change at line 1933 | skipping to change at line 2154 | |||
ssh_set_error(sftp->session, SSH_FATAL, | ssh_set_error(sftp->session, SSH_FATAL, | |||
"Received message %d when attempting to remove directory", | "Received message %d when attempting to remove directory", | |||
msg->packet_type); | msg->packet_type); | |||
sftp_message_free(msg); | sftp_message_free(msg); | |||
} | } | |||
return -1; | return -1; | |||
} | } | |||
/* Code written by Nick */ | /* Code written by Nick */ | |||
int sftp_mkdir(SFTP_SESSION *sftp, const char *directory, mode_t mode) { | int sftp_mkdir(sftp_session sftp, const char *directory, mode_t mode) { | |||
STATUS_MESSAGE *status = NULL; | sftp_status_message status = NULL; | |||
SFTP_MESSAGE *msg = NULL; | sftp_message msg = NULL; | |||
SFTP_ATTRIBUTES *errno_attr = NULL; | sftp_attributes errno_attr = NULL; | |||
SFTP_ATTRIBUTES attr; | struct sftp_attributes_struct attr; | |||
BUFFER *buffer; | ssh_buffer buffer; | |||
STRING *path; | ssh_string path; | |||
u32 id; | uint32_t id; | |||
buffer = buffer_new(); | buffer = buffer_new(); | |||
if (buffer == NULL) { | if (buffer == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
return -1; | return -1; | |||
} | } | |||
path = string_from_char(directory); | path = string_from_char(directory); | |||
if (path == NULL) { | if (path == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
return -1; | return -1; | |||
} | } | |||
ZERO_STRUCT(attr); | ZERO_STRUCT(attr); | |||
attr.permissions = mode; | attr.permissions = mode; | |||
attr.flags = SSH_FILEXFER_ATTR_PERMISSIONS; | attr.flags = SSH_FILEXFER_ATTR_PERMISSIONS; | |||
id = sftp_get_new_id(sftp); | id = sftp_get_new_id(sftp); | |||
if (buffer_add_u32(buffer, id) < 0 || | if (buffer_add_u32(buffer, id) < 0 || | |||
skipping to change at line 2022 | skipping to change at line 2245 | |||
ssh_set_error(sftp->session, SSH_FATAL, | ssh_set_error(sftp->session, SSH_FATAL, | |||
"Received message %d when attempting to make directory", | "Received message %d when attempting to make directory", | |||
msg->packet_type); | msg->packet_type); | |||
sftp_message_free(msg); | sftp_message_free(msg); | |||
} | } | |||
return -1; | return -1; | |||
} | } | |||
/* code written by nick */ | /* code written by nick */ | |||
int sftp_rename(SFTP_SESSION *sftp, const char *original, const char *newna | int sftp_rename(sftp_session sftp, const char *original, const char *newnam | |||
me) { | e) { | |||
STATUS_MESSAGE *status = NULL; | sftp_status_message status = NULL; | |||
SFTP_MESSAGE *msg = NULL; | sftp_message msg = NULL; | |||
BUFFER *buffer; | ssh_buffer buffer; | |||
STRING *oldpath; | ssh_string oldpath; | |||
STRING *newpath; | ssh_string newpath; | |||
u32 id; | uint32_t id; | |||
buffer = buffer_new(); | buffer = buffer_new(); | |||
if (buffer == NULL) { | if (buffer == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
return -1; | return -1; | |||
} | } | |||
oldpath = string_from_char(original); | oldpath = string_from_char(original); | |||
if (oldpath == NULL) { | if (oldpath == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
return -1; | return -1; | |||
} | } | |||
newpath = string_from_char(newname); | newpath = string_from_char(newname); | |||
if (newpath == NULL) { | if (newpath == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
string_free(oldpath); | string_free(oldpath); | |||
return -1; | return -1; | |||
} | } | |||
id = sftp_get_new_id(sftp); | id = sftp_get_new_id(sftp); | |||
if (buffer_add_u32(buffer, id) < 0 || | if (buffer_add_u32(buffer, id) < 0 || | |||
buffer_add_ssh_string(buffer, oldpath) < 0 || | buffer_add_ssh_string(buffer, oldpath) < 0 || | |||
buffer_add_ssh_string(buffer, newpath) < 0 || | buffer_add_ssh_string(buffer, newpath) < 0 || | |||
/* POSIX rename atomically replaces newpath, we should do the same */ | /* POSIX rename atomically replaces newpath, we should do the same */ | |||
buffer_add_u32(buffer, SSH_FXF_RENAME_OVERWRITE) < 0 || | buffer_add_u32(buffer, SSH_FXF_RENAME_OVERWRITE) < 0) { | |||
sftp_packet_write(sftp, SSH_FXP_RENAME, buffer) < 0) { | ssh_set_error_oom(sftp->session); | |||
buffer_free(buffer); | ||||
string_free(oldpath); | ||||
string_free(newpath); | ||||
return -1; | ||||
} | ||||
if (sftp_packet_write(sftp, SSH_FXP_RENAME, buffer) < 0) { | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
string_free(oldpath); | string_free(oldpath); | |||
string_free(newpath); | string_free(newpath); | |||
return -1; | return -1; | |||
} | } | |||
buffer_free(buffer); | buffer_free(buffer); | |||
string_free(oldpath); | string_free(oldpath); | |||
string_free(newpath); | string_free(newpath); | |||
while (msg == NULL) { | while (msg == NULL) { | |||
skipping to change at line 2106 | skipping to change at line 2338 | |||
"Received message %d when attempting to rename", | "Received message %d when attempting to rename", | |||
msg->packet_type); | msg->packet_type); | |||
sftp_message_free(msg); | sftp_message_free(msg); | |||
} | } | |||
return -1; | return -1; | |||
} | } | |||
/* Code written by Nick */ | /* Code written by Nick */ | |||
/* Set file attributes on a file, directory or symbolic link. */ | /* Set file attributes on a file, directory or symbolic link. */ | |||
int sftp_setstat(SFTP_SESSION *sftp, const char *file, SFTP_ATTRIBUTES *att | int sftp_setstat(sftp_session sftp, const char *file, sftp_attributes attr) | |||
r) { | { | |||
u32 id = sftp_get_new_id(sftp); | uint32_t id = sftp_get_new_id(sftp); | |||
BUFFER *buffer = buffer_new(); | ssh_buffer buffer = buffer_new(); | |||
STRING *path = string_from_char(file); | ssh_string path = string_from_char(file); | |||
SFTP_MESSAGE *msg = NULL; | sftp_message msg = NULL; | |||
STATUS_MESSAGE *status = NULL; | sftp_status_message status = NULL; | |||
buffer = buffer_new(); | buffer = buffer_new(); | |||
if (buffer == NULL) { | if (buffer == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
return -1; | return -1; | |||
} | } | |||
path = string_from_char(file); | path = string_from_char(file); | |||
if (path == NULL) { | if (path == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
return -1; | return -1; | |||
} | } | |||
id = sftp_get_new_id(sftp); | id = sftp_get_new_id(sftp); | |||
if (buffer_add_u32(buffer, id) < 0 || | if (buffer_add_u32(buffer, id) < 0 || | |||
buffer_add_ssh_string(buffer, path) < 0 || | buffer_add_ssh_string(buffer, path) < 0 || | |||
buffer_add_attributes(buffer, attr) < 0 || | buffer_add_attributes(buffer, attr) < 0) { | |||
sftp_packet_write(sftp, SSH_FXP_SETSTAT, buffer) < 0) { | ssh_set_error_oom(sftp->session); | |||
buffer_free(buffer); | ||||
string_free(path); | ||||
return -1; | ||||
} | ||||
if (sftp_packet_write(sftp, SSH_FXP_SETSTAT, buffer) < 0) { | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
string_free(path); | string_free(path); | |||
return -1; | return -1; | |||
} | } | |||
buffer_free(buffer); | buffer_free(buffer); | |||
string_free(path); | string_free(path); | |||
while (msg == NULL) { | while (msg == NULL) { | |||
if (sftp_read_and_dispatch(sftp) < 0) { | if (sftp_read_and_dispatch(sftp) < 0) { | |||
return -1; | return -1; | |||
skipping to change at line 2176 | skipping to change at line 2415 | |||
} else { | } else { | |||
ssh_set_error(sftp->session, SSH_FATAL, | ssh_set_error(sftp->session, SSH_FATAL, | |||
"Received message %d when attempting to set stats", msg->packet_typ e); | "Received message %d when attempting to set stats", msg->packet_typ e); | |||
sftp_message_free(msg); | sftp_message_free(msg); | |||
} | } | |||
return -1; | return -1; | |||
} | } | |||
/* Change the file owner and group */ | /* Change the file owner and group */ | |||
int sftp_chown(SFTP_SESSION *sftp, const char *file, uid_t owner, gid_t gro | int sftp_chown(sftp_session sftp, const char *file, uid_t owner, gid_t grou | |||
up) { | p) { | |||
SFTP_ATTRIBUTES attr; | struct sftp_attributes_struct attr; | |||
ZERO_STRUCT(attr); | ZERO_STRUCT(attr); | |||
attr.uid = owner; | attr.uid = owner; | |||
attr.gid = group; | attr.gid = group; | |||
attr.flags = SSH_FILEXFER_ATTR_OWNERGROUP; | attr.flags = SSH_FILEXFER_ATTR_OWNERGROUP; | |||
return sftp_setstat(sftp, file, &attr); | return sftp_setstat(sftp, file, &attr); | |||
} | } | |||
/* Change permissions of a file */ | /* Change permissions of a file */ | |||
int sftp_chmod(SFTP_SESSION *sftp, const char *file, mode_t mode) { | int sftp_chmod(sftp_session sftp, const char *file, mode_t mode) { | |||
SFTP_ATTRIBUTES attr; | struct sftp_attributes_struct attr; | |||
ZERO_STRUCT(attr); | ZERO_STRUCT(attr); | |||
attr.permissions = mode; | attr.permissions = mode; | |||
attr.flags = SSH_FILEXFER_ATTR_PERMISSIONS; | attr.flags = SSH_FILEXFER_ATTR_PERMISSIONS; | |||
return sftp_setstat(sftp, file, &attr); | return sftp_setstat(sftp, file, &attr); | |||
} | } | |||
/* Change the last modification and access time of a file. */ | /* Change the last modification and access time of a file. */ | |||
int sftp_utimes(SFTP_SESSION *sftp, const char *file, | int sftp_utimes(sftp_session sftp, const char *file, | |||
const struct timeval *times) { | const struct timeval *times) { | |||
SFTP_ATTRIBUTES attr; | struct sftp_attributes_struct attr; | |||
ZERO_STRUCT(attr); | ZERO_STRUCT(attr); | |||
attr.atime = times[0].tv_sec; | attr.atime = times[0].tv_sec; | |||
attr.atime_nseconds = times[0].tv_usec; | attr.atime_nseconds = times[0].tv_usec; | |||
attr.mtime = times[1].tv_sec; | attr.mtime = times[1].tv_sec; | |||
attr.mtime_nseconds = times[1].tv_usec; | attr.mtime_nseconds = times[1].tv_usec; | |||
attr.flags |= SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_MODIFYTIME | | attr.flags |= SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_MODIFYTIME | | |||
SSH_FILEXFER_ATTR_SUBSECOND_TIMES; | SSH_FILEXFER_ATTR_SUBSECOND_TIMES; | |||
return sftp_setstat(sftp, file, &attr); | return sftp_setstat(sftp, file, &attr); | |||
} | } | |||
int sftp_symlink(SFTP_SESSION *sftp, const char *target, const char *dest) | int sftp_symlink(sftp_session sftp, const char *target, const char *dest) { | |||
{ | sftp_status_message status = NULL; | |||
STATUS_MESSAGE *status = NULL; | sftp_message msg = NULL; | |||
SFTP_MESSAGE *msg = NULL; | ssh_string target_s; | |||
STRING *target_s; | ssh_string dest_s; | |||
STRING *dest_s; | ssh_buffer buffer; | |||
BUFFER *buffer; | uint32_t id; | |||
u32 id; | ||||
if (sftp == NULL || target == NULL || dest == NULL) { | if (sftp == NULL) | |||
return -1; | ||||
if (target == NULL || dest == NULL) { | ||||
ssh_set_error_invalid(sftp->session, __FUNCTION__); | ||||
return -1; | return -1; | |||
} | } | |||
buffer = buffer_new(); | buffer = buffer_new(); | |||
if (buffer == NULL) { | if (buffer == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
return -1; | return -1; | |||
} | } | |||
target_s = string_from_char(target); | target_s = string_from_char(target); | |||
if (target_s == NULL) { | if (target_s == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
return -1; | return -1; | |||
} | } | |||
dest_s = string_from_char(dest); | dest_s = string_from_char(dest); | |||
if (dest_s == NULL) { | if (dest_s == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
string_free(target_s); | string_free(target_s); | |||
buffer_free(buffer); | buffer_free(buffer); | |||
return -1; | return -1; | |||
} | } | |||
id = sftp_get_new_id(sftp); | id = sftp_get_new_id(sftp); | |||
if (buffer_add_u32(buffer, id) < 0) { | if (buffer_add_u32(buffer, id) < 0) { | |||
ssh_set_error_oom(sftp->session); | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
string_free(dest_s); | string_free(dest_s); | |||
string_free(target_s); | string_free(target_s); | |||
return -1; | return -1; | |||
} | } | |||
if (ssh_get_openssh_version(sftp->session)) { | if (ssh_get_openssh_version(sftp->session)) { | |||
/* TODO check for version number if they ever fix it. */ | /* TODO check for version number if they ever fix it. */ | |||
if (buffer_add_ssh_string(buffer, target_s) < 0 || | if (buffer_add_ssh_string(buffer, target_s) < 0 || | |||
buffer_add_ssh_string(buffer, dest_s) < 0) { | buffer_add_ssh_string(buffer, dest_s) < 0) { | |||
ssh_set_error_oom(sftp->session); | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
string_free(dest_s); | string_free(dest_s); | |||
string_free(target_s); | string_free(target_s); | |||
return -1; | return -1; | |||
} | } | |||
} else { | } else { | |||
if (buffer_add_ssh_string(buffer, dest_s) < 0 || | if (buffer_add_ssh_string(buffer, dest_s) < 0 || | |||
buffer_add_ssh_string(buffer, target_s) < 0) { | buffer_add_ssh_string(buffer, target_s) < 0) { | |||
ssh_set_error_oom(sftp->session); | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
string_free(dest_s); | string_free(dest_s); | |||
string_free(target_s); | string_free(target_s); | |||
return -1; | return -1; | |||
} | } | |||
} | } | |||
if (sftp_packet_write(sftp, SSH_FXP_SYMLINK, buffer) < 0) { | if (sftp_packet_write(sftp, SSH_FXP_SYMLINK, buffer) < 0) { | |||
buffer_free(buffer); | buffer_free(buffer); | |||
string_free(dest_s); | string_free(dest_s); | |||
skipping to change at line 2323 | skipping to change at line 2568 | |||
return -1; | return -1; | |||
} else { | } else { | |||
ssh_set_error(sftp->session, SSH_FATAL, | ssh_set_error(sftp->session, SSH_FATAL, | |||
"Received message %d when attempting to set stats", msg->packet_typ e); | "Received message %d when attempting to set stats", msg->packet_typ e); | |||
sftp_message_free(msg); | sftp_message_free(msg); | |||
} | } | |||
return -1; | return -1; | |||
} | } | |||
char *sftp_readlink(SFTP_SESSION *sftp, const char *path) { | char *sftp_readlink(sftp_session sftp, const char *path) { | |||
STATUS_MESSAGE *status = NULL; | sftp_status_message status = NULL; | |||
SFTP_MESSAGE *msg = NULL; | sftp_message msg = NULL; | |||
STRING *path_s = NULL; | ssh_string path_s = NULL; | |||
STRING *link_s = NULL; | ssh_string link_s = NULL; | |||
BUFFER *buffer; | ssh_buffer buffer; | |||
char *link; | char *lnk; | |||
u32 ignored; | uint32_t ignored; | |||
u32 id; | uint32_t id; | |||
if (sftp == NULL || path == NULL) { | if (sftp == NULL) | |||
return NULL; | ||||
if (path == NULL) { | ||||
ssh_set_error_invalid(sftp, __FUNCTION__); | ||||
return NULL; | ||||
} | ||||
if (sftp->version < 3){ | ||||
ssh_set_error(sftp,SSH_REQUEST_DENIED,"sftp version %d does not support | ||||
sftp_readlink",sftp->version); | ||||
return NULL; | return NULL; | |||
} | } | |||
buffer = buffer_new(); | buffer = buffer_new(); | |||
if (buffer == NULL) { | if (buffer == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
return NULL; | return NULL; | |||
} | } | |||
path_s = string_from_char(path); | path_s = string_from_char(path); | |||
if (path_s == NULL) { | if (path_s == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
return NULL; | return NULL; | |||
} | } | |||
id = sftp_get_new_id(sftp); | id = sftp_get_new_id(sftp); | |||
if (buffer_add_u32(buffer, id) < 0 || | if (buffer_add_u32(buffer, id) < 0 || | |||
buffer_add_ssh_string(buffer, path_s) < 0 || | buffer_add_ssh_string(buffer, path_s) < 0) { | |||
sftp_packet_write(sftp, SSH_FXP_READLINK, buffer) < 0) { | ssh_set_error_oom(sftp->session); | |||
buffer_free(buffer); | ||||
string_free(path_s); | ||||
return NULL; | ||||
} | ||||
if (sftp_packet_write(sftp, SSH_FXP_READLINK, buffer) < 0) { | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
string_free(path_s); | string_free(path_s); | |||
return NULL; | return NULL; | |||
} | } | |||
buffer_free(buffer); | buffer_free(buffer); | |||
string_free(path_s); | string_free(path_s); | |||
while (msg == NULL) { | while (msg == NULL) { | |||
if (sftp_read_and_dispatch(sftp) < 0) { | if (sftp_read_and_dispatch(sftp) < 0) { | |||
return NULL; | return NULL; | |||
skipping to change at line 2373 | skipping to change at line 2631 | |||
msg = sftp_dequeue(sftp, id); | msg = sftp_dequeue(sftp, id); | |||
} | } | |||
if (msg->packet_type == SSH_FXP_NAME) { | if (msg->packet_type == SSH_FXP_NAME) { | |||
/* we don't care about "count" */ | /* we don't care about "count" */ | |||
buffer_get_u32(msg->payload, &ignored); | buffer_get_u32(msg->payload, &ignored); | |||
/* we only care about the file name string */ | /* we only care about the file name string */ | |||
link_s = buffer_get_ssh_string(msg->payload); | link_s = buffer_get_ssh_string(msg->payload); | |||
sftp_message_free(msg); | sftp_message_free(msg); | |||
if (link_s == NULL) { | if (link_s == NULL) { | |||
/* TODO: what error to set here? */ | ||||
return NULL; | return NULL; | |||
} | } | |||
link = string_to_char(link_s); | lnk = string_to_char(link_s); | |||
string_free(link_s); | string_free(link_s); | |||
return link; | return lnk; | |||
} else if (msg->packet_type == SSH_FXP_STATUS) { /* bad response (error) */ | } else if (msg->packet_type == SSH_FXP_STATUS) { /* bad response (error) */ | |||
status = parse_status_msg(msg); | status = parse_status_msg(msg); | |||
sftp_message_free(msg); | sftp_message_free(msg); | |||
if (status == NULL) { | if (status == NULL) { | |||
return NULL; | return NULL; | |||
} | } | |||
ssh_set_error(sftp->session, SSH_REQUEST_DENIED, | ssh_set_error(sftp->session, SSH_REQUEST_DENIED, | |||
"SFTP server: %s", status->errormsg); | "SFTP server: %s", status->errormsg); | |||
status_msg_free(status); | status_msg_free(status); | |||
} else { /* this shouldn't happen */ | } else { /* this shouldn't happen */ | |||
ssh_set_error(sftp->session, SSH_FATAL, | ssh_set_error(sftp->session, SSH_FATAL, | |||
"Received message %d when attempting to set stats", msg->packet_typ e); | "Received message %d when attempting to set stats", msg->packet_typ e); | |||
sftp_message_free(msg); | sftp_message_free(msg); | |||
} | } | |||
return NULL; | return NULL; | |||
} | } | |||
static sftp_statvfs_t sftp_parse_statvfs(sftp_session sftp, ssh_buffer buf) | ||||
{ | ||||
sftp_statvfs_t statvfs; | ||||
uint64_t tmp; | ||||
int ok = 0; | ||||
statvfs = malloc(sizeof(struct sftp_statvfs_struct)); | ||||
if (statvfs == NULL) { | ||||
ssh_set_error_oom(sftp->session); | ||||
return NULL; | ||||
} | ||||
ZERO_STRUCTP(statvfs); | ||||
/* try .. catch */ | ||||
do { | ||||
/* file system block size */ | ||||
if (buffer_get_u64(buf, &tmp) != sizeof(uint64_t)) { | ||||
break; | ||||
} | ||||
statvfs->f_bsize = ntohll(tmp); | ||||
/* fundamental fs block size */ | ||||
if (buffer_get_u64(buf, &tmp) != sizeof(uint64_t)) { | ||||
break; | ||||
} | ||||
statvfs->f_frsize = ntohll(tmp); | ||||
/* number of blocks (unit f_frsize) */ | ||||
if (buffer_get_u64(buf, &tmp) != sizeof(uint64_t)) { | ||||
break; | ||||
} | ||||
statvfs->f_blocks = ntohll(tmp); | ||||
/* free blocks in file system */ | ||||
if (buffer_get_u64(buf, &tmp) != sizeof(uint64_t)) { | ||||
break; | ||||
} | ||||
statvfs->f_bfree = ntohll(tmp); | ||||
/* free blocks for non-root */ | ||||
if (buffer_get_u64(buf, &tmp) != sizeof(uint64_t)) { | ||||
break; | ||||
} | ||||
statvfs->f_bavail = ntohll(tmp); | ||||
/* total file inodes */ | ||||
if (buffer_get_u64(buf, &tmp) != sizeof(uint64_t)) { | ||||
break; | ||||
} | ||||
statvfs->f_files = ntohll(tmp); | ||||
/* free file inodes */ | ||||
if (buffer_get_u64(buf, &tmp) != sizeof(uint64_t)) { | ||||
break; | ||||
} | ||||
statvfs->f_ffree = ntohll(tmp); | ||||
/* free file inodes for to non-root */ | ||||
if (buffer_get_u64(buf, &tmp) != sizeof(uint64_t)) { | ||||
break; | ||||
} | ||||
statvfs->f_favail = ntohll(tmp); | ||||
/* file system id */ | ||||
if (buffer_get_u64(buf, &tmp) != sizeof(uint64_t)) { | ||||
break; | ||||
} | ||||
statvfs->f_fsid = ntohll(tmp); | ||||
/* bit mask of f_flag values */ | ||||
if (buffer_get_u64(buf, &tmp) != sizeof(uint64_t)) { | ||||
break; | ||||
} | ||||
statvfs->f_flag = ntohll(tmp); | ||||
/* maximum filename length */ | ||||
if (buffer_get_u64(buf, &tmp) != sizeof(uint64_t)) { | ||||
break; | ||||
} | ||||
statvfs->f_namemax = ntohll(tmp); | ||||
ok = 1; | ||||
} while(0); | ||||
if (!ok) { | ||||
SAFE_FREE(statvfs); | ||||
ssh_set_error(sftp->session, SSH_FATAL, "Invalid statvfs structure"); | ||||
return NULL; | ||||
} | ||||
return statvfs; | ||||
} | ||||
sftp_statvfs_t sftp_statvfs(sftp_session sftp, const char *path) { | ||||
sftp_status_message status = NULL; | ||||
sftp_message msg = NULL; | ||||
ssh_string pathstr; | ||||
ssh_string ext; | ||||
ssh_buffer buffer; | ||||
uint32_t id; | ||||
if (sftp == NULL) | ||||
return NULL; | ||||
if (path == NULL) { | ||||
ssh_set_error_invalid(sftp->session, __FUNCTION__); | ||||
return NULL; | ||||
} | ||||
if (sftp->version < 3){ | ||||
ssh_set_error(sftp,SSH_REQUEST_DENIED,"sftp version %d does not support | ||||
sftp_statvfs",sftp->version); | ||||
return NULL; | ||||
} | ||||
buffer = buffer_new(); | ||||
if (buffer == NULL) { | ||||
ssh_set_error_oom(sftp->session); | ||||
return NULL; | ||||
} | ||||
ext = string_from_char("statvfs@openssh.com"); | ||||
if (ext == NULL) { | ||||
ssh_set_error_oom(sftp->session); | ||||
buffer_free(buffer); | ||||
return NULL; | ||||
} | ||||
pathstr = string_from_char(path); | ||||
if (pathstr == NULL) { | ||||
ssh_set_error_oom(sftp->session); | ||||
buffer_free(buffer); | ||||
string_free(ext); | ||||
return NULL; | ||||
} | ||||
id = sftp_get_new_id(sftp); | ||||
if (buffer_add_u32(buffer, id) < 0 || | ||||
buffer_add_ssh_string(buffer, ext) < 0 || | ||||
buffer_add_ssh_string(buffer, pathstr) < 0) { | ||||
ssh_set_error_oom(sftp->session); | ||||
buffer_free(buffer); | ||||
string_free(ext); | ||||
string_free(pathstr); | ||||
return NULL; | ||||
} | ||||
if (sftp_packet_write(sftp, SSH_FXP_EXTENDED, buffer) < 0) { | ||||
buffer_free(buffer); | ||||
string_free(ext); | ||||
string_free(pathstr); | ||||
return NULL; | ||||
} | ||||
buffer_free(buffer); | ||||
string_free(ext); | ||||
string_free(pathstr); | ||||
while (msg == NULL) { | ||||
if (sftp_read_and_dispatch(sftp) < 0) { | ||||
return NULL; | ||||
} | ||||
msg = sftp_dequeue(sftp, id); | ||||
} | ||||
if (msg->packet_type == SSH_FXP_EXTENDED_REPLY) { | ||||
sftp_statvfs_t buf = sftp_parse_statvfs(sftp, msg->payload); | ||||
sftp_message_free(msg); | ||||
if (buf == NULL) { | ||||
return NULL; | ||||
} | ||||
return buf; | ||||
} else if (msg->packet_type == SSH_FXP_STATUS) { /* bad response (error) | ||||
*/ | ||||
status = parse_status_msg(msg); | ||||
sftp_message_free(msg); | ||||
if (status == NULL) { | ||||
return NULL; | ||||
} | ||||
ssh_set_error(sftp->session, SSH_REQUEST_DENIED, | ||||
"SFTP server: %s", status->errormsg); | ||||
status_msg_free(status); | ||||
} else { /* this shouldn't happen */ | ||||
ssh_set_error(sftp->session, SSH_FATAL, | ||||
"Received message %d when attempting to get statvfs", msg->packet_t | ||||
ype); | ||||
sftp_message_free(msg); | ||||
} | ||||
return NULL; | ||||
} | ||||
sftp_statvfs_t sftp_fstatvfs(sftp_file file) { | ||||
sftp_status_message status = NULL; | ||||
sftp_message msg = NULL; | ||||
sftp_session sftp; | ||||
ssh_string ext; | ||||
ssh_buffer buffer; | ||||
uint32_t id; | ||||
if (file == NULL) { | ||||
return NULL; | ||||
} | ||||
sftp = file->sftp; | ||||
buffer = buffer_new(); | ||||
if (buffer == NULL) { | ||||
ssh_set_error_oom(sftp->session); | ||||
return NULL; | ||||
} | ||||
ext = string_from_char("fstatvfs@openssh.com"); | ||||
if (ext == NULL) { | ||||
ssh_set_error_oom(sftp->session); | ||||
buffer_free(buffer); | ||||
return NULL; | ||||
} | ||||
id = sftp_get_new_id(sftp); | ||||
if (buffer_add_u32(buffer, id) < 0 || | ||||
buffer_add_ssh_string(buffer, ext) < 0 || | ||||
buffer_add_ssh_string(buffer, file->handle) < 0) { | ||||
ssh_set_error_oom(sftp->session); | ||||
buffer_free(buffer); | ||||
string_free(ext); | ||||
return NULL; | ||||
} | ||||
if (sftp_packet_write(sftp, SSH_FXP_EXTENDED, buffer) < 0) { | ||||
buffer_free(buffer); | ||||
string_free(ext); | ||||
return NULL; | ||||
} | ||||
buffer_free(buffer); | ||||
string_free(ext); | ||||
while (msg == NULL) { | ||||
if (sftp_read_and_dispatch(sftp) < 0) { | ||||
return NULL; | ||||
} | ||||
msg = sftp_dequeue(sftp, id); | ||||
} | ||||
if (msg->packet_type == SSH_FXP_EXTENDED_REPLY) { | ||||
sftp_statvfs_t buf = sftp_parse_statvfs(sftp, msg->payload); | ||||
sftp_message_free(msg); | ||||
if (buf == NULL) { | ||||
return NULL; | ||||
} | ||||
return buf; | ||||
} else if (msg->packet_type == SSH_FXP_STATUS) { /* bad response (error) | ||||
*/ | ||||
status = parse_status_msg(msg); | ||||
sftp_message_free(msg); | ||||
if (status == NULL) { | ||||
return NULL; | ||||
} | ||||
ssh_set_error(sftp->session, SSH_REQUEST_DENIED, | ||||
"SFTP server: %s", status->errormsg); | ||||
status_msg_free(status); | ||||
} else { /* this shouldn't happen */ | ||||
ssh_set_error(sftp->session, SSH_FATAL, | ||||
"Received message %d when attempting to set stats", msg->packet_typ | ||||
e); | ||||
sftp_message_free(msg); | ||||
} | ||||
return NULL; | ||||
} | ||||
void sftp_statvfs_free(sftp_statvfs_t statvfs) { | ||||
if (statvfs == NULL) { | ||||
return; | ||||
} | ||||
SAFE_FREE(statvfs); | ||||
} | ||||
/* another code written by Nick */ | /* another code written by Nick */ | |||
char *sftp_canonicalize_path(SFTP_SESSION *sftp, const char *path) { | char *sftp_canonicalize_path(sftp_session sftp, const char *path) { | |||
STATUS_MESSAGE *status = NULL; | sftp_status_message status = NULL; | |||
SFTP_MESSAGE *msg = NULL; | sftp_message msg = NULL; | |||
STRING *name = NULL; | ssh_string name = NULL; | |||
STRING *pathstr; | ssh_string pathstr; | |||
BUFFER *buffer; | ssh_buffer buffer; | |||
char *cname; | char *cname; | |||
u32 ignored; | uint32_t ignored; | |||
u32 id; | uint32_t id; | |||
if (sftp == NULL) | ||||
return NULL; | ||||
if (path == NULL) { | ||||
ssh_set_error_invalid(sftp->session, __FUNCTION__); | ||||
return NULL; | ||||
} | ||||
buffer = buffer_new(); | buffer = buffer_new(); | |||
if (buffer == NULL) { | if (buffer == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
return NULL; | return NULL; | |||
} | } | |||
pathstr = string_from_char(path); | pathstr = string_from_char(path); | |||
if (pathstr == NULL) { | if (pathstr == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
return NULL; | return NULL; | |||
} | } | |||
id = sftp_get_new_id(sftp); | id = sftp_get_new_id(sftp); | |||
if (buffer_add_u32(buffer, id) < 0 || | if (buffer_add_u32(buffer, id) < 0 || | |||
buffer_add_ssh_string(buffer, pathstr) < 0 || | buffer_add_ssh_string(buffer, pathstr) < 0) { | |||
sftp_packet_write(sftp, SSH_FXP_REALPATH, buffer) < 0) { | ssh_set_error_oom(sftp->session); | |||
buffer_free(buffer); | ||||
string_free(pathstr); | ||||
return NULL; | ||||
} | ||||
if (sftp_packet_write(sftp, SSH_FXP_REALPATH, buffer) < 0) { | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
string_free(pathstr); | string_free(pathstr); | |||
return NULL; | return NULL; | |||
} | } | |||
buffer_free(buffer); | buffer_free(buffer); | |||
string_free(pathstr); | string_free(pathstr); | |||
while (msg == NULL) { | while (msg == NULL) { | |||
if (sftp_read_and_dispatch(sftp) < 0) { | if (sftp_read_and_dispatch(sftp) < 0) { | |||
return NULL; | return NULL; | |||
skipping to change at line 2444 | skipping to change at line 2986 | |||
msg = sftp_dequeue(sftp, id); | msg = sftp_dequeue(sftp, id); | |||
} | } | |||
if (msg->packet_type == SSH_FXP_NAME) { | if (msg->packet_type == SSH_FXP_NAME) { | |||
/* we don't care about "count" */ | /* we don't care about "count" */ | |||
buffer_get_u32(msg->payload, &ignored); | buffer_get_u32(msg->payload, &ignored); | |||
/* we only care about the file name string */ | /* we only care about the file name string */ | |||
name = buffer_get_ssh_string(msg->payload); | name = buffer_get_ssh_string(msg->payload); | |||
sftp_message_free(msg); | sftp_message_free(msg); | |||
if (name == NULL) { | if (name == NULL) { | |||
/* TODO: error message? */ | ||||
return NULL; | return NULL; | |||
} | } | |||
cname = string_to_char(name); | cname = string_to_char(name); | |||
string_free(name); | string_free(name); | |||
if (cname == NULL) { | ||||
ssh_set_error_oom(sftp->session); | ||||
} | ||||
return cname; | return cname; | |||
} else if (msg->packet_type == SSH_FXP_STATUS) { /* bad response (error) */ | } else if (msg->packet_type == SSH_FXP_STATUS) { /* bad response (error) */ | |||
status = parse_status_msg(msg); | status = parse_status_msg(msg); | |||
sftp_message_free(msg); | sftp_message_free(msg); | |||
if (status == NULL) { | if (status == NULL) { | |||
return NULL; | return NULL; | |||
} | } | |||
ssh_set_error(sftp->session, SSH_REQUEST_DENIED, | ssh_set_error(sftp->session, SSH_REQUEST_DENIED, | |||
"SFTP server: %s", status->errormsg); | "SFTP server: %s", status->errormsg); | |||
status_msg_free(status); | status_msg_free(status); | |||
} else { /* this shouldn't happen */ | } else { /* this shouldn't happen */ | |||
ssh_set_error(sftp->session, SSH_FATAL, | ssh_set_error(sftp->session, SSH_FATAL, | |||
"Received message %d when attempting to set stats", msg->packet_typ e); | "Received message %d when attempting to set stats", msg->packet_typ e); | |||
sftp_message_free(msg); | sftp_message_free(msg); | |||
} | } | |||
return NULL; | return NULL; | |||
} | } | |||
static SFTP_ATTRIBUTES *sftp_xstat(SFTP_SESSION *sftp, const char *path, | static sftp_attributes sftp_xstat(sftp_session sftp, const char *path, | |||
int param) { | int param) { | |||
STATUS_MESSAGE *status = NULL; | sftp_status_message status = NULL; | |||
SFTP_MESSAGE *msg = NULL; | sftp_message msg = NULL; | |||
STRING *pathstr; | ssh_string pathstr; | |||
BUFFER *buffer; | ssh_buffer buffer; | |||
u32 id; | uint32_t id; | |||
buffer = buffer_new(); | buffer = buffer_new(); | |||
if (buffer == NULL) { | if (buffer == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
return NULL; | return NULL; | |||
} | } | |||
pathstr = string_from_char(path); | pathstr = string_from_char(path); | |||
if (pathstr == NULL) { | if (pathstr == NULL) { | |||
ssh_set_error_oom(sftp->session); | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
return NULL; | return NULL; | |||
} | } | |||
id = sftp_get_new_id(sftp); | id = sftp_get_new_id(sftp); | |||
if (buffer_add_u32(buffer, id) < 0 || | if (buffer_add_u32(buffer, id) < 0 || | |||
buffer_add_ssh_string(buffer, pathstr) < 0 || | buffer_add_ssh_string(buffer, pathstr) < 0) { | |||
sftp_packet_write(sftp, param, buffer) < 0) { | ssh_set_error_oom(sftp->session); | |||
buffer_free(buffer); | ||||
string_free(pathstr); | ||||
return NULL; | ||||
} | ||||
if (sftp_packet_write(sftp, param, buffer) < 0) { | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
string_free(pathstr); | string_free(pathstr); | |||
return NULL; | return NULL; | |||
} | } | |||
buffer_free(buffer); | buffer_free(buffer); | |||
string_free(pathstr); | string_free(pathstr); | |||
while (msg == NULL) { | while (msg == NULL) { | |||
if (sftp_read_and_dispatch(sftp) < 0) { | if (sftp_read_and_dispatch(sftp) < 0) { | |||
return NULL; | return NULL; | |||
skipping to change at line 2526 | skipping to change at line 3078 | |||
status_msg_free(status); | status_msg_free(status); | |||
return NULL; | return NULL; | |||
} | } | |||
ssh_set_error(sftp->session, SSH_FATAL, | ssh_set_error(sftp->session, SSH_FATAL, | |||
"Received mesg %d during stat()", msg->packet_type); | "Received mesg %d during stat()", msg->packet_type); | |||
sftp_message_free(msg); | sftp_message_free(msg); | |||
return NULL; | return NULL; | |||
} | } | |||
SFTP_ATTRIBUTES *sftp_stat(SFTP_SESSION *session, const char *path) { | sftp_attributes sftp_stat(sftp_session session, const char *path) { | |||
return sftp_xstat(session, path, SSH_FXP_STAT); | return sftp_xstat(session, path, SSH_FXP_STAT); | |||
} | } | |||
SFTP_ATTRIBUTES *sftp_lstat(SFTP_SESSION *session, const char *path) { | sftp_attributes sftp_lstat(sftp_session session, const char *path) { | |||
return sftp_xstat(session, path, SSH_FXP_LSTAT); | return sftp_xstat(session, path, SSH_FXP_LSTAT); | |||
} | } | |||
SFTP_ATTRIBUTES *sftp_fstat(SFTP_FILE *file) { | sftp_attributes sftp_fstat(sftp_file file) { | |||
STATUS_MESSAGE *status = NULL; | sftp_status_message status = NULL; | |||
SFTP_MESSAGE *msg = NULL; | sftp_message msg = NULL; | |||
BUFFER *buffer; | ssh_buffer buffer; | |||
u32 id; | uint32_t id; | |||
buffer = buffer_new(); | buffer = buffer_new(); | |||
if (buffer == NULL) { | if (buffer == NULL) { | |||
ssh_set_error_oom(file->sftp->session); | ||||
return NULL; | return NULL; | |||
} | } | |||
id = sftp_get_new_id(file->sftp); | id = sftp_get_new_id(file->sftp); | |||
if (buffer_add_u32(buffer, id) < 0 || | if (buffer_add_u32(buffer, id) < 0 || | |||
buffer_add_ssh_string(buffer, file->handle) < 0 || | buffer_add_ssh_string(buffer, file->handle) < 0) { | |||
sftp_packet_write(file->sftp, SSH_FXP_FSTAT, buffer) < 0) { | ssh_set_error_oom(file->sftp->session); | |||
buffer_free(buffer); | ||||
return NULL; | ||||
} | ||||
if (sftp_packet_write(file->sftp, SSH_FXP_FSTAT, buffer) < 0) { | ||||
buffer_free(buffer); | buffer_free(buffer); | |||
return NULL; | return NULL; | |||
} | } | |||
buffer_free(buffer); | buffer_free(buffer); | |||
while (msg == NULL) { | while (msg == NULL) { | |||
if (sftp_read_and_dispatch(file->sftp) < 0) { | if (sftp_read_and_dispatch(file->sftp) < 0) { | |||
return NULL; | return NULL; | |||
} | } | |||
msg = sftp_dequeue(file->sftp, id); | msg = sftp_dequeue(file->sftp, id); | |||
End of changes. 202 change blocks. | ||||
321 lines changed or deleted | 885 lines changed or added | |||
This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ |