/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* XXX: memleaks */
/* XXX: signed vs unsigned */
/* XXX: remove all logging, only return status codes */
/* XXX: copy between two remote sites */
#include "includes.h"
RCSID("$OpenBSD: sftp-client.c,v 1.47 2004/03/03 09:30:42 djm Exp $");
#include "openbsd-compat/sys-queue.h"
#include "buffer.h"
#include "bufaux.h"
#include "getput.h"
#include "xmalloc.h"
#include "log.h"
#include "atomicio.h"
#include "progressmeter.h"
#include "sftp.h"
#include "sftp-common.h"
#include "sftp-client.h"
extern int showprogress;
/* Minimum amount of data to read at at time */
#define MIN_READ_SIZE 512
/* Maximum packet size */
#define MAX_MSG_LENGTH (256 * 1024)
struct sftp_conn {
int fd_in;
int fd_out;
u_int transfer_buflen;
u_int num_requests;
u_int version;
u_int msg_id;
};
static void
send_msg(int fd, Buffer *m)
{
u_char mlen[4];
if (buffer_len(m) > MAX_MSG_LENGTH)
fatal("Outbound message too long %u", buffer_len(m));
/* Send length first */
PUT_32BIT(mlen, buffer_len(m));
if (atomicio(vwrite, fd, mlen, sizeof(mlen)) <= 0)
fatal("Couldn't send packet: %s", strerror(errno));
if (atomicio(vwrite, fd, buffer_ptr(m), buffer_len(m)) <= 0)
fatal("Couldn't send packet: %s", strerror(errno));
buffer_clear(m);
}
static void
get_msg(int fd, Buffer *m)
{
ssize_t len;
u_int msg_len;
buffer_append_space(m, 4);
len = atomicio(read, fd, buffer_ptr(m), 4);
if (len == 0)
fatal("Connection closed");
else if (len == -1)
fatal("Couldn't read packet: %s", strerror(errno));
msg_len = buffer_get_int(m);
if (msg_len > MAX_MSG_LENGTH)
fatal("Received message too long %u", msg_len);
buffer_append_space(m, msg_len);
len = atomicio(read, fd, buffer_ptr(m), msg_len);
if (len == 0)
fatal("Connection closed");
else if (len == -1)
fatal("Read packet: %s", strerror(errno));
}
static void
send_string_request(int fd, u_int id, u_int code, char *s,
u_int len)
{
Buffer msg;
buffer_init(&msg);
buffer_put_char(&msg, code);
buffer_put_int(&msg, id);
buffer_put_string(&msg, s, len);
send_msg(fd, &msg);
debug3("Sent message fd %d T:%u I:%u", fd, code, id);
buffer_free(&msg);
}
static void
send_string_attrs_request(int fd,