1
0
mirror of https://git.libssh.org/projects/libssh.git synced 2025-08-13 04:42:23 +03:00

buffers: adapt sftp.c to ssh_buffer_(un)pack()

Reviewed-by: Andreas Schneider <asn@samba.org>
This commit is contained in:
Aris Adamantiadis
2014-04-22 18:46:29 +02:00
committed by Andreas Schneider
parent c238136010
commit c341da03d3
2 changed files with 231 additions and 379 deletions

View File

@@ -145,8 +145,8 @@ struct sftp_request_queue_struct {
struct sftp_status_message_struct { struct sftp_status_message_struct {
uint32_t id; uint32_t id;
uint32_t status; uint32_t status;
ssh_string error; ssh_string error_unused; /* not used anymore */
ssh_string lang; ssh_string lang_unused; /* not used anymore */
char *errormsg; char *errormsg;
char *langmsg; char *langmsg;
}; };

View File

@@ -497,11 +497,10 @@ void sftp_packet_free(sftp_packet packet) {
int sftp_init(sftp_session sftp) { int sftp_init(sftp_session sftp) {
sftp_packet packet = NULL; sftp_packet packet = NULL;
ssh_buffer buffer = NULL; ssh_buffer buffer = NULL;
ssh_string ext_name_s = NULL;
ssh_string ext_data_s = NULL;
char *ext_name = NULL; char *ext_name = NULL;
char *ext_data = NULL; char *ext_data = NULL;
uint32_t version = htonl(LIBSFTP_VERSION); uint32_t version;
int rc;
buffer = ssh_buffer_new(); buffer = ssh_buffer_new();
if (buffer == NULL) { if (buffer == NULL) {
@@ -509,7 +508,8 @@ int sftp_init(sftp_session sftp) {
return -1; return -1;
} }
if (buffer_add_u32(buffer, version) < 0) { rc = ssh_buffer_pack(buffer, "d", LIBSFTP_VERSION);
if (rc != SSH_OK) {
ssh_set_error_oom(sftp->session); ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer); ssh_buffer_free(buffer);
return -1; return -1;
@@ -533,68 +533,48 @@ int sftp_init(sftp_session sftp) {
} }
/* TODO: are we sure there are 4 bytes ready? */ /* TODO: are we sure there are 4 bytes ready? */
buffer_get_u32(packet->payload, &version); rc = ssh_buffer_unpack(packet->payload, "d", &version);
version = ntohl(version); if (rc != SSH_OK){
return -1;
}
SSH_LOG(SSH_LOG_RARE, SSH_LOG(SSH_LOG_RARE,
"SFTP server version %d", "SFTP server version %d",
version); version);
rc = ssh_buffer_unpack(packet->payload, "s", &ext_name);
ext_name_s = buffer_get_ssh_string(packet->payload); while (rc == SSH_OK) {
while (ext_name_s != NULL) {
int count = sftp->ext->count; int count = sftp->ext->count;
char **tmp;
ext_data_s = buffer_get_ssh_string(packet->payload); rc = ssh_buffer_unpack(packet->payload, "s", &ext_data);
if (ext_data_s == NULL) { if (rc == SSH_ERROR) {
ssh_string_free(ext_name_s);
break; break;
} }
ext_name = ssh_string_to_char(ext_name_s);
ext_data = ssh_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);
ssh_string_free(ext_name_s);
ssh_string_free(ext_data_s);
return -1;
}
SSH_LOG(SSH_LOG_RARE, SSH_LOG(SSH_LOG_RARE,
"SFTP server extension: %s, version: %s", "SFTP server extension: %s, version: %s",
ext_name, ext_data); ext_name, ext_data);
count++; count++;
tmp = realloc(sftp->ext->name, count * sizeof(char *)); sftp->ext->name = realloc(sftp->ext->name, count * sizeof(char *));
if (tmp == NULL) { if (sftp->ext->name == NULL) {
ssh_set_error_oom(sftp->session); ssh_set_error_oom(sftp->session);
SAFE_FREE(ext_name); SAFE_FREE(ext_name);
SAFE_FREE(ext_data); SAFE_FREE(ext_data);
ssh_string_free(ext_name_s);
ssh_string_free(ext_data_s);
return -1; return -1;
} }
tmp[count - 1] = ext_name; sftp->ext->name[count - 1] = ext_name;
sftp->ext->name = tmp;
tmp = realloc(sftp->ext->data, count * sizeof(char *)); sftp->ext->data = realloc(sftp->ext->data, count * sizeof(char *));
if (tmp == NULL) { if (sftp->ext->data == NULL) {
ssh_set_error_oom(sftp->session); ssh_set_error_oom(sftp->session);
SAFE_FREE(ext_name); SAFE_FREE(ext_name);
SAFE_FREE(ext_data); SAFE_FREE(ext_data);
ssh_string_free(ext_name_s);
ssh_string_free(ext_data_s);
return -1; return -1;
} }
tmp[count - 1] = ext_data; sftp->ext->data[count - 1] = ext_data;
sftp->ext->data = tmp;
sftp->ext->count = count; sftp->ext->count = count;
ssh_string_free(ext_name_s); rc = ssh_buffer_unpack(packet->payload, "s", &ext_name);
ssh_string_free(ext_data_s);
ext_name_s = buffer_get_ssh_string(packet->payload);
} }
sftp_packet_free(packet); sftp_packet_free(packet);
@@ -766,6 +746,7 @@ static inline uint32_t sftp_get_new_id(sftp_session session) {
static sftp_status_message parse_status_msg(sftp_message msg){ static sftp_status_message parse_status_msg(sftp_message msg){
sftp_status_message status; sftp_status_message status;
int rc;
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,
@@ -781,34 +762,28 @@ static sftp_status_message parse_status_msg(sftp_message msg){
ZERO_STRUCTP(status); ZERO_STRUCTP(status);
status->id = msg->id; status->id = msg->id;
if (buffer_get_u32(msg->payload,&status->status) != 4){ rc = ssh_buffer_unpack(msg->payload, "dSS",
&status->status);
if (rc != SSH_OK){
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); rc = ssh_buffer_unpack(msg->payload, "ss",
status->lang = buffer_get_ssh_string(msg->payload); &status->errormsg,
if(status->error == NULL || status->lang == NULL){ &status->langmsg);
if(msg->sftp->version >=3){
/* These are mandatory from version 3 */
ssh_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); if(rc != SSH_OK && msg->sftp->version >=3){
if(status->error) /* These are mandatory from version 3 */
status->errormsg = ssh_string_to_char(status->error); SAFE_FREE(status);
else ssh_set_error(msg->sftp->session, SSH_FATAL,
"Invalid SSH_FXP_STATUS message");
return NULL;
}
if (status->errormsg == NULL)
status->errormsg = strdup("No error message in packet"); status->errormsg = strdup("No error message in packet");
if(status->lang) if (status->langmsg == NULL)
status->langmsg = ssh_string_to_char(status->lang);
else
status->langmsg = strdup(""); status->langmsg = strdup("");
if (status->errormsg == NULL || status->langmsg == NULL) { if (status->errormsg == NULL || status->langmsg == NULL) {
ssh_set_error_oom(msg->sftp->session); ssh_set_error_oom(msg->sftp->session);
@@ -824,8 +799,6 @@ static void status_msg_free(sftp_status_message status){
return; return;
} }
ssh_string_free(status->error);
ssh_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);
@@ -1192,11 +1165,8 @@ static char *sftp_parse_longname(const char *longname,
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, ssh_buffer buf, static sftp_attributes sftp_parse_attr_3(sftp_session sftp, ssh_buffer buf,
int expectname) { int expectname) {
ssh_string longname;
ssh_string name;
sftp_attributes attr; sftp_attributes attr;
uint32_t flags = 0; int rc;
int ok = 0;
attr = malloc(sizeof(struct sftp_attributes_struct)); attr = malloc(sizeof(struct sftp_attributes_struct));
if (attr == NULL) { if (attr == NULL) {
@@ -1205,79 +1175,60 @@ static sftp_attributes sftp_parse_attr_3(sftp_session sftp, ssh_buffer buf,
} }
ZERO_STRUCTP(attr); ZERO_STRUCTP(attr);
/* This isn't really a loop, but it is like a try..catch.. */
do {
if (expectname) { if (expectname) {
name = buffer_get_ssh_string(buf); rc = ssh_buffer_unpack(buf, "ss",
if (name == NULL) { &attr->name,
break; &attr->longname);
if (rc != SSH_OK){
goto error;
} }
attr->name = ssh_string_to_char(name);
ssh_string_free(name);
if (attr->name == NULL) {
break;
}
SSH_LOG(SSH_LOG_RARE, "Name: %s", attr->name); SSH_LOG(SSH_LOG_RARE, "Name: %s", attr->name);
longname = buffer_get_ssh_string(buf);
if (longname == NULL) {
break;
}
attr->longname = ssh_string_to_char(longname);
ssh_string_free(longname);
if (attr->longname == NULL) {
break;
}
/* Set owner and group if we talk to openssh and have the longname */ /* Set owner and group if we talk to openssh and have the longname */
if (ssh_get_openssh_version(sftp->session)) { if (ssh_get_openssh_version(sftp->session)) {
attr->owner = sftp_parse_longname(attr->longname, SFTP_LONGNAME_OWNER); attr->owner = sftp_parse_longname(attr->longname, SFTP_LONGNAME_OWNER);
if (attr->owner == NULL) { if (attr->owner == NULL) {
break; goto error;
} }
attr->group = sftp_parse_longname(attr->longname, SFTP_LONGNAME_GROUP); attr->group = sftp_parse_longname(attr->longname, SFTP_LONGNAME_GROUP);
if (attr->group == NULL) { if (attr->group == NULL) {
break; goto error;
} }
} }
} }
if (buffer_get_u32(buf, &flags) != sizeof(uint32_t)) { rc = ssh_buffer_unpack(buf, "d", &attr->flags);
break; if (rc != SSH_OK){
goto error;
} }
flags = ntohl(flags);
attr->flags = flags;
SSH_LOG(SSH_LOG_RARE, SSH_LOG(SSH_LOG_RARE,
"Flags: %.8lx\n", (long unsigned int) flags); "Flags: %.8lx\n", (long unsigned int) attr->flags);
if (flags & SSH_FILEXFER_ATTR_SIZE) { if (attr->flags & SSH_FILEXFER_ATTR_SIZE) {
if(buffer_get_u64(buf, &attr->size) != sizeof(uint64_t)) { rc = ssh_buffer_unpack(buf, "q", &attr->size);
break; if(rc != SSH_OK) {
goto error;
} }
attr->size = ntohll(attr->size);
SSH_LOG(SSH_LOG_RARE, SSH_LOG(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 (attr->flags & SSH_FILEXFER_ATTR_UIDGID) {
if (buffer_get_u32(buf, &attr->uid) != sizeof(uint32_t)) { rc = ssh_buffer_unpack(buf, "dd",
break; &attr->uid,
&attr->gid);
if (rc != SSH_OK){
goto error;
} }
if (buffer_get_u32(buf, &attr->gid) != sizeof(uint32_t)) {
break;
}
attr->uid = ntohl(attr->uid);
attr->gid = ntohl(attr->gid);
} }
if (flags & SSH_FILEXFER_ATTR_PERMISSIONS) { if (attr->flags & SSH_FILEXFER_ATTR_PERMISSIONS) {
if (buffer_get_u32(buf, &attr->permissions) != sizeof(uint32_t)) { rc = ssh_buffer_unpack(buf, "d", &attr->permissions);
break; if (rc != SSH_OK){
goto error;
} }
attr->permissions = ntohl(attr->permissions);
switch (attr->permissions & S_IFMT) { switch (attr->permissions & S_IFMT) {
case S_IFSOCK: case S_IFSOCK:
@@ -1301,38 +1252,47 @@ static sftp_attributes sftp_parse_attr_3(sftp_session sftp, ssh_buffer buf,
} }
} }
if (flags & SSH_FILEXFER_ATTR_ACMODTIME) { if (attr->flags & SSH_FILEXFER_ATTR_ACMODTIME) {
if (buffer_get_u32(buf, &attr->atime) != sizeof(uint32_t)) { rc = ssh_buffer_unpack(buf, "dd",
break; &attr->atime,
&attr->mtime);
if (rc != SSH_OK){
goto error;
} }
attr->atime = ntohl(attr->atime);
if (buffer_get_u32(buf, &attr->mtime) != sizeof(uint32_t)) {
break;
}
attr->mtime = ntohl(attr->mtime);
} }
if (flags & SSH_FILEXFER_ATTR_EXTENDED) { if (attr->flags & SSH_FILEXFER_ATTR_EXTENDED) {
if (buffer_get_u32(buf, &attr->extended_count) != sizeof(uint32_t)) { rc = ssh_buffer_unpack(buf, "d", &attr->extended_count);
break; if (rc != SSH_OK){
goto error;
} }
attr->extended_count = ntohl(attr->extended_count); if (attr->extended_count > 0){
while (attr->extended_count && rc = ssh_buffer_unpack(buf, "ss",
(attr->extended_type = buffer_get_ssh_string(buf)) &attr->extended_type,
&& (attr->extended_data = buffer_get_ssh_string(buf))) { &attr->extended_data);
if (rc != SSH_OK){
goto error;
}
attr->extended_count--; attr->extended_count--;
} }
/* just ignore the remaining extensions */
if (attr->extended_count) { while (attr->extended_count > 0){
break; ssh_string tmp1,tmp2;
rc = ssh_buffer_unpack(buf, "SS", &tmp1, &tmp2);
if (rc != SSH_OK){
goto error;
}
SAFE_FREE(tmp1);
SAFE_FREE(tmp2);
attr->extended_count--;
} }
} }
ok = 1;
} while (0);
if (!ok) { return attr;
/* break issued somewhere */
error:
ssh_string_free(attr->extended_type); ssh_string_free(attr->extended_type);
ssh_string_free(attr->extended_data); ssh_string_free(attr->extended_data);
SAFE_FREE(attr->name); SAFE_FREE(attr->name);
@@ -1340,55 +1300,53 @@ static sftp_attributes sftp_parse_attr_3(sftp_session sftp, ssh_buffer buf,
SAFE_FREE(attr->owner); SAFE_FREE(attr->owner);
SAFE_FREE(attr->group); SAFE_FREE(attr->group);
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;
}
/* everything went smoothly */
return attr;
} }
/* FIXME is this really needed as a public function? */ /* FIXME is this really needed as a public function? */
int buffer_add_attributes(ssh_buffer buffer, sftp_attributes attr) { int buffer_add_attributes(ssh_buffer buffer, sftp_attributes attr) {
uint32_t flags = (attr ? attr->flags : 0); uint32_t flags = (attr ? attr->flags : 0);
int rc;
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) { rc = ssh_buffer_pack(buffer, "d", flags);
if (rc != SSH_OK) {
return -1; return -1;
} }
if (attr) { if (attr != NULL) {
if (flags & SSH_FILEXFER_ATTR_SIZE) { if (flags & SSH_FILEXFER_ATTR_SIZE) {
if (buffer_add_u64(buffer, htonll(attr->size)) < 0) { rc = ssh_buffer_pack(buffer, "q", attr->size);
if (rc != SSH_OK) {
return -1; return -1;
} }
} }
if (flags & SSH_FILEXFER_ATTR_UIDGID) { if (flags & SSH_FILEXFER_ATTR_UIDGID) {
if (buffer_add_u32(buffer,htonl(attr->uid)) < 0 || rc = ssh_buffer_pack(buffer, "dd", attr->uid, attr->gid);
buffer_add_u32(buffer,htonl(attr->gid)) < 0) { if (rc != SSH_OK) {
return -1; return -1;
} }
} }
if (flags & SSH_FILEXFER_ATTR_PERMISSIONS) { if (flags & SSH_FILEXFER_ATTR_PERMISSIONS) {
if (buffer_add_u32(buffer, htonl(attr->permissions)) < 0) { rc = ssh_buffer_pack(buffer, "d", attr->permissions);
if (rc != SSH_OK) {
return -1; return -1;
} }
} }
if (flags & SSH_FILEXFER_ATTR_ACMODTIME) { if (flags & SSH_FILEXFER_ATTR_ACMODTIME) {
if (buffer_add_u32(buffer, htonl(attr->atime)) < 0 || rc = ssh_buffer_pack(buffer, "dd", attr->atime, attr->mtime);
buffer_add_u32(buffer, htonl(attr->mtime)) < 0) { if (rc != SSH_OK) {
return -1; return -1;
} }
} }
} }
return 0; return 0;
} }
@@ -1751,6 +1709,7 @@ ssize_t sftp_read(sftp_file handle, void *buf, size_t count) {
ssh_string datastring; ssh_string datastring;
ssh_buffer buffer; ssh_buffer buffer;
int id; int id;
int rc;
if (handle->eof) { if (handle->eof) {
return 0; return 0;
@@ -1761,11 +1720,14 @@ ssize_t sftp_read(sftp_file handle, void *buf, size_t count) {
ssh_set_error_oom(sftp->session); ssh_set_error_oom(sftp->session);
return -1; return -1;
} }
id = sftp_get_new_id(handle->sftp); id = ntohl(sftp_get_new_id(handle->sftp));
if (buffer_add_u32(buffer, id) < 0 || rc = ssh_buffer_pack(buffer,
buffer_add_ssh_string(buffer, handle->handle) < 0 || "dSqd",
buffer_add_u64(buffer, htonll(handle->offset)) < 0 || id,
buffer_add_u32(buffer,htonl(count)) < 0) { handle->handle,
handle->offset,
count);
if (rc != SSH_OK){
ssh_set_error_oom(sftp->session); ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer); ssh_buffer_free(buffer);
return -1; return -1;
@@ -1847,6 +1809,7 @@ int sftp_async_read_begin(sftp_file file, uint32_t len){
sftp_session sftp = file->sftp; sftp_session sftp = file->sftp;
ssh_buffer buffer; ssh_buffer buffer;
uint32_t id; uint32_t id;
int rc;
buffer = ssh_buffer_new(); buffer = ssh_buffer_new();
if (buffer == NULL) { if (buffer == NULL) {
@@ -1854,11 +1817,15 @@ int sftp_async_read_begin(sftp_file file, uint32_t len){
return -1; return -1;
} }
id = sftp_get_new_id(sftp); id = ntohl(sftp_get_new_id(sftp));
if (buffer_add_u32(buffer, id) < 0 ||
buffer_add_ssh_string(buffer, file->handle) < 0 || rc = ssh_buffer_pack(buffer,
buffer_add_u64(buffer, htonll(file->offset)) < 0 || "dSqd",
buffer_add_u32(buffer, htonl(len)) < 0) { id,
file->handle,
file->offset,
len);
if (rc != SSH_OK) {
ssh_set_error_oom(sftp->session); ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer); ssh_buffer_free(buffer);
return -1; return -1;
@@ -1961,11 +1928,11 @@ 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;
sftp_status_message status; sftp_status_message status;
ssh_string datastring;
ssh_buffer buffer; ssh_buffer buffer;
uint32_t id; uint32_t id;
int len; int len;
int packetlen; int packetlen;
int rc;
buffer = ssh_buffer_new(); buffer = ssh_buffer_new();
if (buffer == NULL) { if (buffer == NULL) {
@@ -1973,25 +1940,21 @@ ssize_t sftp_write(sftp_file file, const void *buf, size_t count) {
return -1; return -1;
} }
datastring = ssh_string_new(count);
if (datastring == NULL) {
ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer);
return -1;
}
ssh_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 || rc = buffer_add_u32(buffer, id) != 4 ? SSH_ERROR:SSH_OK;
buffer_add_ssh_string(buffer, file->handle) < 0 || if (rc != SSH_ERROR){
buffer_add_u64(buffer, htonll(file->offset)) < 0 || rc = ssh_buffer_pack(buffer,
buffer_add_ssh_string(buffer, datastring) < 0) { "SqdP",
file->handle,
file->offset,
count, /* len of datastring */
(size_t)count, buf);
}
if (rc != SSH_OK){
ssh_set_error_oom(sftp->session); ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer); ssh_buffer_free(buffer);
ssh_string_free(datastring);
return -1; return -1;
} }
ssh_string_free(datastring);
packetlen=buffer_get_rest_len(buffer); packetlen=buffer_get_rest_len(buffer);
len = sftp_packet_write(file->sftp, SSH_FXP_WRITE, buffer); len = sftp_packet_write(file->sftp, SSH_FXP_WRITE, buffer);
ssh_buffer_free(buffer); ssh_buffer_free(buffer);
@@ -2083,9 +2046,9 @@ void sftp_rewind(sftp_file file) {
int sftp_unlink(sftp_session sftp, const char *file) { int sftp_unlink(sftp_session sftp, const char *file) {
sftp_status_message status = NULL; sftp_status_message status = NULL;
sftp_message msg = NULL; sftp_message msg = NULL;
ssh_string filename;
ssh_buffer buffer; ssh_buffer buffer;
uint32_t id; uint32_t id;
int rc;
buffer = ssh_buffer_new(); buffer = ssh_buffer_new();
if (buffer == NULL) { if (buffer == NULL) {
@@ -2093,27 +2056,22 @@ int sftp_unlink(sftp_session sftp, const char *file) {
return -1; return -1;
} }
filename = ssh_string_from_char(file); id = ntohl(sftp_get_new_id(sftp));
if (filename == NULL) {
rc = ssh_buffer_pack(buffer,
"ds",
id,
file);
if (rc != SSH_OK) {
ssh_set_error_oom(sftp->session); ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer); ssh_buffer_free(buffer);
return -1; return -1;
} }
id = sftp_get_new_id(sftp);
if (buffer_add_u32(buffer, id) < 0 ||
buffer_add_ssh_string(buffer, filename) < 0) {
ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer);
ssh_string_free(filename);
return -1;
}
if (sftp_packet_write(sftp, SSH_FXP_REMOVE, buffer) < 0) { if (sftp_packet_write(sftp, SSH_FXP_REMOVE, buffer) < 0) {
ssh_buffer_free(buffer); ssh_buffer_free(buffer);
ssh_string_free(filename);
return -1; return -1;
} }
ssh_string_free(filename);
ssh_buffer_free(buffer); ssh_buffer_free(buffer);
while (msg == NULL) { while (msg == NULL) {
@@ -2160,9 +2118,9 @@ int sftp_unlink(sftp_session sftp, const char *file) {
int sftp_rmdir(sftp_session sftp, const char *directory) { int sftp_rmdir(sftp_session sftp, const char *directory) {
sftp_status_message status = NULL; sftp_status_message status = NULL;
sftp_message msg = NULL; sftp_message msg = NULL;
ssh_string filename;
ssh_buffer buffer; ssh_buffer buffer;
uint32_t id; uint32_t id;
int rc;
buffer = ssh_buffer_new(); buffer = ssh_buffer_new();
if (buffer == NULL) { if (buffer == NULL) {
@@ -2170,28 +2128,22 @@ int sftp_rmdir(sftp_session sftp, const char *directory) {
return -1; return -1;
} }
filename = ssh_string_from_char(directory); id = ntohl(sftp_get_new_id(sftp));
if (filename == NULL) {
ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer);
return -1;
}
id = sftp_get_new_id(sftp); rc = ssh_buffer_pack(buffer,
if (buffer_add_u32(buffer, id) < 0 || "ds",
buffer_add_ssh_string(buffer, filename) < 0) { id,
directory);
if (rc != SSH_OK) {
ssh_set_error_oom(sftp->session); ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer); ssh_buffer_free(buffer);
ssh_string_free(filename);
return -1; return -1;
} }
if (sftp_packet_write(sftp, SSH_FXP_RMDIR, buffer) < 0) { if (sftp_packet_write(sftp, SSH_FXP_RMDIR, buffer) < 0) {
ssh_buffer_free(buffer); ssh_buffer_free(buffer);
ssh_string_free(filename);
return -1; return -1;
} }
ssh_buffer_free(buffer); ssh_buffer_free(buffer);
ssh_string_free(filename);
while (msg == NULL) { while (msg == NULL) {
if (sftp_read_and_dispatch(sftp) < 0) { if (sftp_read_and_dispatch(sftp) < 0) {
@@ -2327,9 +2279,8 @@ int sftp_rename(sftp_session sftp, const char *original, const char *newname) {
sftp_status_message status = NULL; sftp_status_message status = NULL;
sftp_message msg = NULL; sftp_message msg = NULL;
ssh_buffer buffer; ssh_buffer buffer;
ssh_string oldpath;
ssh_string newpath;
uint32_t id; uint32_t id;
int rc;
buffer = ssh_buffer_new(); buffer = ssh_buffer_new();
if (buffer == NULL) { if (buffer == NULL) {
@@ -2337,43 +2288,30 @@ int sftp_rename(sftp_session sftp, const char *original, const char *newname) {
return -1; return -1;
} }
oldpath = ssh_string_from_char(original); id = ntohl(sftp_get_new_id(sftp));
if (oldpath == NULL) {
rc = ssh_buffer_pack(buffer,
"dss",
id,
original,
newname);
if (rc != SSH_OK) {
ssh_set_error_oom(sftp->session); ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer); ssh_buffer_free(buffer);
return -1; return -1;
} }
newpath = ssh_string_from_char(newname); if (sftp->version >= 4){
if (newpath == NULL) {
ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer);
ssh_string_free(oldpath);
return -1;
}
id = sftp_get_new_id(sftp);
if (buffer_add_u32(buffer, id) < 0 ||
buffer_add_ssh_string(buffer, oldpath) < 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
* only available on >=v4 */ * only available on >=v4 */
sftp->version>=4 ? (buffer_add_u32(buffer, SSH_FXF_RENAME_OVERWRITE) < 0):0) { buffer_add_u32(buffer, SSH_FXF_RENAME_OVERWRITE);
ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer);
ssh_string_free(oldpath);
ssh_string_free(newpath);
return -1;
} }
if (sftp_packet_write(sftp, SSH_FXP_RENAME, buffer) < 0) { if (sftp_packet_write(sftp, SSH_FXP_RENAME, buffer) < 0) {
ssh_buffer_free(buffer); ssh_buffer_free(buffer);
ssh_string_free(oldpath);
ssh_string_free(newpath);
return -1; return -1;
} }
ssh_buffer_free(buffer); ssh_buffer_free(buffer);
ssh_string_free(oldpath);
ssh_string_free(newpath);
while (msg == NULL) { while (msg == NULL) {
if (sftp_read_and_dispatch(sftp) < 0) { if (sftp_read_and_dispatch(sftp) < 0) {
@@ -2537,10 +2475,9 @@ int sftp_utimes(sftp_session sftp, const char *file,
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; sftp_status_message status = NULL;
sftp_message msg = NULL; sftp_message msg = NULL;
ssh_string target_s;
ssh_string dest_s;
ssh_buffer buffer; ssh_buffer buffer;
uint32_t id; uint32_t id;
int rc;
if (sftp == NULL) if (sftp == NULL)
return -1; return -1;
@@ -2555,59 +2492,33 @@ int sftp_symlink(sftp_session sftp, const char *target, const char *dest) {
return -1; return -1;
} }
target_s = ssh_string_from_char(target); id = ntohl(sftp_get_new_id(sftp));
if (target_s == NULL) {
ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer);
return -1;
}
dest_s = ssh_string_from_char(dest);
if (dest_s == NULL) {
ssh_set_error_oom(sftp->session);
ssh_string_free(target_s);
ssh_buffer_free(buffer);
return -1;
}
id = sftp_get_new_id(sftp);
if (buffer_add_u32(buffer, id) < 0) {
ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer);
ssh_string_free(dest_s);
ssh_string_free(target_s);
return -1;
}
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 (ssh_get_openssh_version(sftp->session)) {
buffer_add_ssh_string(buffer, dest_s) < 0) { rc = ssh_buffer_pack(buffer,
ssh_set_error_oom(sftp->session); "dss",
ssh_buffer_free(buffer); id,
ssh_string_free(dest_s); target,
ssh_string_free(target_s); dest);
return -1;
}
} else { } else {
if (buffer_add_ssh_string(buffer, dest_s) < 0 || rc = ssh_buffer_pack(buffer,
buffer_add_ssh_string(buffer, target_s) < 0) { "dss",
id,
dest,
target);
}
if (rc != SSH_OK){
ssh_set_error_oom(sftp->session); ssh_set_error_oom(sftp->session);
ssh_buffer_free(buffer); ssh_buffer_free(buffer);
ssh_string_free(dest_s);
ssh_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) {
ssh_buffer_free(buffer); ssh_buffer_free(buffer);
ssh_string_free(dest_s);
ssh_string_free(target_s);
return -1; return -1;
} }
ssh_buffer_free(buffer); ssh_buffer_free(buffer);
ssh_string_free(dest_s);
ssh_string_free(target_s);
while (msg == NULL) { while (msg == NULL) {
if (sftp_read_and_dispatch(sftp) < 0) { if (sftp_read_and_dispatch(sftp) < 0) {
@@ -2738,8 +2649,7 @@ char *sftp_readlink(sftp_session sftp, const char *path) {
static sftp_statvfs_t sftp_parse_statvfs(sftp_session sftp, ssh_buffer buf) { static sftp_statvfs_t sftp_parse_statvfs(sftp_session sftp, ssh_buffer buf) {
sftp_statvfs_t statvfs; sftp_statvfs_t statvfs;
uint64_t tmp; int rc;
int ok = 0;
statvfs = malloc(sizeof(struct sftp_statvfs_struct)); statvfs = malloc(sizeof(struct sftp_statvfs_struct));
if (statvfs == NULL) { if (statvfs == NULL) {
@@ -2748,78 +2658,20 @@ static sftp_statvfs_t sftp_parse_statvfs(sftp_session sftp, ssh_buffer buf) {
} }
ZERO_STRUCTP(statvfs); ZERO_STRUCTP(statvfs);
/* try .. catch */ rc = ssh_buffer_unpack(buf, "qqqqqqqqqqq",
do { &statvfs->f_bsize, /* file system block size */
/* file system block size */ &statvfs->f_frsize, /* fundamental fs block size */
if (buffer_get_u64(buf, &tmp) != sizeof(uint64_t)) { &statvfs->f_blocks, /* number of blocks (unit f_frsize) */
break; &statvfs->f_bfree, /* free blocks in file system */
} &statvfs->f_bavail, /* free blocks for non-root */
statvfs->f_bsize = ntohll(tmp); &statvfs->f_files, /* total file inodes */
&statvfs->f_ffree, /* free file inodes */
/* fundamental fs block size */ &statvfs->f_favail, /* free file inodes for to non-root */
if (buffer_get_u64(buf, &tmp) != sizeof(uint64_t)) { &statvfs->f_fsid, /* file system id */
break; &statvfs->f_flag, /* bit mask of f_flag values */
} &statvfs->f_namemax/* maximum filename length */
statvfs->f_frsize = ntohll(tmp); );
if (rc != SSH_OK) {
/* 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); SAFE_FREE(statvfs);
ssh_set_error(sftp->session, SSH_FATAL, "Invalid statvfs structure"); ssh_set_error(sftp->session, SSH_FATAL, "Invalid statvfs structure");
return NULL; return NULL;