static void silc_sftp_server_status(SilcSFTP sftp, SilcSFTPStatus status, const char *message, const char *language_tag, void *context) { SilcSFTPServer server = (SilcSFTPServer)sftp; SilcUInt32 id = SILC_PTR_TO_32(context); int mlen, llen; SILC_LOG_DEBUG(("Status callback")); SILC_LOG_DEBUG(("Request ID: %d", id)); if (!message) message = ""; if (!language_tag) language_tag = ""; mlen = strlen(message); llen = strlen(language_tag); silc_sftp_send_packet(server, SILC_SFTP_STATUS, 16 + mlen + llen, SILC_STR_UI_INT(id), SILC_STR_UI_INT(status), SILC_STR_UI_INT(mlen), SILC_STR_UI32_STRING(message), SILC_STR_UI_INT(llen), SILC_STR_UI32_STRING(language_tag), SILC_STR_END); }
static void silc_sftp_server_handle(SilcSFTP sftp, SilcSFTPStatus status, SilcSFTPHandle handle, void *context) { SilcSFTPServer server = (SilcSFTPServer)sftp; SilcUInt32 id = SILC_PTR_TO_32(context); unsigned char *hdata; SilcUInt32 hdata_len; SILC_LOG_DEBUG(("Handle callback")); SILC_LOG_DEBUG(("Request ID: %d", id)); if (status != SILC_SFTP_STATUS_OK) { silc_sftp_send_error(server, status, id); return; } hdata = server->fs->fs->sftp_encode_handle(server->fs->fs_context, sftp, handle, &hdata_len); if (!hdata) { silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id); return; } silc_sftp_send_packet(server, SILC_SFTP_HANDLE, 8 + hdata_len, SILC_STR_UI_INT(id), SILC_STR_UI_INT(hdata_len), SILC_STR_UI_XNSTRING(hdata, hdata_len), SILC_STR_END); }
static void silcpurple_wb_parse(SilcPurpleWb wbs, PurpleWhiteboard *wb, unsigned char *message, SilcUInt32 message_len) { SilcUInt8 command; SilcUInt16 width, height, brush_size; SilcUInt32 brush_color, x, y, dx, dy; SilcBufferStruct buf; int ret; /* Parse the packet */ silc_buffer_set(&buf, message, message_len); ret = silc_buffer_unformat(&buf, SILC_STR_UI_CHAR(&command), SILC_STR_UI_SHORT(&width), SILC_STR_UI_SHORT(&height), SILC_STR_UI_INT(&brush_color), SILC_STR_UI_SHORT(&brush_size), SILC_STR_END); if (ret < 0) return; silc_buffer_pull(&buf, ret); /* Update whiteboard if its dimensions changed */ if (width != wbs->width || height != wbs->height) silcpurple_wb_set_dimensions(wb, height, width); if (command == SILCPURPLE_WB_DRAW) { /* Parse data and draw it */ ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&dx), SILC_STR_UI_INT(&dy), SILC_STR_END); if (ret < 0) return; silc_buffer_pull(&buf, 8); x = dx; y = dy; while (silc_buffer_len(&buf) > 0) { ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&dx), SILC_STR_UI_INT(&dy), SILC_STR_END); if (ret < 0) return; silc_buffer_pull(&buf, 8); purple_whiteboard_draw_line(wb, x, y, x + dx, y + dy, brush_color, brush_size); x += dx; y += dy; } } if (command == SILCPURPLE_WB_CLEAR) purple_whiteboard_clear(wb); }
void silcpurple_wb_send(PurpleWhiteboard *wb, GList *draw_list) { SilcPurpleWb wbs = wb->proto_data; SilcBuffer packet; GList *list; int len; PurpleConnection *gc; SilcPurple sg; g_return_if_fail(draw_list); gc = purple_account_get_connection(wb->account); g_return_if_fail(gc); sg = gc->proto_data; g_return_if_fail(sg); len = SILCPURPLE_WB_HEADER; for (list = draw_list; list; list = list->next) len += 4; packet = silc_buffer_alloc_size(len); if (!packet) return; /* Assmeble packet */ silc_buffer_format(packet, SILC_STR_UI32_STRING(SILCPURPLE_WB_MIME), SILC_STR_UI_CHAR(SILCPURPLE_WB_DRAW), SILC_STR_UI_SHORT(wbs->width), SILC_STR_UI_SHORT(wbs->height), SILC_STR_UI_INT(wbs->brush_color), SILC_STR_UI_SHORT(wbs->brush_size), SILC_STR_END); silc_buffer_pull(packet, SILCPURPLE_WB_HEADER); for (list = draw_list; list; list = list->next) { silc_buffer_format(packet, SILC_STR_UI_INT(GPOINTER_TO_INT(list->data)), SILC_STR_END); silc_buffer_pull(packet, 4); } /* Send the message */ if (wbs->type == 0) { /* Private message */ silc_client_send_private_message(sg->client, sg->conn, wbs->u.client, SILC_MESSAGE_FLAG_DATA, NULL, packet->head, len); } else if (wbs->type == 1) { /* Channel message. Channel private keys are not supported. */ silc_client_send_channel_message(sg->client, sg->conn, wbs->u.channel, NULL, SILC_MESSAGE_FLAG_DATA, NULL, packet->head, len); } silc_buffer_free(packet); }
static void silc_sftp_send_error(SilcSFTPServer sftp, SilcSFTPStatus status, SilcUInt32 id) { SILC_LOG_DEBUG(("Send error %d", status)); silc_sftp_send_packet(sftp, SILC_SFTP_STATUS, 16, SILC_STR_UI_INT(id), SILC_STR_UI_INT(status), SILC_STR_UI_INT(0), /* Error */ SILC_STR_UI_INT(0), /* Language tag */ SILC_STR_END); }
SilcBuffer silc_sftp_name_encode(SilcSFTPName name) { SilcBuffer buffer; int i, len = 4; 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]); if (!attr_buf[i]) return NULL; len += silc_buffer_len(attr_buf[i]); } buffer = silc_buffer_alloc(len); if (!buffer) return NULL; silc_buffer_end(buffer); silc_buffer_format(buffer, SILC_STR_UI_INT(name->count), SILC_STR_END); silc_buffer_pull(buffer, 4); for (i = 0; i < name->count; i++) { len = silc_buffer_format(buffer, SILC_STR_UI_INT(strlen(name->filename[i])), 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_DATA(silc_buffer_data(attr_buf[i]), silc_buffer_len(attr_buf[i])), SILC_STR_END); silc_buffer_pull(buffer, len); silc_free(attr_buf[i]); } silc_free(attr_buf); silc_buffer_push(buffer, buffer->data - buffer->head); return buffer; }
SilcSFTPPacket silc_sftp_packet_decode(SilcBuffer packet, unsigned char **payload, SilcUInt32 *payload_len) { SilcUInt32 len; SilcUInt8 type; int ret; ret = silc_buffer_unformat(packet, SILC_STR_UI_INT(&len), SILC_STR_UI_CHAR(&type), SILC_STR_END); if (ret < 0) return 0; if (type < SILC_SFTP_INIT || type > SILC_SFTP_EXTENDED_REPLY) return 0; if (len > (silc_buffer_len(packet) - 5)) return -1; silc_buffer_pull(packet, 5); ret = silc_buffer_unformat(packet, SILC_STR_UI_XNSTRING(payload, len), SILC_STR_END); if (ret < 0) return 0; silc_buffer_push(packet, 5); *payload_len = len; return (SilcSFTPPacket)type; }
static void silc_sftp_server_attr(SilcSFTP sftp, SilcSFTPStatus status, const SilcSFTPAttributes attrs, void *context) { SilcSFTPServer server = (SilcSFTPServer)sftp; SilcUInt32 id = SILC_PTR_TO_32(context); SilcBuffer attr_buf; SILC_LOG_DEBUG(("Attr callback")); SILC_LOG_DEBUG(("Request ID: %d", id)); if (status != SILC_SFTP_STATUS_OK) { silc_sftp_send_error(server, status, id); return; } attr_buf = silc_sftp_attr_encode(attrs); if (!attr_buf) { silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id); return; } silc_sftp_send_packet(server, SILC_SFTP_ATTRS, 4 + silc_buffer_len(attr_buf), SILC_STR_UI_INT(id), SILC_STR_DATA(silc_buffer_data(attr_buf), silc_buffer_len(attr_buf)), SILC_STR_END); silc_buffer_free(attr_buf); }
static void silc_sftp_server_name(SilcSFTP sftp, SilcSFTPStatus status, const SilcSFTPName name, void *context) { SilcSFTPServer server = (SilcSFTPServer)sftp; SilcUInt32 id = SILC_PTR_TO_32(context); SilcBuffer namebuf; SILC_LOG_DEBUG(("Name callback")); SILC_LOG_DEBUG(("Request ID: %d", id)); if (status != SILC_SFTP_STATUS_OK) { silc_sftp_send_error(server, status, id); return; } namebuf = silc_sftp_name_encode(name); if (!namebuf) { silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id); return; } silc_sftp_send_packet(server, SILC_SFTP_NAME, 4 + silc_buffer_len(namebuf), SILC_STR_UI_INT(id), SILC_STR_DATA(silc_buffer_data(namebuf), silc_buffer_len(namebuf)), SILC_STR_END); }
static void silc_sftp_server_data(SilcSFTP sftp, SilcSFTPStatus status, const unsigned char *data, SilcUInt32 data_len, void *context) { SilcSFTPServer server = (SilcSFTPServer)sftp; SilcUInt32 id = SILC_PTR_TO_32(context); SILC_LOG_DEBUG(("Data callback")); SILC_LOG_DEBUG(("Request ID: %d", id)); if (status != SILC_SFTP_STATUS_OK) { silc_sftp_send_error(server, status, id); return; } silc_sftp_send_packet(server, SILC_SFTP_DATA, 8 + data_len, SILC_STR_UI_INT(id), SILC_STR_UI_INT(data_len), SILC_STR_UI_XNSTRING(data, data_len), SILC_STR_END); }
void silcpurple_wb_clear(PurpleWhiteboard *wb) { SilcPurpleWb wbs = wb->proto_data; SilcBuffer packet; int len; PurpleConnection *gc; SilcPurple sg; gc = purple_account_get_connection(wb->account); g_return_if_fail(gc); sg = gc->proto_data; g_return_if_fail(sg); len = SILCPURPLE_WB_HEADER; packet = silc_buffer_alloc_size(len); if (!packet) return; /* Assmeble packet */ silc_buffer_format(packet, SILC_STR_UI32_STRING(SILCPURPLE_WB_MIME), SILC_STR_UI_CHAR(SILCPURPLE_WB_CLEAR), SILC_STR_UI_SHORT(wbs->width), SILC_STR_UI_SHORT(wbs->height), SILC_STR_UI_INT(wbs->brush_color), SILC_STR_UI_SHORT(wbs->brush_size), SILC_STR_END); /* Send the message */ if (wbs->type == 0) { /* Private message */ silc_client_send_private_message(sg->client, sg->conn, wbs->u.client, SILC_MESSAGE_FLAG_DATA, NULL, packet->head, len); } else if (wbs->type == 1) { /* Channel message */ silc_client_send_channel_message(sg->client, sg->conn, wbs->u.channel, NULL, SILC_MESSAGE_FLAG_DATA, NULL, packet->head, len); } silc_buffer_free(packet); }
SilcBuffer silc_sftp_packet_encode_vp(SilcSFTPPacket packet, SilcBuffer packet_buf, SilcUInt32 len, va_list vp) { SilcBuffer buffer; bool dyn; int ret; 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); silc_buffer_pull(buffer, 5); ret = silc_buffer_format_vp(buffer, vp); if (ret < 0) { if (dyn) silc_buffer_free(buffer); return NULL; } silc_buffer_push(buffer, 5); return buffer; }
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), 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), SILC_STR_END) < 0) goto out; silc_buffer_pull(buffer, 8); } if (attr->flags & SILC_SFTP_ATTR_UIDGID) { if (silc_buffer_unformat(buffer, SILC_STR_UI_INT(&attr->uid), SILC_STR_UI_INT(&attr->gid), SILC_STR_END) < 0) goto out; silc_buffer_pull(buffer, 8); } if (attr->flags & SILC_SFTP_ATTR_PERMISSIONS) { if (silc_buffer_unformat(buffer, SILC_STR_UI_INT(&attr->permissions), SILC_STR_END) < 0) goto out; silc_buffer_pull(buffer, 4); } if (attr->flags & SILC_SFTP_ATTR_ACMODTIME) { if (silc_buffer_unformat(buffer, SILC_STR_UI_INT(&attr->atime), SILC_STR_UI_INT(&attr->mtime), SILC_STR_END) < 0) goto out; silc_buffer_pull(buffer, 8); } if (attr->flags & SILC_SFTP_ATTR_EXTENDED) { int i; 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, sizeof(*attr->extended_type)); 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; SilcUInt32 tmp_len, tmp2_len; if (silc_buffer_unformat(buffer, SILC_STR_UI32_NSTRING(&tmp, &tmp_len), SILC_STR_UI32_NSTRING(&tmp2, &tmp2_len), SILC_STR_END) < 0) goto out; 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); silc_buffer_pull(buffer, tmp_len + 4 + tmp2_len + 4); } } return attr; out: silc_sftp_attr_free(attr); return NULL; }
static void silc_sftp_server_receive_process(SilcSFTP sftp, SilcBuffer buffer) { SilcSFTPServer server = (SilcSFTPServer)sftp; SilcSFTPPacket type; char *filename = NULL, *path = NULL; unsigned char *payload = NULL; SilcUInt32 payload_len; int ret; SilcBufferStruct buf; SilcUInt32 id; SilcSFTPAttributes attrs; SilcSFTPHandle handle; SilcSFTPMonitorDataStruct mdata; SILC_LOG_DEBUG(("Start")); /* Parse the packet */ type = silc_sftp_packet_decode(buffer, &payload, &payload_len); if (type <= 0) return; silc_buffer_set(&buf, payload, payload_len); memset(&mdata, 0, sizeof(mdata)); switch (type) { case SILC_SFTP_READ: { unsigned char *hdata; SilcUInt32 hdata_len; SilcUInt64 offset; SilcUInt32 len; SILC_LOG_DEBUG(("Read request")); ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&id), SILC_STR_UI32_NSTRING(&hdata, &hdata_len), SILC_STR_UI_INT64(&offset), SILC_STR_UI_INT(&len), SILC_STR_END); if (ret < 0) goto failure; /* Get the handle */ handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp, (const unsigned char *)hdata, hdata_len); if (!handle) { silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id); break; } /* Read operation */ server->fs->fs->sftp_read(server->fs->fs_context, sftp, handle, offset, len, silc_sftp_server_data, SILC_32_TO_PTR(id)); /* Call monitor */ if (server->monitors & SILC_SFTP_MONITOR_READ && server->monitor) { mdata.offset = offset; mdata.data_len = len; (*server->monitor)(sftp, SILC_SFTP_MONITOR_READ, &mdata, server->monitor_context); } } break; case SILC_SFTP_WRITE: { unsigned char *hdata; SilcUInt32 hdata_len; SilcUInt64 offset; unsigned char *data; SilcUInt32 data_len; SILC_LOG_DEBUG(("Read request")); ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&id), SILC_STR_UI32_NSTRING(&hdata, &hdata_len), SILC_STR_UI_INT64(&offset), SILC_STR_UI32_NSTRING(&data, &data_len), SILC_STR_END); if (ret < 0) goto failure; /* Get the handle */ handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp, (const unsigned char *)hdata, hdata_len); if (!handle) { silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id); break; } /* Write operation */ server->fs->fs->sftp_write(server->fs->fs_context, sftp, handle, offset, (const unsigned char *)data, data_len, silc_sftp_server_status, SILC_32_TO_PTR(id)); /* Call monitor */ if (server->monitors & SILC_SFTP_MONITOR_WRITE && server->monitor) { mdata.offset = offset; mdata.data_len = data_len; (*server->monitor)(sftp, SILC_SFTP_MONITOR_WRITE, &mdata, server->monitor_context); } } break; case SILC_SFTP_INIT: { SilcSFTPVersion version; SILC_LOG_DEBUG(("Init request")); ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&version), SILC_STR_END); if (ret < 0) break; /* Call monitor */ if (server->monitors & SILC_SFTP_MONITOR_INIT && server->monitor) { mdata.version = version; (*server->monitor)(sftp, SILC_SFTP_MONITOR_INIT, &mdata, server->monitor_context); } silc_sftp_send_packet(server, SILC_SFTP_VERSION, 4, SILC_STR_UI_INT(SILC_SFTP_PROTOCOL_VERSION), SILC_STR_END); } break; case SILC_SFTP_OPEN: { SilcSFTPFileOperation pflags; unsigned char *attr_buf; SilcUInt32 attr_len = 0; SilcBufferStruct tmpbuf; SILC_LOG_DEBUG(("Open request")); ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&id), SILC_STR_UI32_STRING_ALLOC(&filename), SILC_STR_UI_INT(&pflags), SILC_STR_UI32_NSTRING(&attr_buf, &attr_len), SILC_STR_END); if (ret < 0) goto failure; if (attr_len) { silc_buffer_set(&tmpbuf, attr_buf, attr_len); attrs = silc_sftp_attr_decode(&tmpbuf); if (!attrs) goto failure; } else { attrs = silc_calloc(1, sizeof(*attrs)); if (!attrs) goto failure; } /* Call monitor */ if (server->monitors & SILC_SFTP_MONITOR_OPEN && server->monitor) { mdata.name = filename; mdata.pflags = pflags; (*server->monitor)(sftp, SILC_SFTP_MONITOR_OPEN, &mdata, server->monitor_context); } /* Open operation */ server->fs->fs->sftp_open(server->fs->fs_context, sftp, filename, pflags, attrs, silc_sftp_server_handle, SILC_32_TO_PTR(id)); silc_free(filename); silc_sftp_attr_free(attrs); } break; case SILC_SFTP_CLOSE: { unsigned char *hdata; SilcUInt32 hdata_len; SILC_LOG_DEBUG(("Close request")); ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&id), SILC_STR_UI32_NSTRING(&hdata, &hdata_len), SILC_STR_END); if (ret < 0) goto failure; /* Get the handle */ handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp, (const unsigned char *)hdata, hdata_len); if (!handle) { silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id); break; } /* Call monitor */ if (server->monitors & SILC_SFTP_MONITOR_CLOSE && server->monitor) { (*server->monitor)(sftp, SILC_SFTP_MONITOR_CLOSE, &mdata, server->monitor_context); } /* Close operation */ server->fs->fs->sftp_close(server->fs->fs_context, sftp, handle, silc_sftp_server_status, SILC_32_TO_PTR(id)); } break; case SILC_SFTP_REMOVE: { SILC_LOG_DEBUG(("Remove request")); ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&id), SILC_STR_UI32_STRING_ALLOC(&filename), SILC_STR_END); if (ret < 0) goto failure; /* Call monitor */ if (server->monitors & SILC_SFTP_MONITOR_REMOVE && server->monitor) { mdata.name = filename; (*server->monitor)(sftp, SILC_SFTP_MONITOR_REMOVE, &mdata, server->monitor_context); } /* Remove operation */ server->fs->fs->sftp_remove(server->fs->fs_context, sftp, filename, silc_sftp_server_status, SILC_32_TO_PTR(id)); silc_free(filename); } break; case SILC_SFTP_RENAME: { char *newname = NULL; SILC_LOG_DEBUG(("Rename request")); ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&id), SILC_STR_UI32_STRING_ALLOC(&filename), SILC_STR_UI32_STRING_ALLOC(&newname), SILC_STR_END); if (ret < 0) goto failure; /* Call monitor */ if (server->monitors & SILC_SFTP_MONITOR_RENAME && server->monitor) { mdata.name = filename; mdata.name2 = newname; (*server->monitor)(sftp, SILC_SFTP_MONITOR_RENAME, &mdata, server->monitor_context); } /* Rename operation */ server->fs->fs->sftp_rename(server->fs->fs_context, sftp, filename, newname, silc_sftp_server_status, SILC_32_TO_PTR(id)); silc_free(filename); silc_free(newname); } break; case SILC_SFTP_MKDIR: { unsigned char *attr_buf; SilcUInt32 attr_len = 0; SilcBufferStruct tmpbuf; SILC_LOG_DEBUG(("Mkdir request")); ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&id), SILC_STR_UI32_STRING_ALLOC(&path), SILC_STR_UI32_NSTRING(&attr_buf, &attr_len), SILC_STR_END); if (ret < 0) goto failure; if (attr_len) { silc_buffer_set(&tmpbuf, attr_buf, attr_len); attrs = silc_sftp_attr_decode(&tmpbuf); if (!attrs) goto failure; } else { attrs = silc_calloc(1, sizeof(*attrs)); if (!attrs) goto failure; } /* Call monitor */ if (server->monitors & SILC_SFTP_MONITOR_MKDIR && server->monitor) { mdata.name = path; (*server->monitor)(sftp, SILC_SFTP_MONITOR_MKDIR, &mdata, server->monitor_context); } /* Mkdir operation */ server->fs->fs->sftp_mkdir(server->fs->fs_context, sftp, path, attrs, silc_sftp_server_status, SILC_32_TO_PTR(id)); silc_sftp_attr_free(attrs); silc_free(path); } break; case SILC_SFTP_RMDIR: { SILC_LOG_DEBUG(("Rmdir request")); ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&id), SILC_STR_UI32_STRING_ALLOC(&path), SILC_STR_END); if (ret < 0) goto failure; /* Call monitor */ if (server->monitors & SILC_SFTP_MONITOR_RMDIR && server->monitor) { mdata.name = path; (*server->monitor)(sftp, SILC_SFTP_MONITOR_RMDIR, &mdata, server->monitor_context); } /* Rmdir operation */ server->fs->fs->sftp_rmdir(server->fs->fs_context, sftp, path, silc_sftp_server_status, SILC_32_TO_PTR(id)); silc_free(path); } break; case SILC_SFTP_OPENDIR: { SILC_LOG_DEBUG(("Opendir request")); ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&id), SILC_STR_UI32_STRING_ALLOC(&path), SILC_STR_END); if (ret < 0) goto failure; /* Call monitor */ if (server->monitors & SILC_SFTP_MONITOR_OPENDIR && server->monitor) { mdata.name = path; (*server->monitor)(sftp, SILC_SFTP_MONITOR_OPENDIR, &mdata, server->monitor_context); } /* Opendir operation */ server->fs->fs->sftp_opendir(server->fs->fs_context, sftp, path, silc_sftp_server_handle, SILC_32_TO_PTR(id)); silc_free(path); } break; case SILC_SFTP_READDIR: { unsigned char *hdata; SilcUInt32 hdata_len; SILC_LOG_DEBUG(("Readdir request")); ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&id), SILC_STR_UI32_NSTRING(&hdata, &hdata_len), SILC_STR_END); if (ret < 0) goto failure; /* Get the handle */ handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp, (const unsigned char *)hdata, hdata_len); if (!handle) { silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id); break; } /* Call monitor */ if (server->monitors & SILC_SFTP_MONITOR_READDIR && server->monitor) { (*server->monitor)(sftp, SILC_SFTP_MONITOR_READDIR, &mdata, server->monitor_context); } /* Readdir operation */ server->fs->fs->sftp_readdir(server->fs->fs_context, sftp, handle, silc_sftp_server_name, SILC_32_TO_PTR(id)); } break; case SILC_SFTP_STAT: { SILC_LOG_DEBUG(("Stat request")); ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&id), SILC_STR_UI32_STRING_ALLOC(&path), SILC_STR_END); if (ret < 0) goto failure; /* Call monitor */ if (server->monitors & SILC_SFTP_MONITOR_STAT && server->monitor) { mdata.name = path; (*server->monitor)(sftp, SILC_SFTP_MONITOR_STAT, &mdata, server->monitor_context); } /* Stat operation */ server->fs->fs->sftp_stat(server->fs->fs_context, sftp, path, silc_sftp_server_attr, SILC_32_TO_PTR(id)); silc_free(path); } break; case SILC_SFTP_LSTAT: { SILC_LOG_DEBUG(("Lstat request")); ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&id), SILC_STR_UI32_STRING_ALLOC(&path), SILC_STR_END); if (ret < 0) goto failure; /* Call monitor */ if (server->monitors & SILC_SFTP_MONITOR_LSTAT && server->monitor) { mdata.name = path; (*server->monitor)(sftp, SILC_SFTP_MONITOR_LSTAT, &mdata, server->monitor_context); } /* Lstat operation */ server->fs->fs->sftp_lstat(server->fs->fs_context, sftp, path, silc_sftp_server_attr, SILC_32_TO_PTR(id)); silc_free(path); } break; case SILC_SFTP_FSTAT: { unsigned char *hdata; SilcUInt32 hdata_len; SILC_LOG_DEBUG(("Fstat request")); ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&id), SILC_STR_UI32_NSTRING(&hdata, &hdata_len), SILC_STR_END); if (ret < 0) goto failure; /* Get the handle */ handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp, (const unsigned char *)hdata, hdata_len); if (!handle) { silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id); break; } /* Call monitor */ if (server->monitors & SILC_SFTP_MONITOR_FSTAT && server->monitor) { (*server->monitor)(sftp, SILC_SFTP_MONITOR_FSTAT, &mdata, server->monitor_context); } /* Fstat operation */ server->fs->fs->sftp_fstat(server->fs->fs_context, sftp, handle, silc_sftp_server_attr, SILC_32_TO_PTR(id)); } break; case SILC_SFTP_SETSTAT: { unsigned char *attr_buf; SilcUInt32 attr_len = 0; SilcBufferStruct tmpbuf; SILC_LOG_DEBUG(("Setstat request")); ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&id), SILC_STR_UI32_STRING_ALLOC(&path), SILC_STR_UI32_NSTRING(&attr_buf, &attr_len), SILC_STR_END); if (ret < 0) goto failure; if (attr_len) { silc_buffer_set(&tmpbuf, attr_buf, attr_len); attrs = silc_sftp_attr_decode(&tmpbuf); if (!attrs) goto failure; } else { attrs = silc_calloc(1, sizeof(*attrs)); if (!attrs) goto failure; } /* Call monitor */ if (server->monitors & SILC_SFTP_MONITOR_SETSTAT && server->monitor) { mdata.name = path; (*server->monitor)(sftp, SILC_SFTP_MONITOR_SETSTAT, &mdata, server->monitor_context); } /* Setstat operation */ server->fs->fs->sftp_setstat(server->fs->fs_context, sftp, path, attrs, silc_sftp_server_status, SILC_32_TO_PTR(id)); silc_sftp_attr_free(attrs); silc_free(path); } break; case SILC_SFTP_FSETSTAT: { unsigned char *hdata, *attr_buf; SilcUInt32 hdata_len, attr_len = 0; SilcBufferStruct tmpbuf; SILC_LOG_DEBUG(("Fsetstat request")); ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&id), SILC_STR_UI32_NSTRING(&hdata, &hdata_len), SILC_STR_UI32_NSTRING(&attr_buf, &attr_len), SILC_STR_END); if (ret < 0) goto failure; if (attr_len) { silc_buffer_set(&tmpbuf, attr_buf, attr_len); attrs = silc_sftp_attr_decode(&tmpbuf); if (!attrs) goto failure; } else { attrs = silc_calloc(1, sizeof(*attrs)); if (!attrs) goto failure; } /* Get the handle */ handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp, (const unsigned char *)hdata, hdata_len); if (!handle) { silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id); break; } /* Call monitor */ if (server->monitors & SILC_SFTP_MONITOR_FSETSTAT && server->monitor) { (*server->monitor)(sftp, SILC_SFTP_MONITOR_FSETSTAT, &mdata, server->monitor_context); } /* Fsetstat operation */ server->fs->fs->sftp_fsetstat(server->fs->fs_context, sftp, handle, attrs, silc_sftp_server_status, SILC_32_TO_PTR(id)); silc_sftp_attr_free(attrs); } break; case SILC_SFTP_READLINK: { SILC_LOG_DEBUG(("Readlink request")); ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&id), SILC_STR_UI32_STRING_ALLOC(&path), SILC_STR_END); if (ret < 0) goto failure; /* Call monitor */ if (server->monitors & SILC_SFTP_MONITOR_READLINK && server->monitor) { mdata.name = path; (*server->monitor)(sftp, SILC_SFTP_MONITOR_READLINK, &mdata, server->monitor_context); } /* Readlink operation */ server->fs->fs->sftp_readlink(server->fs->fs_context, sftp, path, silc_sftp_server_name, SILC_32_TO_PTR(id)); silc_free(path); } break; case SILC_SFTP_SYMLINK: { char *target = NULL; SILC_LOG_DEBUG(("Symlink request")); ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&id), SILC_STR_UI32_STRING_ALLOC(&path), SILC_STR_UI32_STRING_ALLOC(&target), SILC_STR_END); if (ret < 0) goto failure; /* Call monitor */ if (server->monitors & SILC_SFTP_MONITOR_SYMLINK && server->monitor) { mdata.name = path; mdata.name2 = target; (*server->monitor)(sftp, SILC_SFTP_MONITOR_SYMLINK, &mdata, server->monitor_context); } /* Symlink operation */ server->fs->fs->sftp_symlink(server->fs->fs_context, sftp, path, target, silc_sftp_server_status, SILC_32_TO_PTR(id)); silc_free(path); silc_free(target); } break; case SILC_SFTP_REALPATH: { SILC_LOG_DEBUG(("Realpath request")); ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&id), SILC_STR_UI32_STRING_ALLOC(&path), SILC_STR_END); if (ret < 0) goto failure; /* Call monitor */ if (server->monitors & SILC_SFTP_MONITOR_REALPATH && server->monitor) { mdata.name = path; (*server->monitor)(sftp, SILC_SFTP_MONITOR_REALPATH, &mdata, server->monitor_context); } /* Realpath operation */ server->fs->fs->sftp_realpath(server->fs->fs_context, sftp, path, silc_sftp_server_name, SILC_32_TO_PTR(id)); silc_free(path); } break; case SILC_SFTP_EXTENDED: { char *request = NULL; unsigned char *data; SilcUInt32 data_len; SILC_LOG_DEBUG(("Extended request")); ret = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&id), SILC_STR_UI32_STRING_ALLOC(&request), SILC_STR_END); if (ret < 0) goto failure; data_len = 8 + strlen(request); silc_buffer_pull(&buf, data_len); ret = silc_buffer_unformat(&buf, SILC_STR_DATA(&data, silc_buffer_len(&buf)), SILC_STR_END); if (ret < 0) goto failure; data_len = silc_buffer_len(&buf); /* Call monitor */ if (server->monitors & SILC_SFTP_MONITOR_EXTENDED && server->monitor) { (*server->monitor)(sftp, SILC_SFTP_MONITOR_EXTENDED, &mdata, server->monitor_context); } /* Extended operation */ server->fs->fs->sftp_extended(server->fs->fs_context, sftp, request, data, data_len, silc_sftp_server_extended, SILC_32_TO_PTR(id)); silc_free(request); } break; default: break; } return; failure: silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id); }
static void silc_pkcs_ssh_sign_cb(SilcBool success, const unsigned char *signature, SilcUInt32 signature_len, void *context) { SilcSshSign sign = context; SilcStack stack = sign->stack; unsigned char rbuf[20], sbuf[20]; SilcBufferStruct sig; SilcAsn1 asn1; SilcMPInt r, s; memset(&sig, 0, sizeof(sig)); /* Format the signature. RSA is easy because PKCS#1 is already in correct format. For DSA the returned signature is in PKIX compliant format and we have to reformat it for SSH2. */ if (!strcmp(sign->privkey->pkcs->name, "dsa")) { asn1 = silc_asn1_alloc(stack); if (!asn1) { sign->sign_cb(FALSE, NULL, 0, sign->context); silc_sfree(stack, sign); silc_stack_free(stack); return; } /* Decode the signature */ silc_buffer_set(&sig, (unsigned char *)signature, signature_len); if (!silc_asn1_decode(asn1, &sig, SILC_ASN1_SEQUENCE, SILC_ASN1_INT(&r), SILC_ASN1_INT(&s), SILC_ASN1_END, SILC_ASN1_END)) { sign->sign_cb(FALSE, NULL, 0, sign->context); silc_asn1_free(asn1); silc_sfree(stack, sign); silc_stack_free(stack); return; } /* Encode the integers */ memset(rbuf, 0, sizeof(rbuf)); memset(sbuf, 0, sizeof(sbuf)); silc_mp_mp2bin_noalloc(&r, rbuf, sizeof(rbuf)); silc_mp_mp2bin_noalloc(&s, sbuf, sizeof(sbuf)); silc_asn1_free(asn1); /* Encode SSH2 DSS signature */ if (silc_buffer_sformat(stack, &sig, SILC_STR_UI_INT(7), SILC_STR_UI32_STRING("ssh-dss"), SILC_STR_UI_INT(sizeof(rbuf) + sizeof(sbuf)), SILC_STR_DATA(rbuf, sizeof(rbuf)), SILC_STR_DATA(sbuf, sizeof(sbuf)), SILC_STR_END) < 0) { sign->sign_cb(FALSE, NULL, 0, sign->context); silc_sfree(stack, sign); silc_stack_free(stack); return; } } else { /* Encode SSH2 RSA signature */ if (silc_buffer_sformat(stack, &sig, SILC_STR_UI_INT(7), SILC_STR_UI32_STRING("ssh-rsa"), SILC_STR_UI_INT(signature_len), SILC_STR_DATA(signature, signature_len), SILC_STR_END) < 0) { sign->sign_cb(FALSE, NULL, 0, sign->context); silc_sfree(stack, sign); silc_stack_free(stack); return; } } /* Deliver result */ sign->sign_cb(TRUE, silc_buffer_data(&sig), silc_buffer_len(&sig), sign->context); silc_buffer_spurge(stack, &sig); silc_sfree(stack, sign); silc_stack_free(stack); }
SilcBool silc_attribute_get_object(SilcAttributePayload payload, void *object, SilcUInt32 object_size) { SilcUInt16 len; SilcBool ret = FALSE; if (!object || payload->flags & SILC_ATTRIBUTE_FLAG_INVALID) return FALSE; switch (payload->attribute) { case SILC_ATTRIBUTE_USER_INFO: { SilcVCard vcard = object; if (object_size != sizeof(*vcard)) break; if (!silc_vcard_decode(payload->data, payload->data_len, vcard)) break; ret = TRUE; } break; case SILC_ATTRIBUTE_SERVICE: { SilcAttributeObjService *service = object; SilcBufferStruct buf; SilcUInt16 addr_len, signon_len; char *addr, *signon; int res; if (object_size != sizeof(*service)) break; if (payload->data_len < 13) break; silc_buffer_set(&buf, payload->data, payload->data_len); res = silc_buffer_unformat(&buf, SILC_STR_UI_INT(&service->port), SILC_STR_UI16_NSTRING(&addr, &addr_len), SILC_STR_UI_CHAR(&service->status), SILC_STR_UI16_NSTRING(&signon, &signon_len), SILC_STR_UI_INT(&service->idle), SILC_STR_END); if (res == -1) break; memset(service->address, 0, sizeof(service->address)); memset(service->signon, 0, sizeof(service->signon)); memcpy(service->address, addr, (addr_len < sizeof(service->address) - 1 ? addr_len : sizeof(service->address) - 1)); memcpy(service->signon, signon, (signon_len < sizeof(service->signon) - 1 ? signon_len : sizeof(service->signon) - 1)); ret = TRUE; } break; case SILC_ATTRIBUTE_STATUS_MOOD: case SILC_ATTRIBUTE_PREFERRED_CONTACT: { SilcUInt32 *mask = (SilcUInt32 *)object; if (object_size != sizeof(SilcUInt32)) break; if (payload->data_len < 4) break; SILC_GET32_MSB(*mask, payload->data); ret = TRUE; } break; case SILC_ATTRIBUTE_STATUS_FREETEXT: case SILC_ATTRIBUTE_PREFERRED_LANGUAGE: case SILC_ATTRIBUTE_TIMEZONE: { char *string = object; if (payload->data_len < 2) break; SILC_GET16_MSB(len, payload->data); if (payload->data_len < 2 + len) break; if (object_size < len) break; memcpy(string, payload->data + 2, len); ret = TRUE; } break; case SILC_ATTRIBUTE_STATUS_MESSAGE: case SILC_ATTRIBUTE_EXTENSION: case SILC_ATTRIBUTE_USER_ICON: { SilcMime mime = object; if (object_size != sizeof(*mime)) break; if (!silc_mime_decode(mime, payload->data, payload->data_len)) break; ret = TRUE; } break; case SILC_ATTRIBUTE_GEOLOCATION: { SilcAttributeObjGeo *geo = object; SilcBufferStruct buffer; int res; if (object_size != sizeof(*geo)) break; silc_buffer_set(&buffer, (unsigned char *)payload->data, payload->data_len); res = silc_buffer_unformat(&buffer, SILC_STR_UI16_STRING_ALLOC(&geo->longitude), SILC_STR_UI16_STRING_ALLOC(&geo->latitude), SILC_STR_UI16_STRING_ALLOC(&geo->altitude), SILC_STR_UI16_STRING_ALLOC(&geo->accuracy), SILC_STR_END); if (res == -1) break; ret = TRUE; } break; case SILC_ATTRIBUTE_DEVICE_INFO: { SilcAttributeObjDevice *dev = object; SilcBufferStruct buffer; SilcUInt32 type; int res; if (object_size != sizeof(*dev)) break; silc_buffer_set(&buffer, (unsigned char *)payload->data, payload->data_len); res = silc_buffer_unformat(&buffer, SILC_STR_UI_INT(&type), SILC_STR_UI16_STRING_ALLOC(&dev->manufacturer), SILC_STR_UI16_STRING_ALLOC(&dev->version), SILC_STR_UI16_STRING_ALLOC(&dev->model), SILC_STR_UI16_STRING_ALLOC(&dev->language), SILC_STR_END); if (res == -1) break; dev->type = type; ret = TRUE; } break; case SILC_ATTRIBUTE_PHONE_NUMBER: { SilcAttributeObjPN *pn = object; SilcBufferStruct buffer; SilcUInt32 pn_format; int res; if (object_size != sizeof(*pn)) break; silc_buffer_set(&buffer, (unsigned char *)payload->data, payload->data_len); res = silc_buffer_unformat(&buffer, SILC_STR_UI_INT(&pn_format), SILC_STR_UI16_STRING_ALLOC(&pn->number), SILC_STR_END); if (res == -1) break; pn->format = pn_format; ret = TRUE; } break; case SILC_ATTRIBUTE_USER_PUBLIC_KEY: case SILC_ATTRIBUTE_SERVER_PUBLIC_KEY: { SilcAttributeObjPk *pk = object; SilcBufferStruct buffer; int res; if (object_size != sizeof(*pk)) break; silc_buffer_set(&buffer, (unsigned char *)payload->data, payload->data_len); res = silc_buffer_unformat(&buffer, SILC_STR_UI16_NSTRING_ALLOC(&pk->type, &len), SILC_STR_END); if (res == -1 || len > silc_buffer_len(&buffer) - 2) break; pk->data = silc_memdup(payload->data + 2 + len, payload->data_len - 2 - len); pk->data_len = payload->data_len - 2 - len; ret = TRUE; } break; case SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE: case SILC_ATTRIBUTE_SERVER_DIGITAL_SIGNATURE: { SilcAttributeObjPk *pk = object; if (object_size != sizeof(*pk)) break; pk->type = NULL; pk->data = silc_memdup(payload->data, payload->data_len); pk->data_len = payload->data_len; ret = TRUE; } break; default: break; } return ret; }
static unsigned char * silc_attribute_payload_encode_int(SilcAttribute attribute, SilcAttributeFlags flags, void *object, SilcUInt32 object_size, SilcUInt32 *ret_len) { SilcBuffer tmpbuf = NULL; unsigned char tmp[4], *str = NULL, *ret; SilcUInt32 len; /* Encode according to attribute type */ if (flags & SILC_ATTRIBUTE_FLAG_VALID) { if (!object && !object_size) return NULL; switch (attribute) { case SILC_ATTRIBUTE_USER_INFO: { SilcVCard vcard = object; if (object_size != sizeof(*vcard)) return NULL; str = silc_vcard_encode(vcard, &object_size); if (!str) return NULL; object = str; } break; case SILC_ATTRIBUTE_SERVICE: { SilcAttributeObjService *service = object; SilcUInt32 len2; if (object_size != sizeof(*service)) return NULL; len = strlen(service->address); len2 = strlen(service->signon); tmpbuf = silc_buffer_alloc_size(13 + len + len2); if (!tmpbuf) return NULL; silc_buffer_format(tmpbuf, SILC_STR_UI_INT(service->port), SILC_STR_UI_SHORT(len), SILC_STR_UI_XNSTRING(service->address, len), SILC_STR_UI_CHAR(service->status), SILC_STR_UI_SHORT(len2), SILC_STR_UI_XNSTRING(service->signon, len2), SILC_STR_UI_INT(service->idle), SILC_STR_END); object = tmpbuf->data; object_size = silc_buffer_len(tmpbuf); } break; case SILC_ATTRIBUTE_STATUS_MOOD: case SILC_ATTRIBUTE_PREFERRED_CONTACT: { SilcUInt32 mask = SILC_PTR_TO_32(object); if (object_size != sizeof(SilcUInt32)) return NULL; SILC_PUT32_MSB(mask, tmp); object = tmp; object_size = sizeof(SilcUInt32); } break; case SILC_ATTRIBUTE_STATUS_FREETEXT: case SILC_ATTRIBUTE_PREFERRED_LANGUAGE: case SILC_ATTRIBUTE_TIMEZONE: { unsigned char *string = object; str = silc_malloc(2 + object_size); if (!str) return NULL; SILC_PUT16_MSB(object_size, str); memcpy(str + 2, string, object_size); object = str; object_size += 2; } break; case SILC_ATTRIBUTE_STATUS_MESSAGE: case SILC_ATTRIBUTE_EXTENSION: case SILC_ATTRIBUTE_USER_ICON: { SilcMime mime = object; if (object_size != sizeof(*mime)) return NULL; str = silc_mime_encode(mime, &object_size); if (!str) return NULL; object = str; } break; case SILC_ATTRIBUTE_GEOLOCATION: { SilcAttributeObjGeo *geo = object; SilcUInt32 len1, len2, len3, len4; if (object_size != sizeof(*geo)) return NULL; len1 = (geo->longitude ? strlen(geo->longitude) : 0); len2 = (geo->latitude ? strlen(geo->latitude) : 0); len3 = (geo->altitude ? strlen(geo->altitude) : 0); len4 = (geo->accuracy ? strlen(geo->accuracy) : 0); if (len1 + len2 + len3 + len4 == 0) return NULL; len = len1 + len2 + len3 + len4; tmpbuf = silc_buffer_alloc_size(8 + len); if (!tmpbuf) return NULL; silc_buffer_format(tmpbuf, SILC_STR_UI_SHORT(len1), SILC_STR_UI16_STRING(len1 ? geo->longitude : ""), SILC_STR_UI_SHORT(len2), SILC_STR_UI16_STRING(len2 ? geo->latitude : ""), SILC_STR_UI_SHORT(len3), SILC_STR_UI16_STRING(len3 ? geo->altitude : ""), SILC_STR_UI_SHORT(len4), SILC_STR_UI16_STRING(len4 ? geo->accuracy : ""), SILC_STR_END); object = tmpbuf->data; object_size = silc_buffer_len(tmpbuf); } break; case SILC_ATTRIBUTE_DEVICE_INFO: { SilcAttributeObjDevice *dev = object; SilcUInt32 len1, len2, len3, len4; if (object_size != sizeof(*dev)) return NULL; len1 = (dev->manufacturer ? strlen(dev->manufacturer) : 0); len2 = (dev->version ? strlen(dev->version) : 0); len3 = (dev->model ? strlen(dev->model) : 0); len4 = (dev->language ? strlen(dev->language) : 0); if (len1 + len2 + len3 + len4 == 0) return NULL; len = len1 + len2 + len3 + len4; tmpbuf = silc_buffer_alloc_size(4 + 8 + len); if (!tmpbuf) return NULL; silc_buffer_format(tmpbuf, SILC_STR_UI_INT(dev->type), SILC_STR_UI_SHORT(len1), SILC_STR_UI16_STRING(len1 ? dev->manufacturer : ""), SILC_STR_UI_SHORT(len2), SILC_STR_UI16_STRING(len2 ? dev->version : ""), SILC_STR_UI_SHORT(len3), SILC_STR_UI16_STRING(len3 ? dev->model : ""), SILC_STR_UI_SHORT(len4), SILC_STR_UI16_STRING(len4 ? dev->language : ""), SILC_STR_END); object = tmpbuf->data; object_size = silc_buffer_len(tmpbuf); } break; case SILC_ATTRIBUTE_PHONE_NUMBER: { SilcAttributeObjPN *pn = object; if (object_size != sizeof(*pn)) return NULL; if (!pn->number || strlen(pn->number) < 5) return NULL; tmpbuf = silc_buffer_alloc(0); if (!tmpbuf) return NULL; if (silc_buffer_format(tmpbuf, SILC_STR_UI_INT(pn->format), SILC_STR_UI_SHORT(strlen(pn->number)), SILC_STR_UI16_STRING(pn->number), SILC_STR_END) < 0) return NULL; object = tmpbuf->data; object_size = silc_buffer_len(tmpbuf); } break; case SILC_ATTRIBUTE_USER_PUBLIC_KEY: case SILC_ATTRIBUTE_SERVER_PUBLIC_KEY: { SilcAttributeObjPk *pk = object; if (object_size != sizeof(*pk)) return NULL; len = (pk->type ? strlen(pk->type) : 0); tmpbuf = silc_buffer_alloc_size(2 + len + pk->data_len); if (!tmpbuf) return NULL; silc_buffer_format(tmpbuf, SILC_STR_UI_SHORT(len), SILC_STR_UI16_STRING(pk->type), SILC_STR_UI_XNSTRING(pk->data, pk->data_len), SILC_STR_END); object = tmpbuf->data; object_size = silc_buffer_len(tmpbuf); } break; case SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE: case SILC_ATTRIBUTE_SERVER_DIGITAL_SIGNATURE: { SilcAttributeObjPk *pk = object; if (object_size != sizeof(*pk)) return NULL; object = pk->data; object_size = pk->data_len; } break; default: return NULL; break; } ret = silc_memdup(object, object_size); if (tmpbuf) silc_buffer_free(tmpbuf); silc_free(str); if (ret_len) *ret_len = object_size; return ret; } return NULL; }
SilcBuffer silc_sftp_attr_encode(SilcSFTPAttributes attr) { SilcBuffer buffer; int i, ret; SilcUInt32 len = 4; if (attr->flags & SILC_SFTP_ATTR_SIZE) len += 8; if (attr->flags & SILC_SFTP_ATTR_UIDGID) len += 8; if (attr->flags & SILC_SFTP_ATTR_PERMISSIONS) len += 4; if (attr->flags & SILC_SFTP_ATTR_ACMODTIME) len += 8; if (attr->flags & SILC_SFTP_ATTR_EXTENDED) { len += 4; for (i = 0; i < attr->extended_count; i++) { len += 8; len += silc_buffer_len(attr->extended_type[i]); len += silc_buffer_len(attr->extended_data[i]); } } buffer = silc_buffer_alloc_size(len); if (!buffer) return NULL; 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_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_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_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_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_STR_END); silc_buffer_pull(buffer, 4); for (i = 0; i < attr->extended_count; i++) { 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); } } silc_buffer_push(buffer, buffer->data - buffer->head); return buffer; }