X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=blobdiff_plain;f=lib%2Fsilcsftp%2Fsftp_util.c;h=6ec07bba94c2aec6b414bde5dcaa5cdf8f7f0cfb;hp=349f8a0fdbe5446702478cacf17725d1a67303a7;hb=1ea936cbf1bb3b19bd55839b904ef59ada84b8b5;hpb=e5d8d3db6caa344b3d419b884556c21b15e7d123 diff --git a/lib/silcsftp/sftp_util.c b/lib/silcsftp/sftp_util.c index 349f8a0f..6ec07bba 100644 --- a/lib/silcsftp/sftp_util.c +++ b/lib/silcsftp/sftp_util.c @@ -1,10 +1,10 @@ /* - sftp_util.c + sftp_util.c Author: Pekka Riikonen - Copyright (C) 2001 Pekka Riikonen + Copyright (C) 2001 - 2008 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 @@ -16,23 +16,27 @@ GNU General Public License for more details. */ +/* $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; @@ -41,15 +45,32 @@ SilcBuffer silc_sftp_packet_encode(SilcSFTPPacket packet, uint32 len, ...) /* 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); @@ -57,7 +78,8 @@ SilcBuffer silc_sftp_packet_encode_vp(SilcSFTPPacket packet, uint32 len, ret = silc_buffer_format_vp(buffer, vp); if (ret < 0) { - silc_buffer_free(buffer); + if (dyn) + silc_buffer_free(buffer); return NULL; } @@ -68,14 +90,15 @@ SilcBuffer silc_sftp_packet_encode_vp(SilcSFTPPacket packet, uint32 len, /* 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, @@ -88,11 +111,11 @@ SilcSFTPPacket silc_sftp_packet_decode(SilcBuffer 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) @@ -111,7 +134,8 @@ SilcSFTPPacket silc_sftp_packet_decode(SilcBuffer packet, 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; @@ -125,65 +149,67 @@ SilcBuffer silc_sftp_attr_encode(SilcSFTPAttributes attr) 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); } } @@ -201,17 +227,19 @@ SilcSFTPAttributes silc_sftp_attr_decode(SilcBuffer buffer) 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; @@ -219,9 +247,9 @@ SilcSFTPAttributes silc_sftp_attr_decode(SilcBuffer buffer) } 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; @@ -229,8 +257,8 @@ SilcSFTPAttributes silc_sftp_attr_decode(SilcBuffer buffer) } 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; @@ -238,9 +266,9 @@ SilcSFTPAttributes silc_sftp_attr_decode(SilcBuffer buffer) } 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; @@ -250,22 +278,25 @@ SilcSFTPAttributes silc_sftp_attr_decode(SilcBuffer buffer) 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) @@ -273,6 +304,8 @@ SilcSFTPAttributes silc_sftp_attr_decode(SilcBuffer buffer) 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); @@ -309,11 +342,13 @@ void silc_sftp_name_add(SilcSFTPName name, const char *short_name, { 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); @@ -321,7 +356,7 @@ void silc_sftp_name_add(SilcSFTPName name, const char *short_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) @@ -331,14 +366,21 @@ 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), @@ -352,8 +394,8 @@ SilcBuffer silc_sftp_name_encode(SilcSFTPName name) 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); @@ -370,20 +412,26 @@ SilcBuffer silc_sftp_name_encode(SilcSFTPName name) `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]), @@ -398,6 +446,10 @@ SilcSFTPName silc_sftp_name_decode(uint32 count, SilcBuffer buffer) /* 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; @@ -423,7 +475,7 @@ void silc_sftp_name_free(SilcSFTPName name) /* Maps errno to SFTP status message. */ -SilcSFTPStatus silc_sftp_map_errno(int err) +SilcSFTPStatus silc_sftp_map_errno(SilcResult err) { SilcSFTPStatus ret; @@ -431,19 +483,15 @@ SilcSFTPStatus silc_sftp_map_errno(int err) case 0: ret = SILC_SFTP_STATUS_OK; break; - case ENOENT: - case ENOTDIR: - case EBADF: - case ELOOP: + case SILC_ERR_NOT_DIRECTORY: + case SILC_ERR_NO_SUCH_FILE: + case SILC_ERR_BAD_FD: ret = SILC_SFTP_STATUS_NO_SUCH_FILE; break; - case EPERM: - case EACCES: - case EFAULT: + case SILC_ERR_PERMISSION_DENIED: ret = SILC_SFTP_STATUS_PERMISSION_DENIED; break; - case ENAMETOOLONG: - case EINVAL: + case SILC_ERR_INVALID_ARGUMENT: ret = SILC_SFTP_STATUS_BAD_MESSAGE; break; default: