/*
- sftp_util.c
+ sftp_util.c
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2001 Pekka Riikonen
+ Copyright (C) 2001 - 2007 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
*/
/* $Id$ */
-#include "silcincludes.h"
+#include "silc.h"
#include "silcsftp.h"
#include "sftp_util.h"
/* Encodes a SFTP packet of type `packet' of length `len'. The variable
argument list is encoded as data payload to the buffer. Returns the
encoded packet or NULL on error. The caller must free the returned
- buffer. */
+ buffer. If `packet_buf' is non-NULL then the new packet data is put
+ to that buffer instead of allocating new one. If the new data cannot
+ fit to `packet_buf' will be reallocated. */
-SilcBuffer silc_sftp_packet_encode(SilcSFTPPacket packet, uint32 len, ...)
+SilcBuffer silc_sftp_packet_encode(SilcSFTPPacket packet,
+ SilcBuffer packet_buf, SilcUInt32 len, ...)
{
SilcBuffer buffer;
va_list vp;
va_start(vp, len);
- buffer = silc_sftp_packet_encode_vp(packet, len, vp);
+ buffer = silc_sftp_packet_encode_vp(packet, packet_buf, len, vp);
va_end(vp);
return buffer;
/* Same as silc_sftp_packet_encode but takes the variable argument list
pointer as argument. */
-SilcBuffer silc_sftp_packet_encode_vp(SilcSFTPPacket packet, uint32 len,
+SilcBuffer silc_sftp_packet_encode_vp(SilcSFTPPacket packet,
+ SilcBuffer packet_buf, SilcUInt32 len,
va_list vp)
{
SilcBuffer buffer;
+ bool dyn;
int ret;
- buffer = silc_buffer_alloc(4 + 1 + len);
- silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
- silc_buffer_format(buffer,
+ if (packet_buf) {
+ if (silc_buffer_truelen(packet_buf) < 4 + 1 + len) {
+ packet_buf = silc_buffer_realloc(packet_buf, 4 + 1 + len);
+ if (!packet_buf)
+ return NULL;
+ }
+
+ buffer = packet_buf;
+ dyn = FALSE;
+ } else {
+ buffer = silc_buffer_alloc(4 + 1 + len);
+ if (!buffer)
+ return NULL;
+ dyn = TRUE;
+ }
+
+ silc_buffer_pull_tail(buffer, 4 + 1 + len);
+ silc_buffer_format(buffer,
SILC_STR_UI_INT(len),
SILC_STR_UI_CHAR(packet),
SILC_STR_END);
ret = silc_buffer_format_vp(buffer, vp);
if (ret < 0) {
- silc_buffer_free(buffer);
+ if (dyn)
+ silc_buffer_free(buffer);
return NULL;
}
/* Decodes the SFTP packet data `packet' and return the SFTP packet type.
The payload of the packet is returned to the `payload' pointer. Returns
- 0 if error occurred during decoding. */
+ 0 if error occurred during decoding and -1 if partial packet was
+ received. */
SilcSFTPPacket silc_sftp_packet_decode(SilcBuffer packet,
unsigned char **payload,
- uint32 *payload_len)
+ SilcUInt32 *payload_len)
{
- uint32 len;
- uint8 type;
+ SilcUInt32 len;
+ SilcUInt8 type;
int ret;
ret = silc_buffer_unformat(packet,
if (type < SILC_SFTP_INIT || type > SILC_SFTP_EXTENDED_REPLY)
return 0;
- if (len > (packet->len - 5))
- return 0;
+ if (len > (silc_buffer_len(packet) - 5))
+ return -1;
silc_buffer_pull(packet, 5);
- ret = silc_buffer_unformat(packet,
+ ret = silc_buffer_unformat(packet,
SILC_STR_UI_XNSTRING(payload, len),
SILC_STR_END);
if (ret < 0)
SilcBuffer silc_sftp_attr_encode(SilcSFTPAttributes attr)
{
SilcBuffer buffer;
- int i, ret, len = 4;
+ int i, ret;
+ SilcUInt32 len = 4;
if (attr->flags & SILC_SFTP_ATTR_SIZE)
len += 8;
len += 4;
for (i = 0; i < attr->extended_count; i++) {
len += 8;
- len += attr->extended_type[i]->len;
- len += attr->extended_data[i]->len;
+ len += silc_buffer_len(attr->extended_type[i]);
+ len += silc_buffer_len(attr->extended_data[i]);
}
}
- buffer = silc_buffer_alloc(len);
- silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
+ buffer = silc_buffer_alloc_size(len);
+ if (!buffer)
+ return NULL;
- silc_buffer_format(buffer,
- SILC_STR_UI_INT(attr->flags),
+ silc_buffer_format(buffer,
+ SILC_STR_UI_INT(attr->flags),
SILC_STR_END);
silc_buffer_pull(buffer, 4);
if (attr->flags & SILC_SFTP_ATTR_SIZE) {
- silc_buffer_format(buffer,
- SILC_STR_UI_INT64(attr->size),
+ silc_buffer_format(buffer,
+ SILC_STR_UI_INT64(attr->size),
SILC_STR_END);
silc_buffer_pull(buffer, 8);
}
if (attr->flags & SILC_SFTP_ATTR_UIDGID) {
- silc_buffer_format(buffer,
- SILC_STR_UI_INT(attr->uid),
- SILC_STR_UI_INT(attr->gid),
+ silc_buffer_format(buffer,
+ SILC_STR_UI_INT(attr->uid),
+ SILC_STR_UI_INT(attr->gid),
SILC_STR_END);
silc_buffer_pull(buffer, 8);
}
if (attr->flags & SILC_SFTP_ATTR_PERMISSIONS) {
- silc_buffer_format(buffer,
- SILC_STR_UI_INT(attr->permissions),
+ silc_buffer_format(buffer,
+ SILC_STR_UI_INT(attr->permissions),
SILC_STR_END);
silc_buffer_pull(buffer, 4);
}
if (attr->flags & SILC_SFTP_ATTR_ACMODTIME) {
- silc_buffer_format(buffer,
- SILC_STR_UI_INT(attr->atime),
- SILC_STR_UI_INT(attr->mtime),
+ silc_buffer_format(buffer,
+ SILC_STR_UI_INT(attr->atime),
+ SILC_STR_UI_INT(attr->mtime),
SILC_STR_END);
silc_buffer_pull(buffer, 8);
}
if (attr->flags & SILC_SFTP_ATTR_EXTENDED) {
- silc_buffer_format(buffer,
- SILC_STR_UI_INT(attr->extended_count),
+ silc_buffer_format(buffer,
+ SILC_STR_UI_INT(attr->extended_count),
SILC_STR_END);
silc_buffer_pull(buffer, 4);
for (i = 0; i < attr->extended_count; i++) {
- ret =
- silc_buffer_format(buffer,
- SILC_STR_UI_INT(attr->extended_type[i]->len),
- SILC_STR_UI_XNSTRING(attr->extended_type[i]->data,
- attr->extended_type[i]->len),
- SILC_STR_UI_INT(attr->extended_data[i]->len),
- SILC_STR_UI_XNSTRING(attr->extended_data[i]->data,
- attr->extended_data[i]->len),
- SILC_STR_END);
+ ret =
+ silc_buffer_format(
+ buffer,
+ SILC_STR_UI_INT(silc_buffer_len(attr->extended_type[i])),
+ SILC_STR_DATA(silc_buffer_data(attr->extended_type[i]),
+ silc_buffer_len(attr->extended_type[i])),
+ SILC_STR_UI_INT(silc_buffer_len(attr->extended_data[i])),
+ SILC_STR_DATA(silc_buffer_data(attr->extended_data[i]),
+ silc_buffer_len(attr->extended_data[i])),
+ SILC_STR_END);
silc_buffer_pull(buffer, ret);
}
}
SilcSFTPAttributes attr;
attr = silc_calloc(1, sizeof(*attr));
+ if (!attr)
+ return NULL;
- if (silc_buffer_unformat(buffer,
- SILC_STR_UI_INT(&attr->flags),
+ if (silc_buffer_unformat(buffer,
+ SILC_STR_UI_INT(&attr->flags),
SILC_STR_END) < 0)
goto out;
silc_buffer_pull(buffer, 4);
if (attr->flags & SILC_SFTP_ATTR_SIZE) {
- if (silc_buffer_unformat(buffer,
- SILC_STR_UI_INT64(&attr->size),
+ if (silc_buffer_unformat(buffer,
+ SILC_STR_UI_INT64(&attr->size),
SILC_STR_END) < 0)
goto out;
}
if (attr->flags & SILC_SFTP_ATTR_UIDGID) {
- if (silc_buffer_unformat(buffer,
- SILC_STR_UI_INT(&attr->uid),
- SILC_STR_UI_INT(&attr->gid),
+ if (silc_buffer_unformat(buffer,
+ SILC_STR_UI_INT(&attr->uid),
+ SILC_STR_UI_INT(&attr->gid),
SILC_STR_END) < 0)
goto out;
}
if (attr->flags & SILC_SFTP_ATTR_PERMISSIONS) {
- if (silc_buffer_unformat(buffer,
- SILC_STR_UI_INT(&attr->permissions),
+ if (silc_buffer_unformat(buffer,
+ SILC_STR_UI_INT(&attr->permissions),
SILC_STR_END) < 0)
goto out;
}
if (attr->flags & SILC_SFTP_ATTR_ACMODTIME) {
- if (silc_buffer_unformat(buffer,
- SILC_STR_UI_INT(&attr->atime),
- SILC_STR_UI_INT(&attr->mtime),
+ if (silc_buffer_unformat(buffer,
+ SILC_STR_UI_INT(&attr->atime),
+ SILC_STR_UI_INT(&attr->mtime),
SILC_STR_END) < 0)
goto out;
if (attr->flags & SILC_SFTP_ATTR_EXTENDED) {
int i;
- if (silc_buffer_unformat(buffer,
- SILC_STR_UI_INT(&attr->extended_count),
+ if (silc_buffer_unformat(buffer,
+ SILC_STR_UI_INT(&attr->extended_count),
SILC_STR_END) < 0)
goto out;
silc_buffer_pull(buffer, 4);
- attr->extended_type = silc_calloc(attr->extended_count,
+ attr->extended_type = silc_calloc(attr->extended_count,
sizeof(*attr->extended_type));
- attr->extended_data = silc_calloc(attr->extended_count,
+ attr->extended_data = silc_calloc(attr->extended_count,
sizeof(*attr->extended_data));
+ if (!attr->extended_type || !attr->extended_data)
+ return NULL;
+
for (i = 0; i < attr->extended_count; i++) {
unsigned char *tmp, *tmp2;
- uint32 tmp_len, tmp2_len;
+ SilcUInt32 tmp_len, tmp2_len;
- if (silc_buffer_unformat(buffer,
+ if (silc_buffer_unformat(buffer,
SILC_STR_UI32_NSTRING(&tmp, &tmp_len),
SILC_STR_UI32_NSTRING(&tmp2, &tmp2_len),
SILC_STR_END) < 0)
attr->extended_type[i] = silc_buffer_alloc(tmp_len);
attr->extended_data[i] = silc_buffer_alloc(tmp2_len);
+ if (!attr->extended_type[i] || !attr->extended_data[i])
+ return NULL;
silc_buffer_put(attr->extended_type[i], tmp, tmp_len);
silc_buffer_put(attr->extended_data[i], tmp2, tmp2_len);
{
name->filename = silc_realloc(name->filename, sizeof(*name->filename) *
(name->count + 1));
- name->long_filename = silc_realloc(name->long_filename,
+ name->long_filename = silc_realloc(name->long_filename,
sizeof(*name->long_filename) *
(name->count + 1));
name->attrs = silc_realloc(name->attrs, sizeof(*name->attrs) *
(name->count + 1));
+ if (!name->filename || !name->long_filename || !name->attrs)
+ return;
name->filename[name->count] = strdup(short_name);
name->long_filename[name->count] = strdup(long_name);
name->count++;
}
-/* Encodes the SilcSFTPName to a buffer and returns the allocated buffer.
+/* Encodes the SilcSFTPName to a buffer and returns the allocated buffer.
The caller must free the buffer. */
SilcBuffer silc_sftp_name_encode(SilcSFTPName name)
SilcBuffer *attr_buf;
attr_buf = silc_calloc(name->count, sizeof(*attr_buf));
+ if (!attr_buf)
+ return NULL;
+
for (i = 0; i < name->count; i++) {
len += (8 + strlen(name->filename[i]) + strlen(name->long_filename[i]));
attr_buf[i] = silc_sftp_attr_encode(name->attrs[i]);
- len += attr_buf[i]->len;
+ if (!attr_buf[i])
+ return NULL;
+ len += silc_buffer_len(attr_buf[i]);
}
buffer = silc_buffer_alloc(len);
- silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
+ if (!buffer)
+ return NULL;
+ silc_buffer_end(buffer);
silc_buffer_format(buffer,
SILC_STR_UI_INT(name->count),
SILC_STR_UI32_STRING(name->filename[i]),
SILC_STR_UI_INT(strlen(name->long_filename[i])),
SILC_STR_UI32_STRING(name->long_filename[i]),
- SILC_STR_UI_XNSTRING(attr_buf[i]->data,
- attr_buf[i]->len),
+ SILC_STR_DATA(silc_buffer_data(attr_buf[i]),
+ silc_buffer_len(attr_buf[i])),
SILC_STR_END);
silc_buffer_pull(buffer, len);
`count' many name, longname and attribute values. Returns the allocated
structure or NULL on error. */
-SilcSFTPName silc_sftp_name_decode(uint32 count, SilcBuffer buffer)
+SilcSFTPName silc_sftp_name_decode(SilcUInt32 count, SilcBuffer buffer)
{
SilcSFTPName name;
int i;
int ret;
name = silc_calloc(1, sizeof(*name));
+ if (!name)
+ return NULL;
name->filename = silc_calloc(count, sizeof(*name->filename));
name->long_filename = silc_calloc(count, sizeof(*name->filename));
name->attrs = silc_calloc(count, sizeof(*name->attrs));
+ if (!name->filename || !name->long_filename || !name->attrs) {
+ silc_sftp_name_free(name);
+ return NULL;
+ }
name->count = count;
for (i = 0; i < count; i++) {
- ret =
+ ret =
silc_buffer_unformat(buffer,
SILC_STR_UI32_STRING_ALLOC(&name->filename[i]),
SILC_STR_UI32_STRING_ALLOC(&name->long_filename[i]),
/* Decode attributes, this will pull the `buffer' to correct place
for next round automatically. */
name->attrs[i] = silc_sftp_attr_decode(buffer);
+ if (!name->attrs[i]) {
+ silc_sftp_name_free(name);
+ return NULL;
+ }
}
return name;
case ENOENT:
case ENOTDIR:
case EBADF:
- case ELOOP:
ret = SILC_SFTP_STATUS_NO_SUCH_FILE;
break;
case EPERM: