update sftp client and server to new buffer API.
authordjm <djm@openbsd.org>
Wed, 14 Jan 2015 13:54:13 +0000 (13:54 +0000)
committerdjm <djm@openbsd.org>
Wed, 14 Jan 2015 13:54:13 +0000 (13:54 +0000)
pretty much just mechanical changes; with & ok markus

usr.bin/ssh/progressmeter.c
usr.bin/ssh/progressmeter.h
usr.bin/ssh/sftp-client.c
usr.bin/ssh/sftp-client.h
usr.bin/ssh/sftp-common.c
usr.bin/ssh/sftp-common.h
usr.bin/ssh/sftp-glob.c
usr.bin/ssh/sftp-server.c
usr.bin/ssh/sftp.c

index 5c4ae99..5aeaee6 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: progressmeter.c,v 1.40 2013/09/19 00:24:52 djm Exp $ */
+/* $OpenBSD: progressmeter.c,v 1.41 2015/01/14 13:54:13 djm Exp $ */
 /*
  * Copyright (c) 2003 Nils Nordman.  All rights reserved.
  *
@@ -63,7 +63,7 @@ static void update_progress_meter(int);
 
 static time_t start;           /* start progress */
 static time_t last_update;     /* last progress update */
-static char *file;             /* name of the file being transferred */
+static const char *file;       /* name of the file being transferred */
 static off_t start_pos;                /* initial position of transfer */
 static off_t end_pos;          /* ending position of transfer */
 static off_t cur_pos;          /* transfer position as of last refresh */
@@ -246,7 +246,7 @@ update_progress_meter(int ignore)
 }
 
 void
-start_progress_meter(char *f, off_t filesize, off_t *ctr)
+start_progress_meter(const char *f, off_t filesize, off_t *ctr)
 {
        start = last_update = monotime();
        file = f;
index 10bab99..bf179dc 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: progressmeter.h,v 1.2 2006/03/25 22:22:43 djm Exp $ */
+/* $OpenBSD: progressmeter.h,v 1.3 2015/01/14 13:54:13 djm Exp $ */
 /*
  * Copyright (c) 2002 Nils Nordman.  All rights reserved.
  *
@@ -23,5 +23,5 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-void   start_progress_meter(char *, off_t, off_t *);
+void   start_progress_meter(const char *, off_t, off_t *);
 void   stop_progress_meter(void);
index 5102562..739f589 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp-client.c,v 1.115 2014/04/21 14:36:16 logan Exp $ */
+/* $OpenBSD: sftp-client.c,v 1.116 2015/01/14 13:54:13 djm Exp $ */
 /*
  * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
  *
@@ -40,7 +40,8 @@
 #include <unistd.h>
 
 #include "xmalloc.h"
-#include "buffer.h"
+#include "ssherr.h"
+#include "sshbuf.h"
 #include "log.h"
 #include "atomicio.h"
 #include "progressmeter.h"
@@ -76,8 +77,8 @@ struct sftp_conn {
        struct bwlimit bwlimit_in, bwlimit_out;
 };
 
-static char *
-get_handle(struct sftp_conn *conn, u_int expected_id, u_int *len,
+static u_char *
+get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len,
     const char *errfmt, ...) __attribute__((format(printf, 4, 5)));
 
 /* ARGSUSED */
@@ -91,36 +92,39 @@ sftpio(void *_bwlimit, size_t amount)
 }
 
 static void
-send_msg(struct sftp_conn *conn, Buffer *m)
+send_msg(struct sftp_conn *conn, struct sshbuf *m)
 {
        u_char mlen[4];
        struct iovec iov[2];
 
-       if (buffer_len(m) > SFTP_MAX_MSG_LENGTH)
-               fatal("Outbound message too long %u", buffer_len(m));
+       if (sshbuf_len(m) > SFTP_MAX_MSG_LENGTH)
+               fatal("Outbound message too long %zu", sshbuf_len(m));
 
        /* Send length first */
-       put_u32(mlen, buffer_len(m));
+       put_u32(mlen, sshbuf_len(m));
        iov[0].iov_base = mlen;
        iov[0].iov_len = sizeof(mlen);
-       iov[1].iov_base = buffer_ptr(m);
-       iov[1].iov_len = buffer_len(m);
+       iov[1].iov_base = (u_char *)sshbuf_ptr(m);
+       iov[1].iov_len = sshbuf_len(m);
 
        if (atomiciov6(writev, conn->fd_out, iov, 2,
            conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_out) !=
-           buffer_len(m) + sizeof(mlen))
+           sshbuf_len(m) + sizeof(mlen))
                fatal("Couldn't send packet: %s", strerror(errno));
 
-       buffer_clear(m);
+       sshbuf_reset(m);
 }
 
 static void
-get_msg(struct sftp_conn *conn, Buffer *m)
+get_msg(struct sftp_conn *conn, struct sshbuf *m)
 {
        u_int msg_len;
+       u_char *p;
+       int r;
 
-       buffer_append_space(m, 4);
-       if (atomicio6(read, conn->fd_in, buffer_ptr(m), 4,
+       if ((r = sshbuf_reserve(m, 4, &p)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
+       if (atomicio6(read, conn->fd_in, p, 4,
            conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) != 4) {
                if (errno == EPIPE)
                        fatal("Connection closed");
@@ -128,12 +132,14 @@ get_msg(struct sftp_conn *conn, Buffer *m)
                        fatal("Couldn't read packet: %s", strerror(errno));
        }
 
-       msg_len = buffer_get_int(m);
+       if ((r = sshbuf_get_u32(m, &msg_len)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
        if (msg_len > SFTP_MAX_MSG_LENGTH)
                fatal("Received message too long %u", msg_len);
 
-       buffer_append_space(m, msg_len);
-       if (atomicio6(read, conn->fd_in, buffer_ptr(m), msg_len,
+       if ((r = sshbuf_reserve(m, msg_len, &p)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
+       if (atomicio6(read, conn->fd_in, p, msg_len,
            conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in)
            != msg_len) {
                if (errno == EPIPE)
@@ -144,46 +150,56 @@ get_msg(struct sftp_conn *conn, Buffer *m)
 }
 
 static void
-send_string_request(struct sftp_conn *conn, u_int id, u_int code, char *s,
+send_string_request(struct sftp_conn *conn, u_int id, u_int code, const 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(conn, &msg);
+       struct sshbuf *msg;
+       int r;
+
+       if ((msg = sshbuf_new()) == NULL)
+               fatal("%s: sshbuf_new failed", __func__);
+       if ((r = sshbuf_put_u8(msg, code)) != 0 ||
+           (r = sshbuf_put_u32(msg, id)) != 0 ||
+           (r = sshbuf_put_string(msg, s, len)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
+       send_msg(conn, msg);
        debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id);
-       buffer_free(&msg);
+       sshbuf_free(msg);
 }
 
 static void
 send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code,
-    char *s, u_int len, Attrib *a)
+    const void *s, u_int len, Attrib *a)
 {
-       Buffer msg;
-
-       buffer_init(&msg);
-       buffer_put_char(&msg, code);
-       buffer_put_int(&msg, id);
-       buffer_put_string(&msg, s, len);
-       encode_attrib(&msg, a);
-       send_msg(conn, &msg);
+       struct sshbuf *msg;
+       int r;
+
+       if ((msg = sshbuf_new()) == NULL)
+               fatal("%s: sshbuf_new failed", __func__);
+       if ((r = sshbuf_put_u8(msg, code)) != 0 ||
+           (r = sshbuf_put_u32(msg, id)) != 0 ||
+           (r = sshbuf_put_string(msg, s, len)) != 0 ||
+           (r = encode_attrib(msg, a)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
+       send_msg(conn, msg);
        debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id);
-       buffer_free(&msg);
+       sshbuf_free(msg);
 }
 
 static u_int
 get_status(struct sftp_conn *conn, u_int expected_id)
 {
-       Buffer msg;
-       u_int type, id, status;
+       struct sshbuf *msg;
+       u_char type;
+       u_int id, status;
+       int r;
 
-       buffer_init(&msg);
-       get_msg(conn, &msg);
-       type = buffer_get_char(&msg);
-       id = buffer_get_int(&msg);
+       if ((msg = sshbuf_new()) == NULL)
+               fatal("%s: sshbuf_new failed", __func__);
+       get_msg(conn, msg);
+       if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
+           (r = sshbuf_get_u32(msg, &id)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
        if (id != expected_id)
                fatal("ID mismatch (%u != %u)", id, expected_id);
@@ -191,112 +207,136 @@ get_status(struct sftp_conn *conn, u_int expected_id)
                fatal("Expected SSH2_FXP_STATUS(%u) packet, got %u",
                    SSH2_FXP_STATUS, type);
 
-       status = buffer_get_int(&msg);
-       buffer_free(&msg);
+       if ((r = sshbuf_get_u32(msg, &status)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
+       sshbuf_free(msg);
 
        debug3("SSH2_FXP_STATUS %u", status);
 
        return status;
 }
 
-static char *
-get_handle(struct sftp_conn *conn, u_int expected_id, u_int *len,
+static u_char *
+get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len,
     const char *errfmt, ...)
 {
-       Buffer msg;
-       u_int type, id;
-       char *handle, errmsg[256];
+       struct sshbuf *msg;
+       u_int id, status;
+       u_char type;
+       u_char *handle;
+       char errmsg[256];
        va_list args;
-       int status;
+       int r;
 
        va_start(args, errfmt);
        if (errfmt != NULL)
                vsnprintf(errmsg, sizeof(errmsg), errfmt, args);
        va_end(args);
 
-       buffer_init(&msg);
-       get_msg(conn, &msg);
-       type = buffer_get_char(&msg);
-       id = buffer_get_int(&msg);
+       if ((msg = sshbuf_new()) == NULL)
+               fatal("%s: sshbuf_new failed", __func__);
+       get_msg(conn, msg);
+       if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
+           (r = sshbuf_get_u32(msg, &id)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
        if (id != expected_id)
                fatal("%s: ID mismatch (%u != %u)",
                    errfmt == NULL ? __func__ : errmsg, id, expected_id);
        if (type == SSH2_FXP_STATUS) {
-               status = buffer_get_int(&msg);
+               if ((r = sshbuf_get_u32(msg, &status)) != 0)
+                       fatal("%s: buffer error: %s", __func__, ssh_err(r));
                if (errfmt != NULL)
                        error("%s: %s", errmsg, fx2txt(status));
-               buffer_free(&msg);
+               sshbuf_free(msg);
                return(NULL);
        } else if (type != SSH2_FXP_HANDLE)
                fatal("%s: Expected SSH2_FXP_HANDLE(%u) packet, got %u",
                    errfmt == NULL ? __func__ : errmsg, SSH2_FXP_HANDLE, type);
 
-       handle = buffer_get_string(&msg, len);
-       buffer_free(&msg);
+       if ((r = sshbuf_get_string(msg, &handle, len)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
+       sshbuf_free(msg);
 
-       return(handle);
+       return handle;
 }
 
 static Attrib *
 get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet)
 {
-       Buffer msg;
-       u_int type, id;
-       Attrib *a;
+       struct sshbuf *msg;
+       u_int id;
+       u_char type;
+       int r;
+       static Attrib a;
 
-       buffer_init(&msg);
-       get_msg(conn, &msg);
+       if ((msg = sshbuf_new()) == NULL)
+               fatal("%s: sshbuf_new failed", __func__);
+       get_msg(conn, msg);
 
-       type = buffer_get_char(&msg);
-       id = buffer_get_int(&msg);
+       if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
+           (r = sshbuf_get_u32(msg, &id)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
        debug3("Received stat reply T:%u I:%u", type, id);
        if (id != expected_id)
                fatal("ID mismatch (%u != %u)", id, expected_id);
        if (type == SSH2_FXP_STATUS) {
-               int status = buffer_get_int(&msg);
+               u_int status;
 
+               if ((r = sshbuf_get_u32(msg, &status)) != 0)
+                       fatal("%s: buffer error: %s", __func__, ssh_err(r));
                if (quiet)
                        debug("Couldn't stat remote file: %s", fx2txt(status));
                else
                        error("Couldn't stat remote file: %s", fx2txt(status));
-               buffer_free(&msg);
+               sshbuf_free(msg);
                return(NULL);
        } else if (type != SSH2_FXP_ATTRS) {
                fatal("Expected SSH2_FXP_ATTRS(%u) packet, got %u",
                    SSH2_FXP_ATTRS, type);
        }
-       a = decode_attrib(&msg);
-       buffer_free(&msg);
+       if ((r = decode_attrib(msg, &a)) != 0) {
+               error("%s: couldn't decode attrib: %s", __func__, ssh_err(r));
+               sshbuf_free(msg);
+               return NULL;
+       }
+       sshbuf_free(msg);
 
-       return(a);
+       return &a;
 }
 
 static int
 get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st,
     u_int expected_id, int quiet)
 {
-       Buffer msg;
-       u_int type, id, flag;
+       struct sshbuf *msg;
+       u_char type;
+       u_int id;
+       u_int64_t flag;
+       int r;
 
-       buffer_init(&msg);
-       get_msg(conn, &msg);
+       if ((msg = sshbuf_new()) == NULL)
+               fatal("%s: sshbuf_new failed", __func__);
+       get_msg(conn, msg);
 
-       type = buffer_get_char(&msg);
-       id = buffer_get_int(&msg);
+       if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
+           (r = sshbuf_get_u32(msg, &id)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
        debug3("Received statvfs reply T:%u I:%u", type, id);
        if (id != expected_id)
                fatal("ID mismatch (%u != %u)", id, expected_id);
        if (type == SSH2_FXP_STATUS) {
-               int status = buffer_get_int(&msg);
+               u_int status;
 
+               if ((r = sshbuf_get_u32(msg, &status)) != 0)
+                       fatal("%s: buffer error: %s", __func__, ssh_err(r));
                if (quiet)
                        debug("Couldn't statvfs: %s", fx2txt(status));
                else
                        error("Couldn't statvfs: %s", fx2txt(status));
-               buffer_free(&msg);
+               sshbuf_free(msg);
                return -1;
        } else if (type != SSH2_FXP_EXTENDED_REPLY) {
                fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u",
@@ -304,22 +344,23 @@ get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st,
        }
 
        memset(st, 0, sizeof(*st));
-       st->f_bsize = buffer_get_int64(&msg);
-       st->f_frsize = buffer_get_int64(&msg);
-       st->f_blocks = buffer_get_int64(&msg);
-       st->f_bfree = buffer_get_int64(&msg);
-       st->f_bavail = buffer_get_int64(&msg);
-       st->f_files = buffer_get_int64(&msg);
-       st->f_ffree = buffer_get_int64(&msg);
-       st->f_favail = buffer_get_int64(&msg);
-       st->f_fsid = buffer_get_int64(&msg);
-       flag = buffer_get_int64(&msg);
-       st->f_namemax = buffer_get_int64(&msg);
+       if ((r = sshbuf_get_u64(msg, &st->f_bsize)) != 0 ||
+           (r = sshbuf_get_u64(msg, &st->f_frsize)) != 0 ||
+           (r = sshbuf_get_u64(msg, &st->f_blocks)) != 0 ||
+           (r = sshbuf_get_u64(msg, &st->f_bfree)) != 0 ||
+           (r = sshbuf_get_u64(msg, &st->f_bavail)) != 0 ||
+           (r = sshbuf_get_u64(msg, &st->f_files)) != 0 ||
+           (r = sshbuf_get_u64(msg, &st->f_ffree)) != 0 ||
+           (r = sshbuf_get_u64(msg, &st->f_favail)) != 0 ||
+           (r = sshbuf_get_u64(msg, &st->f_fsid)) != 0 ||
+           (r = sshbuf_get_u64(msg, &flag)) != 0 ||
+           (r = sshbuf_get_u64(msg, &st->f_namemax)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
        st->f_flag = (flag & SSH2_FXE_STATVFS_ST_RDONLY) ? ST_RDONLY : 0;
        st->f_flag |= (flag & SSH2_FXE_STATVFS_ST_NOSUID) ? ST_NOSUID : 0;
 
-       buffer_free(&msg);
+       sshbuf_free(msg);
 
        return 0;
 }
@@ -328,9 +369,10 @@ struct sftp_conn *
 do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests,
     u_int64_t limit_kbps)
 {
-       u_int type;
-       Buffer msg;
+       u_char type;
+       struct sshbuf *msg;
        struct sftp_conn *ret;
+       int r;
 
        ret = xcalloc(1, sizeof(*ret));
        ret->msg_id = 1;
@@ -341,52 +383,61 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests,
        ret->exts = 0;
        ret->limit_kbps = 0;
 
-       buffer_init(&msg);
-       buffer_put_char(&msg, SSH2_FXP_INIT);
-       buffer_put_int(&msg, SSH2_FILEXFER_VERSION);
-       send_msg(ret, &msg);
+       if ((msg = sshbuf_new()) == NULL)
+               fatal("%s: sshbuf_new failed", __func__);
+       if ((r = sshbuf_put_u8(msg, SSH2_FXP_INIT)) != 0 ||
+           (r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
+       send_msg(ret, msg);
 
-       buffer_clear(&msg);
+       sshbuf_reset(msg);
 
-       get_msg(ret, &msg);
+       get_msg(ret, msg);
 
        /* Expecting a VERSION reply */
-       if ((type = buffer_get_char(&msg)) != SSH2_FXP_VERSION) {
+       if ((r = sshbuf_get_u8(msg, &type)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
+       if (type != SSH2_FXP_VERSION) {
                error("Invalid packet back from SSH2_FXP_INIT (type %u)",
                    type);
-               buffer_free(&msg);
+               sshbuf_free(msg);
                return(NULL);
        }
-       ret->version = buffer_get_int(&msg);
+       if ((r = sshbuf_get_u32(msg, &ret->version)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
        debug2("Remote version: %u", ret->version);
 
        /* Check for extensions */
-       while (buffer_len(&msg) > 0) {
-               char *name = buffer_get_string(&msg, NULL);
-               char *value = buffer_get_string(&msg, NULL);
+       while (sshbuf_len(msg) > 0) {
+               char *name;
+               u_char *value;
+               size_t vlen;
                int known = 0;
 
+               if ((r = sshbuf_get_cstring(msg, &name, NULL)) != 0 ||
+                   (r = sshbuf_get_string(msg, &value, &vlen)) != 0)
+                       fatal("%s: buffer error: %s", __func__, ssh_err(r));
                if (strcmp(name, "posix-rename@openssh.com") == 0 &&
-                   strcmp(value, "1") == 0) {
+                   strcmp((char *)value, "1") == 0) {
                        ret->exts |= SFTP_EXT_POSIX_RENAME;
                        known = 1;
                } else if (strcmp(name, "statvfs@openssh.com") == 0 &&
-                   strcmp(value, "2") == 0) {
+                   strcmp((char *)value, "2") == 0) {
                        ret->exts |= SFTP_EXT_STATVFS;
                        known = 1;
                } else if (strcmp(name, "fstatvfs@openssh.com") == 0 &&
-                   strcmp(value, "2") == 0) {
+                   strcmp((char *)value, "2") == 0) {
                        ret->exts |= SFTP_EXT_FSTATVFS;
                        known = 1;
                } else if (strcmp(name, "hardlink@openssh.com") == 0 &&
-                   strcmp(value, "1") == 0) {
+                   strcmp((char *)value, "1") == 0) {
                        ret->exts |= SFTP_EXT_HARDLINK;
                        known = 1;
-               } else if (strcmp(name, "fsync@openssh.com") == 0 &&
-                   strcmp(value, "1") == 0) {
-                       ret->exts |= SFTP_EXT_FSYNC;
-                       known = 1;
+               } else if (strcmp(name, "fsync@openssh.com") == 0 &&
+                   strcmp((char *)value, "1") == 0) {
+                       ret->exts |= SFTP_EXT_FSYNC;
+                       known = 1;
                }
                if (known) {
                        debug2("Server supports extension \"%s\" revision %s",
@@ -398,7 +449,7 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests,
                free(value);
        }
 
-       buffer_free(&msg);
+       sshbuf_free(msg);
 
        /* Some filexfer v.0 servers don't support large packets */
        if (ret->version == 0)
@@ -422,54 +473,62 @@ sftp_proto_version(struct sftp_conn *conn)
 }
 
 int
-do_close(struct sftp_conn *conn, char *handle, u_int handle_len)
+do_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len)
 {
        u_int id, status;
-       Buffer msg;
+       struct sshbuf *msg;
+       int r;
 
-       buffer_init(&msg);
+       if ((msg = sshbuf_new()) == NULL)
+               fatal("%s: sshbuf_new failed", __func__);
 
        id = conn->msg_id++;
-       buffer_put_char(&msg, SSH2_FXP_CLOSE);
-       buffer_put_int(&msg, id);
-       buffer_put_string(&msg, handle, handle_len);
-       send_msg(conn, &msg);
+       if ((r = sshbuf_put_u8(msg, SSH2_FXP_CLOSE)) != 0 ||
+           (r = sshbuf_put_u32(msg, id)) != 0 ||
+           (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
+       send_msg(conn, msg);
        debug3("Sent message SSH2_FXP_CLOSE I:%u", id);
 
        status = get_status(conn, id);
        if (status != SSH2_FX_OK)
                error("Couldn't close file: %s", fx2txt(status));
 
-       buffer_free(&msg);
+       sshbuf_free(msg);
 
-       return status;
+       return status == SSH2_FX_OK ? 0 : -1;
 }
 
 
 static int
-do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag,
+do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag,
     SFTP_DIRENT ***dir)
 {
-       Buffer msg;
-       u_int count, type, id, handle_len, i, expected_id, ents = 0;
+       struct sshbuf *msg;
+       u_int count, id, i, expected_id, ents = 0;
+       size_t handle_len;
+       u_char type;
        char *handle;
        int status = SSH2_FX_FAILURE;
+       int r;
 
        if (dir)
                *dir = NULL;
 
        id = conn->msg_id++;
 
-       buffer_init(&msg);
-       buffer_put_char(&msg, SSH2_FXP_OPENDIR);
-       buffer_put_int(&msg, id);
-       buffer_put_cstring(&msg, path);
-       send_msg(conn, &msg);
+       if ((msg = sshbuf_new()) == NULL)
+               fatal("%s: sshbuf_new failed", __func__);
+       if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPENDIR)) != 0 ||
+           (r = sshbuf_put_u32(msg, id)) != 0 ||
+           (r = sshbuf_put_cstring(msg, path)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
+       send_msg(conn, msg);
 
        handle = get_handle(conn, id, &handle_len,
            "remote readdir(\"%s\")", path);
        if (handle == NULL) {
-               buffer_free(&msg);
+               sshbuf_free(msg);
                return -1;
        }
 
@@ -484,18 +543,20 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag,
 
                debug3("Sending SSH2_FXP_READDIR I:%u", id);
 
-               buffer_clear(&msg);
-               buffer_put_char(&msg, SSH2_FXP_READDIR);
-               buffer_put_int(&msg, id);
-               buffer_put_string(&msg, handle, handle_len);
-               send_msg(conn, &msg);
+               sshbuf_reset(msg);
+               if ((r = sshbuf_put_u8(msg, SSH2_FXP_READDIR)) != 0 ||
+                   (r = sshbuf_put_u32(msg, id)) != 0 ||
+                   (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
+                       fatal("%s: buffer error: %s", __func__, ssh_err(r));
+               send_msg(conn, msg);
 
-               buffer_clear(&msg);
+               sshbuf_reset(msg);
 
-               get_msg(conn, &msg);
+               get_msg(conn, msg);
 
-               type = buffer_get_char(&msg);
-               id = buffer_get_int(&msg);
+               if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
+                   (r = sshbuf_get_u32(msg, &id)) != 0)
+                       fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
                debug3("Received reply T:%u I:%u", type, id);
 
@@ -503,27 +564,43 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag,
                        fatal("ID mismatch (%u != %u)", id, expected_id);
 
                if (type == SSH2_FXP_STATUS) {
-                       status = buffer_get_int(&msg);
-                       debug3("Received SSH2_FXP_STATUS %d", status);
-                       if (status == SSH2_FX_EOF)
+                       u_int rstatus;
+
+                       if ((r = sshbuf_get_u32(msg, &rstatus)) != 0)
+                               fatal("%s: buffer error: %s",
+                                   __func__, ssh_err(r));
+                       debug3("Received SSH2_FXP_STATUS %d", rstatus);
+                       if (rstatus == SSH2_FX_EOF)
                                break;
-                       error("Couldn't read directory: %s", fx2txt(status));
+                       error("Couldn't read directory: %s", fx2txt(rstatus));
                        goto out;
                } else if (type != SSH2_FXP_NAME)
                        fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
                            SSH2_FXP_NAME, type);
 
-               count = buffer_get_int(&msg);
+               if ((r = sshbuf_get_u32(msg, &count)) != 0)
+                       fatal("%s: buffer error: %s", __func__, ssh_err(r));
                if (count == 0)
                        break;
                debug3("Received %d SSH2_FXP_NAME responses", count);
                for (i = 0; i < count; i++) {
                        char *filename, *longname;
-                       Attrib *a;
-
-                       filename = buffer_get_string(&msg, NULL);
-                       longname = buffer_get_string(&msg, NULL);
-                       a = decode_attrib(&msg);
+                       Attrib a;
+
+                       if ((r = sshbuf_get_cstring(msg, &filename,
+                           NULL)) != 0 ||
+                           (r = sshbuf_get_cstring(msg, &longname,
+                           NULL)) != 0)
+                               fatal("%s: buffer error: %s",
+                                   __func__, ssh_err(r));
+                       if ((r = decode_attrib(msg, &a)) != 0) {
+                               error("%s: couldn't decode attrib: %s",
+                                   __func__, ssh_err(r));
+                               free(filename);
+                               free(longname);
+                               sshbuf_free(msg);
+                               return -1;
+                       }
 
                        if (print_flag)
                                printf("%s\n", longname);
@@ -541,7 +618,7 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag,
                                (*dir)[ents] = xcalloc(1, sizeof(***dir));
                                (*dir)[ents]->filename = xstrdup(filename);
                                (*dir)[ents]->longname = xstrdup(longname);
-                               memcpy(&(*dir)[ents]->a, a, sizeof(*a));
+                               memcpy(&(*dir)[ents]->a, &a, sizeof(a));
                                (*dir)[++ents] = NULL;
                        }
                        free(filename);
@@ -551,7 +628,7 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag,
        status = 0;
 
  out:
-       buffer_free(&msg);
+       sshbuf_free(msg);
        do_close(conn, handle, handle_len);
        free(handle);
 
@@ -570,7 +647,7 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag,
 }
 
 int
-do_readdir(struct sftp_conn *conn, char *path, SFTP_DIRENT ***dir)
+do_readdir(struct sftp_conn *conn, const char *path, SFTP_DIRENT ***dir)
 {
        return(do_lsreaddir(conn, path, 0, dir));
 }
@@ -590,7 +667,7 @@ void free_sftp_dirents(SFTP_DIRENT **s)
 }
 
 int
-do_rm(struct sftp_conn *conn, char *path)
+do_rm(struct sftp_conn *conn, const char *path)
 {
        u_int status, id;
 
@@ -601,11 +678,11 @@ do_rm(struct sftp_conn *conn, char *path)
        status = get_status(conn, id);
        if (status != SSH2_FX_OK)
                error("Couldn't delete file: %s", fx2txt(status));
-       return(status);
+       return status == SSH2_FX_OK ? 0 : -1;
 }
 
 int
-do_mkdir(struct sftp_conn *conn, char *path, Attrib *a, int print_flag)
+do_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int print_flag)
 {
        u_int status, id;
 
@@ -617,11 +694,11 @@ do_mkdir(struct sftp_conn *conn, char *path, Attrib *a, int print_flag)
        if (status != SSH2_FX_OK && print_flag)
                error("Couldn't create directory: %s", fx2txt(status));
 
-       return(status);
+       return status == SSH2_FX_OK ? 0 : -1;
 }
 
 int
-do_rmdir(struct sftp_conn *conn, char *path)
+do_rmdir(struct sftp_conn *conn, const char *path)
 {
        u_int status, id;
 
@@ -633,11 +710,11 @@ do_rmdir(struct sftp_conn *conn, char *path)
        if (status != SSH2_FX_OK)
                error("Couldn't remove directory: %s", fx2txt(status));
 
-       return(status);
+       return status == SSH2_FX_OK ? 0 : -1;
 }
 
 Attrib *
-do_stat(struct sftp_conn *conn, char *path, int quiet)
+do_stat(struct sftp_conn *conn, const char *path, int quiet)
 {
        u_int id;
 
@@ -651,7 +728,7 @@ do_stat(struct sftp_conn *conn, char *path, int quiet)
 }
 
 Attrib *
-do_lstat(struct sftp_conn *conn, char *path, int quiet)
+do_lstat(struct sftp_conn *conn, const char *path, int quiet)
 {
        u_int id;
 
@@ -672,7 +749,8 @@ do_lstat(struct sftp_conn *conn, char *path, int quiet)
 
 #ifdef notyet
 Attrib *
-do_fstat(struct sftp_conn *conn, char *handle, u_int handle_len, int quiet)
+do_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
+    int quiet)
 {
        u_int id;
 
@@ -685,7 +763,7 @@ do_fstat(struct sftp_conn *conn, char *handle, u_int handle_len, int quiet)
 #endif
 
 int
-do_setstat(struct sftp_conn *conn, char *path, Attrib *a)
+do_setstat(struct sftp_conn *conn, const char *path, Attrib *a)
 {
        u_int status, id;
 
@@ -698,11 +776,11 @@ do_setstat(struct sftp_conn *conn, char *path, Attrib *a)
                error("Couldn't setstat on \"%s\": %s", path,
                    fx2txt(status));
 
-       return(status);
+       return status == SSH2_FX_OK ? 0 : -1;
 }
 
 int
-do_fsetstat(struct sftp_conn *conn, char *handle, u_int handle_len,
+do_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
     Attrib *a)
 {
        u_int status, id;
@@ -715,181 +793,201 @@ do_fsetstat(struct sftp_conn *conn, char *handle, u_int handle_len,
        if (status != SSH2_FX_OK)
                error("Couldn't fsetstat: %s", fx2txt(status));
 
-       return(status);
+       return status == SSH2_FX_OK ? 0 : -1;
 }
 
 char *
-do_realpath(struct sftp_conn *conn, char *path)
+do_realpath(struct sftp_conn *conn, const char *path)
 {
-       Buffer msg;
-       u_int type, expected_id, count, id;
+       struct sshbuf *msg;
+       u_int expected_id, count, id;
        char *filename, *longname;
-       Attrib *a;
+       Attrib a;
+       u_char type;
+       int r;
 
        expected_id = id = conn->msg_id++;
        send_string_request(conn, id, SSH2_FXP_REALPATH, path,
            strlen(path));
 
-       buffer_init(&msg);
+       if ((msg = sshbuf_new()) == NULL)
+               fatal("%s: sshbuf_new failed", __func__);
 
-       get_msg(conn, &msg);
-       type = buffer_get_char(&msg);
-       id = buffer_get_int(&msg);
+       get_msg(conn, msg);
+       if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
+           (r = sshbuf_get_u32(msg, &id)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
        if (id != expected_id)
                fatal("ID mismatch (%u != %u)", id, expected_id);
 
        if (type == SSH2_FXP_STATUS) {
-               u_int status = buffer_get_int(&msg);
+               u_int status;
 
+               if ((r = sshbuf_get_u32(msg, &status)) != 0)
+                       fatal("%s: buffer error: %s", __func__, ssh_err(r));
                error("Couldn't canonicalize: %s", fx2txt(status));
-               buffer_free(&msg);
+               sshbuf_free(msg);
                return NULL;
        } else if (type != SSH2_FXP_NAME)
                fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
                    SSH2_FXP_NAME, type);
 
-       count = buffer_get_int(&msg);
+       if ((r = sshbuf_get_u32(msg, &count)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
        if (count != 1)
                fatal("Got multiple names (%d) from SSH_FXP_REALPATH", count);
 
-       filename = buffer_get_string(&msg, NULL);
-       longname = buffer_get_string(&msg, NULL);
-       a = decode_attrib(&msg);
+       if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 ||
+           (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 ||
+           (r = decode_attrib(msg, &a)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
        debug3("SSH_FXP_REALPATH %s -> %s size %lu", path, filename,
-           (unsigned long)a->size);
+           (unsigned long)a.size);
 
        free(longname);
 
-       buffer_free(&msg);
+       sshbuf_free(msg);
 
        return(filename);
 }
 
 int
-do_rename(struct sftp_conn *conn, char *oldpath, char *newpath,
+do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath,
     int force_legacy)
 {
-       Buffer msg;
+       struct sshbuf *msg;
        u_int status, id;
-       int use_ext = (conn->exts & SFTP_EXT_POSIX_RENAME) && !force_legacy;
+       int r, use_ext = (conn->exts & SFTP_EXT_POSIX_RENAME) && !force_legacy;
 
-       buffer_init(&msg);
+       if ((msg = sshbuf_new()) == NULL)
+               fatal("%s: sshbuf_new failed", __func__);
 
        /* Send rename request */
        id = conn->msg_id++;
        if (use_ext) {
-               buffer_put_char(&msg, SSH2_FXP_EXTENDED);
-               buffer_put_int(&msg, id);
-               buffer_put_cstring(&msg, "posix-rename@openssh.com");
+               if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
+                   (r = sshbuf_put_u32(msg, id)) != 0 ||
+                   (r = sshbuf_put_cstring(msg,
+                   "posix-rename@openssh.com")) != 0)
+                       fatal("%s: buffer error: %s", __func__, ssh_err(r));
        } else {
-               buffer_put_char(&msg, SSH2_FXP_RENAME);
-               buffer_put_int(&msg, id);
+               if ((r = sshbuf_put_u8(msg, SSH2_FXP_RENAME)) != 0 ||
+                   (r = sshbuf_put_u32(msg, id)) != 0)
+                       fatal("%s: buffer error: %s", __func__, ssh_err(r));
        }
-       buffer_put_cstring(&msg, oldpath);
-       buffer_put_cstring(&msg, newpath);
-       send_msg(conn, &msg);
+       if ((r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
+           (r = sshbuf_put_cstring(msg, newpath)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
+       send_msg(conn, msg);
        debug3("Sent message %s \"%s\" -> \"%s\"",
-           use_ext ? "posix-rename@openssh.com" : "SSH2_FXP_RENAME",
-           oldpath, newpath);
-       buffer_free(&msg);
+           use_ext ? "posix-rename@openssh.com" :
+           "SSH2_FXP_RENAME", oldpath, newpath);
+       sshbuf_free(msg);
 
        status = get_status(conn, id);
        if (status != SSH2_FX_OK)
                error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath,
                    newpath, fx2txt(status));
 
-       return(status);
+       return status == SSH2_FX_OK ? 0 : -1;
 }
 
 int
-do_hardlink(struct sftp_conn *conn, char *oldpath, char *newpath)
+do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
 {
-       Buffer msg;
+       struct sshbuf *msg;
        u_int status, id;
+       int r;
 
        if ((conn->exts & SFTP_EXT_HARDLINK) == 0) {
                error("Server does not support hardlink@openssh.com extension");
                return -1;
        }
 
-       buffer_init(&msg);
+       if ((msg = sshbuf_new()) == NULL)
+               fatal("%s: sshbuf_new failed", __func__);
 
        /* Send link request */
        id = conn->msg_id++;
-       buffer_put_char(&msg, SSH2_FXP_EXTENDED);
-       buffer_put_int(&msg, id);
-       buffer_put_cstring(&msg, "hardlink@openssh.com");
-       buffer_put_cstring(&msg, oldpath);
-       buffer_put_cstring(&msg, newpath);
-       send_msg(conn, &msg);
+       if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
+           (r = sshbuf_put_u32(msg, id)) != 0 ||
+           (r = sshbuf_put_cstring(msg, "hardlink@openssh.com")) != 0 ||
+           (r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
+           (r = sshbuf_put_cstring(msg, newpath)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
+       send_msg(conn, msg);
        debug3("Sent message hardlink@openssh.com \"%s\" -> \"%s\"",
               oldpath, newpath);
-       buffer_free(&msg);
+       sshbuf_free(msg);
 
        status = get_status(conn, id);
        if (status != SSH2_FX_OK)
                error("Couldn't link file \"%s\" to \"%s\": %s", oldpath,
                    newpath, fx2txt(status));
 
-       return(status);
+       return status == SSH2_FX_OK ? 0 : -1;
 }
 
 int
-do_symlink(struct sftp_conn *conn, char *oldpath, char *newpath)
+do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
 {
-       Buffer msg;
+       struct sshbuf *msg;
        u_int status, id;
+       int r;
 
        if (conn->version < 3) {
                error("This server does not support the symlink operation");
                return(SSH2_FX_OP_UNSUPPORTED);
        }
 
-       buffer_init(&msg);
+       if ((msg = sshbuf_new()) == NULL)
+               fatal("%s: sshbuf_new failed", __func__);
 
        /* Send symlink request */
        id = conn->msg_id++;
-       buffer_put_char(&msg, SSH2_FXP_SYMLINK);
-       buffer_put_int(&msg, id);
-       buffer_put_cstring(&msg, oldpath);
-       buffer_put_cstring(&msg, newpath);
-       send_msg(conn, &msg);
+       if ((r = sshbuf_put_u8(msg, SSH2_FXP_SYMLINK)) != 0 ||
+           (r = sshbuf_put_u32(msg, id)) != 0 ||
+           (r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
+           (r = sshbuf_put_cstring(msg, newpath)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
+       send_msg(conn, msg);
        debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath,
            newpath);
-       buffer_free(&msg);
+       sshbuf_free(msg);
 
        status = get_status(conn, id);
        if (status != SSH2_FX_OK)
                error("Couldn't symlink file \"%s\" to \"%s\": %s", oldpath,
                    newpath, fx2txt(status));
 
-       return(status);
+       return status == SSH2_FX_OK ? 0 : -1;
 }
 
 int
-do_fsync(struct sftp_conn *conn, char *handle, u_int handle_len)
+do_fsync(struct sftp_conn *conn, u_char *handle, u_int handle_len)
 {
-       Buffer msg;
+       struct sshbuf *msg;
        u_int status, id;
+       int r;
 
        /* Silently return if the extension is not supported */
        if ((conn->exts & SFTP_EXT_FSYNC) == 0)
                return -1;
 
-       buffer_init(&msg);
-
        /* Send fsync request */
+       if ((msg = sshbuf_new()) == NULL)
+               fatal("%s: sshbuf_new failed", __func__);
        id = conn->msg_id++;
-
-       buffer_put_char(&msg, SSH2_FXP_EXTENDED);
-       buffer_put_int(&msg, id);
-       buffer_put_cstring(&msg, "fsync@openssh.com");
-       buffer_put_string(&msg, handle, handle_len);
-       send_msg(conn, &msg);
+       if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
+           (r = sshbuf_put_u32(msg, id)) != 0 ||
+           (r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 ||
+           (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
+       send_msg(conn, msg);
        debug3("Sent message fsync@openssh.com I:%u", id);
-       buffer_free(&msg);
+       sshbuf_free(msg);
 
        status = get_status(conn, id);
        if (status != SSH2_FX_OK)
@@ -900,50 +998,58 @@ do_fsync(struct sftp_conn *conn, char *handle, u_int handle_len)
 
 #ifdef notyet
 char *
-do_readlink(struct sftp_conn *conn, char *path)
+do_readlink(struct sftp_conn *conn, const char *path)
 {
-       Buffer msg;
-       u_int type, expected_id, count, id;
+       struct sshbuf *msg;
+       u_int expected_id, count, id;
        char *filename, *longname;
-       Attrib *a;
+       Attrib a;
+       u_char type;
+       int r;
 
        expected_id = id = conn->msg_id++;
        send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path));
 
-       buffer_init(&msg);
+       if ((msg = sshbuf_new()) == NULL)
+               fatal("%s: sshbuf_new failed", __func__);
 
-       get_msg(conn, &msg);
-       type = buffer_get_char(&msg);
-       id = buffer_get_int(&msg);
+       get_msg(conn, msg);
+       if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
+           (r = sshbuf_get_u32(msg, &id)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
        if (id != expected_id)
                fatal("ID mismatch (%u != %u)", id, expected_id);
 
        if (type == SSH2_FXP_STATUS) {
-               u_int status = buffer_get_int(&msg);
+               u_int status;
 
+               if ((r = sshbuf_get_u32(msg, &status)) != 0)
+                       fatal("%s: buffer error: %s", __func__, ssh_err(r));
                error("Couldn't readlink: %s", fx2txt(status));
-               buffer_free(&msg);
+               sshbuf_free(msg);
                return(NULL);
        } else if (type != SSH2_FXP_NAME)
                fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
                    SSH2_FXP_NAME, type);
 
-       count = buffer_get_int(&msg);
+       if ((r = sshbuf_get_u32(msg, &count)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
        if (count != 1)
                fatal("Got multiple names (%d) from SSH_FXP_READLINK", count);
 
-       filename = buffer_get_string(&msg, NULL);
-       longname = buffer_get_string(&msg, NULL);
-       a = decode_attrib(&msg);
+       if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 ||
+           (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 ||
+           (r = decode_attrib(msg, &a)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
        debug3("SSH_FXP_READLINK %s -> %s", path, filename);
 
        free(longname);
 
-       buffer_free(&msg);
+       sshbuf_free(msg);
 
-       return(filename);
+       return filename;
 }
 #endif
 
@@ -951,8 +1057,9 @@ int
 do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st,
     int quiet)
 {
-       Buffer msg;
+       struct sshbuf *msg;
        u_int id;
+       int r;
 
        if ((conn->exts & SFTP_EXT_STATVFS) == 0) {
                error("Server does not support statvfs@openssh.com extension");
@@ -961,24 +1068,26 @@ do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st,
 
        id = conn->msg_id++;
 
-       buffer_init(&msg);
-       buffer_clear(&msg);
-       buffer_put_char(&msg, SSH2_FXP_EXTENDED);
-       buffer_put_int(&msg, id);
-       buffer_put_cstring(&msg, "statvfs@openssh.com");
-       buffer_put_cstring(&msg, path);
-       send_msg(conn, &msg);
-       buffer_free(&msg);
+       if ((msg = sshbuf_new()) == NULL)
+               fatal("%s: sshbuf_new failed", __func__);
+       sshbuf_reset(msg);
+       if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
+           (r = sshbuf_put_u32(msg, id)) != 0 ||
+           (r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 ||
+           (r = sshbuf_put_cstring(msg, path)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
+       send_msg(conn, msg);
+       sshbuf_free(msg);
 
        return get_decode_statvfs(conn, st, id, quiet);
 }
 
 #ifdef notyet
 int
-do_fstatvfs(struct sftp_conn *conn, const char *handle, u_int handle_len,
+do_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
     struct sftp_statvfs *st, int quiet)
 {
-       Buffer msg;
+       struct sshbuf *msg;
        u_int id;
 
        if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) {
@@ -988,14 +1097,16 @@ do_fstatvfs(struct sftp_conn *conn, const char *handle, u_int handle_len,
 
        id = conn->msg_id++;
 
-       buffer_init(&msg);
-       buffer_clear(&msg);
-       buffer_put_char(&msg, SSH2_FXP_EXTENDED);
-       buffer_put_int(&msg, id);
-       buffer_put_cstring(&msg, "fstatvfs@openssh.com");
-       buffer_put_string(&msg, handle, handle_len);
-       send_msg(conn, &msg);
-       buffer_free(&msg);
+       if ((msg = sshbuf_new()) == NULL)
+               fatal("%s: sshbuf_new failed", __func__);
+       sshbuf_reset(msg);
+       if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
+           (r = sshbuf_put_u32(msg, id)) != 0 ||
+           (r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 ||
+           (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
+       send_msg(conn, msg);
+       sshbuf_free(msg);
 
        return get_decode_statvfs(conn, st, id, quiet);
 }
@@ -1003,42 +1114,48 @@ do_fstatvfs(struct sftp_conn *conn, const char *handle, u_int handle_len,
 
 static void
 send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset,
-    u_int len, char *handle, u_int handle_len)
+    u_int len, const u_char *handle, u_int handle_len)
 {
-       Buffer msg;
-
-       buffer_init(&msg);
-       buffer_clear(&msg);
-       buffer_put_char(&msg, SSH2_FXP_READ);
-       buffer_put_int(&msg, id);
-       buffer_put_string(&msg, handle, handle_len);
-       buffer_put_int64(&msg, offset);
-       buffer_put_int(&msg, len);
-       send_msg(conn, &msg);
-       buffer_free(&msg);
+       struct sshbuf *msg;
+       int r;
+
+       if ((msg = sshbuf_new()) == NULL)
+               fatal("%s: sshbuf_new failed", __func__);
+       sshbuf_reset(msg);
+       if ((r = sshbuf_put_u8(msg, SSH2_FXP_READ)) != 0 ||
+           (r = sshbuf_put_u32(msg, id)) != 0 ||
+           (r = sshbuf_put_string(msg, handle, handle_len)) != 0 ||
+           (r = sshbuf_put_u64(msg, offset)) != 0 ||
+           (r = sshbuf_put_u32(msg, len)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
+       send_msg(conn, msg);
+       sshbuf_free(msg);
 }
 
 int
-do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
-    Attrib *a, int preserve_flag, int resume_flag, int fsync_flag)
+do_download(struct sftp_conn *conn, const char *remote_path,
+    const char *local_path, Attrib *a, int preserve_flag, int resume_flag,
+    int fsync_flag)
 {
        Attrib junk;
-       Buffer msg;
-       char *handle;
-       int local_fd = -1, status = 0, write_error;
-       int read_error, write_errno, reordered = 0;
+       struct sshbuf *msg;
+       u_char *handle;
+       int local_fd = -1, write_error;
+       int read_error, write_errno, reordered = 0, r;
        u_int64_t offset = 0, size, highwater;
-       u_int handle_len, mode, type, id, buflen, num_req, max_req;
+       u_int mode, id, buflen, num_req, max_req, status = SSH2_FX_OK;
        off_t progress_counter;
+       size_t handle_len;
        struct stat st;
        struct request {
                u_int id;
-               u_int len;
+               size_t len;
                u_int64_t offset;
                TAILQ_ENTRY(request) tq;
        };
        TAILQ_HEAD(reqhead, request) requests;
        struct request *req;
+       u_char type;
 
        TAILQ_INIT(&requests);
 
@@ -1063,23 +1180,26 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
                size = 0;
 
        buflen = conn->transfer_buflen;
-       buffer_init(&msg);
+       if ((msg = sshbuf_new()) == NULL)
+               fatal("%s: sshbuf_new failed", __func__);
+
+       attrib_clear(&junk); /* Send empty attributes */
 
        /* Send open request */
        id = conn->msg_id++;
-       buffer_put_char(&msg, SSH2_FXP_OPEN);
-       buffer_put_int(&msg, id);
-       buffer_put_cstring(&msg, remote_path);
-       buffer_put_int(&msg, SSH2_FXF_READ);
-       attrib_clear(&junk); /* Send empty attributes */
-       encode_attrib(&msg, &junk);
-       send_msg(conn, &msg);
+       if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 ||
+           (r = sshbuf_put_u32(msg, id)) != 0 ||
+           (r = sshbuf_put_cstring(msg, remote_path)) != 0 ||
+           (r = sshbuf_put_u32(msg, SSH2_FXF_READ)) != 0 ||
+           (r = encode_attrib(msg, &junk)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
+       send_msg(conn, msg);
        debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path);
 
        handle = get_handle(conn, id, &handle_len,
            "remote open(\"%s\")", remote_path);
        if (handle == NULL) {
-               buffer_free(&msg);
+               sshbuf_free(msg);
                return(-1);
        }
 
@@ -1106,7 +1226,7 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
                            "local file is larger than remote", local_path);
  fail:
                        do_close(conn, handle, handle_len);
-                       buffer_free(&msg);
+                       sshbuf_free(msg);
                        free(handle);
                        if (local_fd != -1)
                                close(local_fd);
@@ -1124,8 +1244,8 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
                start_progress_meter(remote_path, size, &progress_counter);
 
        while (num_req > 0 || max_req > 0) {
-               char *data;
-               u_int len;
+               u_char *data;
+               size_t len;
 
                /*
                 * Simulate EOF on interrupt: stop sending new requests and
@@ -1154,10 +1274,11 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
                            req->len, handle, handle_len);
                }
 
-               buffer_clear(&msg);
-               get_msg(conn, &msg);
-               type = buffer_get_char(&msg);
-               id = buffer_get_int(&msg);
+               sshbuf_reset(msg);
+               get_msg(conn, msg);
+               if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
+                   (r = sshbuf_get_u32(msg, &id)) != 0)
+                       fatal("%s: buffer error: %s", __func__, ssh_err(r));
                debug3("Received reply T:%u I:%u R:%d", type, id, max_req);
 
                /* Find the request in our queue */
@@ -1170,7 +1291,9 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
 
                switch (type) {
                case SSH2_FXP_STATUS:
-                       status = buffer_get_int(&msg);
+                       if ((r = sshbuf_get_u32(msg, &status)) != 0)
+                               fatal("%s: buffer error: %s",
+                                   __func__, ssh_err(r));
                        if (status != SSH2_FX_EOF)
                                read_error = 1;
                        max_req = 0;
@@ -1179,13 +1302,15 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
                        num_req--;
                        break;
                case SSH2_FXP_DATA:
-                       data = buffer_get_string(&msg, &len);
+                       if ((r = sshbuf_get_string(msg, &data, &len)) != 0)
+                               fatal("%s: buffer error: %s",
+                                   __func__, ssh_err(r));
                        debug3("Received data %llu -> %llu",
                            (unsigned long long)req->offset,
                            (unsigned long long)req->offset + len - 1);
                        if (len > req->len)
                                fatal("Received more data than asked for "
-                                   "%u > %u", len, req->len);
+                                   "%zu > %zu", len, req->len);
                        if ((lseek(local_fd, req->offset, SEEK_SET) == -1 ||
                            atomicio(vwrite, local_fd, data, len) != len) &&
                            !write_error) {
@@ -1262,12 +1387,13 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
        } else if (write_error) {
                error("Couldn't write to \"%s\": %s", local_path,
                    strerror(write_errno));
-               status = -1;
+               status = SSH2_FX_FAILURE;
                do_close(conn, handle, handle_len);
        } else {
-               status = do_close(conn, handle, handle_len);
-               if (interrupted || status != SSH2_FX_OK)
-                       status = -1;
+               if (do_close(conn, handle, handle_len) != 0 || interrupted)
+                       status = SSH2_FX_FAILURE;
+               else
+                       status = SSH2_FX_OK;
                /* Override umask and utimes if asked */
                if (preserve_flag && fchmod(local_fd, mode) == -1)
                        error("Couldn't set mode on \"%s\": %s", local_path,
@@ -1290,16 +1416,16 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
                }
        }
        close(local_fd);
-       buffer_free(&msg);
+       sshbuf_free(msg);
        free(handle);
 
        return(status);
 }
 
 static int
-download_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth,
-    Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag,
-    int fsync_flag)
+download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
+    int depth, Attrib *dirattrib, int preserve_flag, int print_flag,
+    int resume_flag, int fsync_flag)
 {
        int i, ret = 0;
        SFTP_DIRENT **dir_entries;
@@ -1389,9 +1515,9 @@ download_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth,
 }
 
 int
-download_dir(struct sftp_conn *conn, char *src, char *dst,
-    Attrib *dirattrib, int preserve_flag, int print_flag,
-    int resume_flag, int fsync_flag)
+download_dir(struct sftp_conn *conn, const char *src, const char *dst,
+    Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag,
+    int fsync_flag)
 {
        char *src_canon;
        int ret;
@@ -1408,15 +1534,16 @@ download_dir(struct sftp_conn *conn, char *src, char *dst,
 }
 
 int
-do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
-    int preserve_flag, int resume, int fsync_flag)
+do_upload(struct sftp_conn *conn, const char *local_path,
+    const char *remote_path, int preserve_flag, int resume, int fsync_flag)
 {
-       int local_fd;
-       int status = SSH2_FX_OK;
-       u_int handle_len, id, type;
+       int r, local_fd;
+       u_int status = SSH2_FX_OK;
+       u_int id;
+       u_char type;
        off_t offset, progress_counter;
-       char *handle, *data;
-       Buffer msg;
+       u_char *handle, *data;
+       struct sshbuf *msg;
        struct stat sb;
        Attrib a, *c = NULL;
        u_int32_t startid;
@@ -1429,6 +1556,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
        };
        TAILQ_HEAD(ackhead, outstanding_ack) acks;
        struct outstanding_ack *ack = NULL;
+       size_t handle_len;
 
        TAILQ_INIT(&acks);
 
@@ -1476,26 +1604,28 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
                }
        }
 
-       buffer_init(&msg);
+       if ((msg = sshbuf_new()) == NULL)
+               fatal("%s: sshbuf_new failed", __func__);
 
        /* Send open request */
        id = conn->msg_id++;
-       buffer_put_char(&msg, SSH2_FXP_OPEN);
-       buffer_put_int(&msg, id);
-       buffer_put_cstring(&msg, remote_path);
-       buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|
-                     (resume ? SSH2_FXF_APPEND : SSH2_FXF_TRUNC));
-       encode_attrib(&msg, &a);
-       send_msg(conn, &msg);
+       if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 ||
+           (r = sshbuf_put_u32(msg, id)) != 0 ||
+           (r = sshbuf_put_cstring(msg, remote_path)) != 0 ||
+           (r = sshbuf_put_u32(msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|
+           (resume ? SSH2_FXF_APPEND : SSH2_FXF_TRUNC))) != 0 ||
+           (r = encode_attrib(msg, &a)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
+       send_msg(conn, msg);
        debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path);
 
-       buffer_clear(&msg);
+       sshbuf_reset(msg);
 
        handle = get_handle(conn, id, &handle_len,
            "remote open(\"%s\")", remote_path);
        if (handle == NULL) {
                close(local_fd);
-               buffer_free(&msg);
+               sshbuf_free(msg);
                return -1;
        }
 
@@ -1534,13 +1664,16 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
                        ack->len = len;
                        TAILQ_INSERT_TAIL(&acks, ack, tq);
 
-                       buffer_clear(&msg);
-                       buffer_put_char(&msg, SSH2_FXP_WRITE);
-                       buffer_put_int(&msg, ack->id);
-                       buffer_put_string(&msg, handle, handle_len);
-                       buffer_put_int64(&msg, offset);
-                       buffer_put_string(&msg, data, len);
-                       send_msg(conn, &msg);
+                       sshbuf_reset(msg);
+                       if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 ||
+                           (r = sshbuf_put_u32(msg, ack->id)) != 0 ||
+                           (r = sshbuf_put_string(msg, handle,
+                           handle_len)) != 0 ||
+                           (r = sshbuf_put_u64(msg, offset)) != 0 ||
+                           (r = sshbuf_put_string(msg, data, len)) != 0)
+                               fatal("%s: buffer error: %s",
+                                   __func__, ssh_err(r));
+                       send_msg(conn, msg);
                        debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u",
                            id, (unsigned long long)offset, len);
                } else if (TAILQ_FIRST(&acks) == NULL)
@@ -1551,27 +1684,31 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
 
                if (id == startid || len == 0 ||
                    id - ackid >= conn->num_requests) {
-                       u_int r_id;
+                       u_int rid;
 
-                       buffer_clear(&msg);
-                       get_msg(conn, &msg);
-                       type = buffer_get_char(&msg);
-                       r_id = buffer_get_int(&msg);
+                       sshbuf_reset(msg);
+                       get_msg(conn, msg);
+                       if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
+                           (r = sshbuf_get_u32(msg, &rid)) != 0)
+                               fatal("%s: buffer error: %s",
+                                   __func__, ssh_err(r));
 
                        if (type != SSH2_FXP_STATUS)
                                fatal("Expected SSH2_FXP_STATUS(%d) packet, "
                                    "got %d", SSH2_FXP_STATUS, type);
 
-                       status = buffer_get_int(&msg);
-                       debug3("SSH2_FXP_STATUS %d", status);
+                       if ((r = sshbuf_get_u32(msg, &status)) != 0)
+                               fatal("%s: buffer error: %s",
+                                   __func__, ssh_err(r));
+                       debug3("SSH2_FXP_STATUS %u", status);
 
                        /* Find the request in our queue */
                        for (ack = TAILQ_FIRST(&acks);
-                           ack != NULL && ack->id != r_id;
+                           ack != NULL && ack->id != rid;
                            ack = TAILQ_NEXT(ack, tq))
                                ;
                        if (ack == NULL)
-                               fatal("Can't find request for ID %u", r_id);
+                               fatal("Can't find request for ID %u", rid);
                        TAILQ_REMOVE(&acks, ack, tq);
                        debug3("In write loop, ack for %u %u bytes at %lld",
                            ack->id, ack->len, (long long)ack->offset);
@@ -1583,7 +1720,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
                if (offset < 0)
                        fatal("%s: offset < 0", __func__);
        }
-       buffer_free(&msg);
+       sshbuf_free(msg);
 
        if (showprogress)
                stop_progress_meter();
@@ -1592,13 +1729,13 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
        if (status != SSH2_FX_OK) {
                error("Couldn't write to remote file \"%s\": %s",
                    remote_path, fx2txt(status));
-               status = -1;
+               status = SSH2_FX_FAILURE;
        }
 
        if (close(local_fd) == -1) {
                error("Couldn't close local file \"%s\": %s", local_path,
                    strerror(errno));
-               status = -1;
+               status = SSH2_FX_FAILURE;
        }
 
        /* Override umask and utimes if asked */
@@ -1609,17 +1746,19 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
                (void)do_fsync(conn, handle, handle_len);
 
        if (do_close(conn, handle, handle_len) != SSH2_FX_OK)
-               status = -1;
+               status = SSH2_FX_FAILURE;
+
        free(handle);
 
-       return status;
+       return status == SSH2_FX_OK ? 0 : -1;
 }
 
 static int
-upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth,
-    int preserve_flag, int print_flag, int resume, int fsync_flag)
+upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
+    int depth, int preserve_flag, int print_flag, int resume, int fsync_flag)
 {
-       int ret = 0, status;
+       int ret = 0;
+       u_int status;
        DIR *dirp;
        struct dirent *dp;
        char *filename, *new_src, *new_dst;
@@ -1709,8 +1848,8 @@ upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth,
 }
 
 int
-upload_dir(struct sftp_conn *conn, char *src, char *dst, int preserve_flag,
-    int print_flag, int resume, int fsync_flag)
+upload_dir(struct sftp_conn *conn, const char *src, const char *dst,
+    int preserve_flag, int print_flag, int resume, int fsync_flag)
 {
        char *dst_canon;
        int ret;
@@ -1728,7 +1867,7 @@ upload_dir(struct sftp_conn *conn, char *src, char *dst, int preserve_flag,
 }
 
 char *
-path_append(char *p1, char *p2)
+path_append(const char *p1, const char *p2)
 {
        char *ret;
        size_t len = strlen(p1) + strlen(p2) + 2;
index 967840b..507d763 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp-client.h,v 1.25 2014/04/21 14:36:16 logan Exp $ */
+/* $OpenBSD: sftp-client.h,v 1.26 2015/01/14 13:54:13 djm Exp $ */
 
 /*
  * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
@@ -56,79 +56,81 @@ struct sftp_conn *do_init(int, int, u_int, u_int, u_int64_t);
 u_int sftp_proto_version(struct sftp_conn *);
 
 /* Close file referred to by 'handle' */
-int do_close(struct sftp_conn *, char *, u_int);
+int do_close(struct sftp_conn *, const u_char *, u_int);
 
 /* Read contents of 'path' to NULL-terminated array 'dir' */
-int do_readdir(struct sftp_conn *, char *, SFTP_DIRENT ***);
+int do_readdir(struct sftp_conn *, const char *, SFTP_DIRENT ***);
 
 /* Frees a NULL-terminated array of SFTP_DIRENTs (eg. from do_readdir) */
 void free_sftp_dirents(SFTP_DIRENT **);
 
 /* Delete file 'path' */
-int do_rm(struct sftp_conn *, char *);
+int do_rm(struct sftp_conn *, const char *);
 
 /* Create directory 'path' */
-int do_mkdir(struct sftp_conn *, char *, Attrib *, int);
+int do_mkdir(struct sftp_conn *, const char *, Attrib *, int);
 
 /* Remove directory 'path' */
-int do_rmdir(struct sftp_conn *, char *);
+int do_rmdir(struct sftp_conn *, const char *);
 
 /* Get file attributes of 'path' (follows symlinks) */
-Attrib *do_stat(struct sftp_conn *, char *, int);
+Attrib *do_stat(struct sftp_conn *, const char *, int);
 
 /* Get file attributes of 'path' (does not follow symlinks) */
-Attrib *do_lstat(struct sftp_conn *, char *, int);
+Attrib *do_lstat(struct sftp_conn *, const char *, int);
 
 /* Set file attributes of 'path' */
-int do_setstat(struct sftp_conn *, char *, Attrib *);
+int do_setstat(struct sftp_conn *, const char *, Attrib *);
 
 /* Set file attributes of open file 'handle' */
-int do_fsetstat(struct sftp_conn *, char *, u_int, Attrib *);
+int do_fsetstat(struct sftp_conn *, const u_char *, u_int, Attrib *);
 
 /* Canonicalise 'path' - caller must free result */
-char *do_realpath(struct sftp_conn *, char *);
+char *do_realpath(struct sftp_conn *, const char *);
 
 /* Get statistics for filesystem hosting file at "path" */
 int do_statvfs(struct sftp_conn *, const char *, struct sftp_statvfs *, int);
 
 /* Rename 'oldpath' to 'newpath' */
-int do_rename(struct sftp_conn *, char *, char *m, int force_legacy);
+int do_rename(struct sftp_conn *, const char *, const char *, int force_legacy);
 
 /* Link 'oldpath' to 'newpath' */
-int do_hardlink(struct sftp_conn *, char *, char *);
+int do_hardlink(struct sftp_conn *, const char *, const char *);
 
 /* Rename 'oldpath' to 'newpath' */
-int do_symlink(struct sftp_conn *, char *, char *);
+int do_symlink(struct sftp_conn *, const char *, const char *);
 
 /* Call fsync() on open file 'handle' */
-int do_fsync(struct sftp_conn *conn, char *, u_int);
+int do_fsync(struct sftp_conn *conn, u_char *, u_int);
 
 /*
  * Download 'remote_path' to 'local_path'. Preserve permissions and times
  * if 'pflag' is set
  */
-int do_download(struct sftp_conn *, char *, char *, Attrib *, int, int, int);
+int do_download(struct sftp_conn *, const char *, const char *,
+    Attrib *, int, int, int);
 
 /*
  * Recursively download 'remote_directory' to 'local_directory'. Preserve 
  * times if 'pflag' is set
  */
-int download_dir(struct sftp_conn *, char *, char *, Attrib *, int,
-    int, int, int);
+int download_dir(struct sftp_conn *, const char *, const char *,
+    Attrib *, int, int, int, int);
 
 /*
  * Upload 'local_path' to 'remote_path'. Preserve permissions and times
  * if 'pflag' is set
  */
-int do_upload(struct sftp_conn *, char *, char *, int, int, int);
+int do_upload(struct sftp_conn *, const char *, const char *, int, int, int);
 
 /*
  * Recursively upload 'local_directory' to 'remote_directory'. Preserve 
  * times if 'pflag' is set
  */
-int upload_dir(struct sftp_conn *, char *, char *, int, int, int, int);
+int upload_dir(struct sftp_conn *, const char *, const char *, int, int, int,
+    int);
 
 /* Concatenate paths, taking care of slashes. Caller must free result. */
-char *path_append(char *, char *);
+char *path_append(const char *, const char *);
 
 #endif
index ba73ba7..d51e632 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp-common.c,v 1.26 2014/01/09 03:26:00 guenther Exp $ */
+/* $OpenBSD: sftp-common.c,v 1.27 2015/01/14 13:54:13 djm Exp $ */
 /*
  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
  * Copyright (c) 2001 Damien Miller.  All rights reserved.
@@ -38,7 +38,8 @@
 #include <util.h>
 
 #include "xmalloc.h"
-#include "buffer.h"
+#include "ssherr.h"
+#include "sshbuf.h"
 #include "log.h"
 
 #include "sftp.h"
@@ -96,59 +97,81 @@ attrib_to_stat(const Attrib *a, struct stat *st)
 }
 
 /* Decode attributes in buffer */
-Attrib *
-decode_attrib(Buffer *b)
+int
+decode_attrib(struct sshbuf *b, Attrib *a)
 {
-       static Attrib a;
-
-       attrib_clear(&a);
-       a.flags = buffer_get_int(b);
-       if (a.flags & SSH2_FILEXFER_ATTR_SIZE)
-               a.size = buffer_get_int64(b);
-       if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) {
-               a.uid = buffer_get_int(b);
-               a.gid = buffer_get_int(b);
-       }
-       if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
-               a.perm = buffer_get_int(b);
-       if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
-               a.atime = buffer_get_int(b);
-               a.mtime = buffer_get_int(b);
+       int r;
+
+       attrib_clear(a);
+       if ((r = sshbuf_get_u32(b, &a->flags)) != 0)
+               return r;
+       if (a->flags & SSH2_FILEXFER_ATTR_SIZE) {
+               if ((r = sshbuf_get_u64(b, &a->size)) != 0)
+                       return r;
+       }
+       if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
+               if ((r = sshbuf_get_u32(b, &a->uid)) != 0 ||
+                   (r = sshbuf_get_u32(b, &a->gid)) != 0)
+                       return r;
+       }
+       if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
+               if ((r = sshbuf_get_u32(b, &a->perm)) != 0)
+                       return r;
+       }
+       if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
+               if ((r = sshbuf_get_u32(b, &a->atime)) != 0 ||
+                   (r = sshbuf_get_u32(b, &a->mtime)) != 0)
+                       return r;
        }
        /* vendor-specific extensions */
-       if (a.flags & SSH2_FILEXFER_ATTR_EXTENDED) {
-               char *type, *data;
-               int i, count;
+       if (a->flags & SSH2_FILEXFER_ATTR_EXTENDED) {
+               char *type;
+               u_char *data;
+               size_t dlen;
+               u_int i, count;
 
-               count = buffer_get_int(b);
+               if ((r = sshbuf_get_u32(b, &count)) != 0)
+                       fatal("%s: buffer error: %s", __func__, ssh_err(r));
                for (i = 0; i < count; i++) {
-                       type = buffer_get_string(b, NULL);
-                       data = buffer_get_string(b, NULL);
-                       debug3("Got file attribute \"%s\"", type);
+                       if ((r = sshbuf_get_cstring(b, &type, NULL)) != 0 ||
+                           (r = sshbuf_get_string(b, &data, &dlen)) != 0)
+                               return r;
+                       debug3("Got file attribute \"%.100s\" len %zu",
+                           type, dlen);
                        free(type);
                        free(data);
                }
        }
-       return &a;
+       return 0;
 }
 
 /* Encode attributes to buffer */
-void
-encode_attrib(Buffer *b, const Attrib *a)
+int
+encode_attrib(struct sshbuf *b, const Attrib *a)
 {
-       buffer_put_int(b, a->flags);
-       if (a->flags & SSH2_FILEXFER_ATTR_SIZE)
-               buffer_put_int64(b, a->size);
+       int r;
+
+       if ((r = sshbuf_put_u32(b, a->flags)) != 0)
+               return r;
+       if (a->flags & SSH2_FILEXFER_ATTR_SIZE) {
+               if ((r = sshbuf_put_u64(b, a->size)) != 0)
+                       return r;
+       }
        if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
-               buffer_put_int(b, a->uid);
-               buffer_put_int(b, a->gid);
+               if ((r = sshbuf_put_u32(b, a->uid)) != 0 ||
+                   (r = sshbuf_put_u32(b, a->gid)) != 0)
+                       return r;
+       }
+       if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
+               if ((r = sshbuf_put_u32(b, a->perm)) != 0)
+                       return r;
        }
-       if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
-               buffer_put_int(b, a->perm);
        if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
-               buffer_put_int(b, a->atime);
-               buffer_put_int(b, a->mtime);
+               if ((r = sshbuf_put_u32(b, a->atime)) != 0 ||
+                   (r = sshbuf_put_u32(b, a->mtime)) != 0)
+                       return r;
        }
+       return 0;
 }
 
 /* Convert from SSH2_FX_ status to text error message */
index 9ed86c0..2e778a9 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp-common.h,v 1.11 2010/01/13 01:40:16 djm Exp $ */
+/* $OpenBSD: sftp-common.h,v 1.12 2015/01/14 13:54:13 djm Exp $ */
 
 /*
  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
@@ -28,6 +28,7 @@
 /* Maximum packet that we are willing to send/accept */
 #define SFTP_MAX_MSG_LENGTH    (256 * 1024)
 
+struct sshbuf;
 typedef struct Attrib Attrib;
 
 /* File attributes */
@@ -44,8 +45,8 @@ struct Attrib {
 void    attrib_clear(Attrib *);
 void    stat_to_attrib(const struct stat *, Attrib *);
 void    attrib_to_stat(const Attrib *, struct stat *);
-Attrib *decode_attrib(Buffer *);
-void    encode_attrib(Buffer *, const Attrib *);
+int     decode_attrib(struct sshbuf *, Attrib *);
+int     encode_attrib(struct sshbuf *, const Attrib *);
 char   *ls_file(const char *, const struct stat *, int, int);
 
 const char *fx2txt(int);
index 1c4d477..5e7e67a 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp-glob.c,v 1.26 2013/11/08 11:15:19 dtucker Exp $ */
+/* $OpenBSD: sftp-glob.c,v 1.27 2015/01/14 13:54:13 djm Exp $ */
 /*
  * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
  *
 #include <glob.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdlib.h>
 
 #include "xmalloc.h"
 #include "sftp.h"
-#include "buffer.h"
 #include "sftp-common.h"
 #include "sftp-client.h"
 
index 76694b3..08d19a9 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp-server.c,v 1.103 2014/01/17 06:23:24 dtucker Exp $ */
+/* $OpenBSD: sftp-server.c,v 1.104 2015/01/14 13:54:13 djm Exp $ */
 /*
  * Copyright (c) 2000-2004 Markus Friedl.  All rights reserved.
  *
@@ -34,7 +34,8 @@
 #include <stdarg.h>
 
 #include "xmalloc.h"
-#include "buffer.h"
+#include "sshbuf.h"
+#include "ssherr.h"
 #include "log.h"
 #include "misc.h"
 #include "match.h"
 #include "sftp.h"
 #include "sftp-common.h"
 
-/* helper */
-#define get_int64()                    buffer_get_int64(&iqueue);
-#define get_int()                      buffer_get_int(&iqueue);
-#define get_string(lenp)               buffer_get_string(&iqueue, lenp);
-
 /* Our verbosity */
 static LogLevel log_level = SYSLOG_LEVEL_ERROR;
 
@@ -56,8 +52,8 @@ static struct passwd *pw = NULL;
 static char *client_addr = NULL;
 
 /* input and output queue */
-static Buffer iqueue;
-static Buffer oqueue;
+struct sshbuf *iqueue;
+struct sshbuf *oqueue;
 
 /* Version of client */
 static u_int version;
@@ -263,12 +259,6 @@ string_from_portable(int pflags)
        return ret;
 }
 
-static Attrib *
-get_attrib(void)
-{
-       return decode_attrib(&iqueue);
-}
-
 /* handle handles */
 
 typedef struct Handle Handle;
@@ -332,7 +322,7 @@ handle_is_ok(int i, int type)
 }
 
 static int
-handle_to_string(int handle, char **stringp, int *hlenp)
+handle_to_string(int handle, u_char **stringp, int *hlenp)
 {
        if (stringp == NULL || hlenp == NULL)
                return -1;
@@ -343,7 +333,7 @@ handle_to_string(int handle, char **stringp, int *hlenp)
 }
 
 static int
-handle_from_string(const char *handle, u_int hlen)
+handle_from_string(const u_char *handle, u_int hlen)
 {
        int val;
 
@@ -465,29 +455,31 @@ handle_log_exit(void)
 }
 
 static int
-get_handle(void)
+get_handle(struct sshbuf *queue, int *hp)
 {
-       char *handle;
-       int val = -1;
-       u_int hlen;
+       u_char *handle;
+       int r;
+       size_t hlen;
 
-       handle = get_string(&hlen);
+       *hp = -1;
+       if ((r = sshbuf_get_string(queue, &handle, &hlen)) != 0)
+               return r;
        if (hlen < 256)
-               val = handle_from_string(handle, hlen);
+               *hp = handle_from_string(handle, hlen);
        free(handle);
-       return val;
+       return 0;
 }
 
 /* send replies */
 
 static void
-send_msg(Buffer *m)
+send_msg(struct sshbuf *m)
 {
-       int mlen = buffer_len(m);
+       int r;
 
-       buffer_put_int(&oqueue, mlen);
-       buffer_append(&oqueue, buffer_ptr(m), mlen);
-       buffer_consume(m, mlen);
+       if ((r = sshbuf_put_stringb(oqueue, m)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
+       sshbuf_reset(m);
 }
 
 static const char *
@@ -511,38 +503,46 @@ status_to_message(u_int32_t status)
 static void
 send_status(u_int32_t id, u_int32_t status)
 {
-       Buffer msg;
+       struct sshbuf *msg;
+       int r;
 
        debug3("request %u: sent status %u", id, status);
        if (log_level > SYSLOG_LEVEL_VERBOSE ||
            (status != SSH2_FX_OK && status != SSH2_FX_EOF))
                logit("sent status %s", status_to_message(status));
-       buffer_init(&msg);
-       buffer_put_char(&msg, SSH2_FXP_STATUS);
-       buffer_put_int(&msg, id);
-       buffer_put_int(&msg, status);
+       if ((msg = sshbuf_new()) == NULL)
+               fatal("%s: sshbuf_new failed", __func__);
+       if ((r = sshbuf_put_u8(msg, SSH2_FXP_STATUS)) != 0 ||
+           (r = sshbuf_put_u32(msg, id)) != 0 ||
+           (r = sshbuf_put_u32(msg, status)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
        if (version >= 3) {
-               buffer_put_cstring(&msg, status_to_message(status));
-               buffer_put_cstring(&msg, "");
+               if ((r = sshbuf_put_cstring(msg,
+                   status_to_message(status))) != 0 ||
+                   (r = sshbuf_put_cstring(msg, "")) != 0)
+                       fatal("%s: buffer error: %s", __func__, ssh_err(r));
        }
-       send_msg(&msg);
-       buffer_free(&msg);
+       send_msg(msg);
+       sshbuf_free(msg);
 }
 static void
-send_data_or_handle(char type, u_int32_t id, const char *data, int dlen)
+send_data_or_handle(char type, u_int32_t id, const u_char *data, int dlen)
 {
-       Buffer msg;
-
-       buffer_init(&msg);
-       buffer_put_char(&msg, type);
-       buffer_put_int(&msg, id);
-       buffer_put_string(&msg, data, dlen);
-       send_msg(&msg);
-       buffer_free(&msg);
+       struct sshbuf *msg;
+       int r;
+
+       if ((msg = sshbuf_new()) == NULL)
+               fatal("%s: sshbuf_new failed", __func__);
+       if ((r = sshbuf_put_u8(msg, type)) != 0 ||
+           (r = sshbuf_put_u32(msg, id)) != 0 ||
+           (r = sshbuf_put_string(msg, data, dlen)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
+       send_msg(msg);
+       sshbuf_free(msg);
 }
 
 static void
-send_data(u_int32_t id, const char *data, int dlen)
+send_data(u_int32_t id, const u_char *data, int dlen)
 {
        debug("request %u: sent data len %d", id, dlen);
        send_data_or_handle(SSH2_FXP_DATA, id, data, dlen);
@@ -551,7 +551,7 @@ send_data(u_int32_t id, const char *data, int dlen)
 static void
 send_handle(u_int32_t id, int handle)
 {
-       char *string;
+       u_char *string;
        int hlen;
 
        handle_to_string(handle, &string, &hlen);
@@ -563,62 +563,71 @@ send_handle(u_int32_t id, int handle)
 static void
 send_names(u_int32_t id, int count, const Stat *stats)
 {
-       Buffer msg;
-       int i;
-
-       buffer_init(&msg);
-       buffer_put_char(&msg, SSH2_FXP_NAME);
-       buffer_put_int(&msg, id);
-       buffer_put_int(&msg, count);
+       struct sshbuf *msg;
+       int i, r;
+
+       if ((msg = sshbuf_new()) == NULL)
+               fatal("%s: sshbuf_new failed", __func__);
+       if ((r = sshbuf_put_u8(msg, SSH2_FXP_NAME)) != 0 ||
+           (r = sshbuf_put_u32(msg, id)) != 0 ||
+           (r = sshbuf_put_u32(msg, count)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
        debug("request %u: sent names count %d", id, count);
        for (i = 0; i < count; i++) {
-               buffer_put_cstring(&msg, stats[i].name);
-               buffer_put_cstring(&msg, stats[i].long_name);
-               encode_attrib(&msg, &stats[i].attrib);
+               if ((r = sshbuf_put_cstring(msg, stats[i].name)) != 0 ||
+                   (r = sshbuf_put_cstring(msg, stats[i].long_name)) != 0 ||
+                   (r = encode_attrib(msg, &stats[i].attrib)) != 0)
+                       fatal("%s: buffer error: %s", __func__, ssh_err(r));
        }
-       send_msg(&msg);
-       buffer_free(&msg);
+       send_msg(msg);
+       sshbuf_free(msg);
 }
 
 static void
 send_attrib(u_int32_t id, const Attrib *a)
 {
-       Buffer msg;
+       struct sshbuf *msg;
+       int r;
 
        debug("request %u: sent attrib have 0x%x", id, a->flags);
-       buffer_init(&msg);
-       buffer_put_char(&msg, SSH2_FXP_ATTRS);
-       buffer_put_int(&msg, id);
-       encode_attrib(&msg, a);
-       send_msg(&msg);
-       buffer_free(&msg);
+       if ((msg = sshbuf_new()) == NULL)
+               fatal("%s: sshbuf_new failed", __func__);
+       if ((r = sshbuf_put_u8(msg, SSH2_FXP_ATTRS)) != 0 ||
+           (r = sshbuf_put_u32(msg, id)) != 0 ||
+           (r = encode_attrib(msg, a)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
+       send_msg(msg);
+       sshbuf_free(msg);
 }
 
 static void
 send_statvfs(u_int32_t id, struct statvfs *st)
 {
-       Buffer msg;
+       struct sshbuf *msg;
        u_int64_t flag;
+       int r;
 
        flag = (st->f_flag & ST_RDONLY) ? SSH2_FXE_STATVFS_ST_RDONLY : 0;
        flag |= (st->f_flag & ST_NOSUID) ? SSH2_FXE_STATVFS_ST_NOSUID : 0;
 
-       buffer_init(&msg);
-       buffer_put_char(&msg, SSH2_FXP_EXTENDED_REPLY);
-       buffer_put_int(&msg, id);
-       buffer_put_int64(&msg, st->f_bsize);
-       buffer_put_int64(&msg, st->f_frsize);
-       buffer_put_int64(&msg, st->f_blocks);
-       buffer_put_int64(&msg, st->f_bfree);
-       buffer_put_int64(&msg, st->f_bavail);
-       buffer_put_int64(&msg, st->f_files);
-       buffer_put_int64(&msg, st->f_ffree);
-       buffer_put_int64(&msg, st->f_favail);
-       buffer_put_int64(&msg, st->f_fsid);
-       buffer_put_int64(&msg, flag);
-       buffer_put_int64(&msg, st->f_namemax);
-       send_msg(&msg);
-       buffer_free(&msg);
+       if ((msg = sshbuf_new()) == NULL)
+               fatal("%s: sshbuf_new failed", __func__);
+       if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED_REPLY)) != 0 ||
+           (r = sshbuf_put_u32(msg, id)) != 0 ||
+           (r = sshbuf_put_u64(msg, st->f_bsize)) != 0 ||
+           (r = sshbuf_put_u64(msg, st->f_frsize)) != 0 ||
+           (r = sshbuf_put_u64(msg, st->f_blocks)) != 0 ||
+           (r = sshbuf_put_u64(msg, st->f_bfree)) != 0 ||
+           (r = sshbuf_put_u64(msg, st->f_bavail)) != 0 ||
+           (r = sshbuf_put_u64(msg, st->f_files)) != 0 ||
+           (r = sshbuf_put_u64(msg, st->f_ffree)) != 0 ||
+           (r = sshbuf_put_u64(msg, st->f_favail)) != 0 ||
+           (r = sshbuf_put_u64(msg, st->f_fsid)) != 0 ||
+           (r = sshbuf_put_u64(msg, flag)) != 0 ||
+           (r = sshbuf_put_u64(msg, st->f_namemax)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
+       send_msg(msg);
+       sshbuf_free(msg);
 }
 
 /* parse incoming */
@@ -626,53 +635,59 @@ send_statvfs(u_int32_t id, struct statvfs *st)
 static void
 process_init(void)
 {
-       Buffer msg;
+       struct sshbuf *msg;
+       int r;
 
-       version = get_int();
+       if ((r = sshbuf_get_u32(iqueue, &version)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
        verbose("received client version %u", version);
-       buffer_init(&msg);
-       buffer_put_char(&msg, SSH2_FXP_VERSION);
-       buffer_put_int(&msg, SSH2_FILEXFER_VERSION);
-       /* POSIX rename extension */
-       buffer_put_cstring(&msg, "posix-rename@openssh.com");
-       buffer_put_cstring(&msg, "1"); /* version */
-       /* statvfs extension */
-       buffer_put_cstring(&msg, "statvfs@openssh.com");
-       buffer_put_cstring(&msg, "2"); /* version */
-       /* fstatvfs extension */
-       buffer_put_cstring(&msg, "fstatvfs@openssh.com");
-       buffer_put_cstring(&msg, "2"); /* version */
-       /* hardlink extension */
-       buffer_put_cstring(&msg, "hardlink@openssh.com");
-       buffer_put_cstring(&msg, "1"); /* version */
-       /* fsync extension */
-       buffer_put_cstring(&msg, "fsync@openssh.com");
-       buffer_put_cstring(&msg, "1"); /* version */
-       send_msg(&msg);
-       buffer_free(&msg);
+       if ((msg = sshbuf_new()) == NULL)
+               fatal("%s: sshbuf_new failed", __func__);
+       if ((r = sshbuf_put_u8(msg, SSH2_FXP_VERSION)) != 0 ||
+           (r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0 ||
+           /* POSIX rename extension */
+           (r = sshbuf_put_cstring(msg, "posix-rename@openssh.com")) != 0 ||
+           (r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */
+           /* statvfs extension */
+           (r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 ||
+           (r = sshbuf_put_cstring(msg, "2")) != 0 || /* version */
+           /* fstatvfs extension */
+           (r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 ||
+           (r = sshbuf_put_cstring(msg, "2")) != 0 || /* version */
+           /* hardlink extension */
+           (r = sshbuf_put_cstring(msg, "hardlink@openssh.com")) != 0 ||
+           (r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */
+           /* fsync extension */
+           (r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 ||
+           (r = sshbuf_put_cstring(msg, "1")) != 0) /* version */
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
+       send_msg(msg);
+       sshbuf_free(msg);
 }
 
 static void
 process_open(u_int32_t id)
 {
        u_int32_t pflags;
-       Attrib *a;
+       Attrib a;
        char *name;
-       int handle, fd, flags, mode, status = SSH2_FX_FAILURE;
+       int r, handle, fd, flags, mode, status = SSH2_FX_FAILURE;
+
+       if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
+           (r = sshbuf_get_u32(iqueue, &pflags)) != 0 || /* portable flags */
+           (r = decode_attrib(iqueue, &a)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
-       name = get_string(NULL);
-       pflags = get_int();             /* portable flags */
        debug3("request %u: open flags %d", id, pflags);
-       a = get_attrib();
        flags = flags_from_portable(pflags);
-       mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666;
+       mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a.perm : 0666;
        logit("open \"%s\" flags %s mode 0%o",
            name, string_from_portable(pflags), mode);
        if (readonly &&
            ((flags & O_ACCMODE) == O_WRONLY ||
            (flags & O_ACCMODE) == O_RDWR)) {
                verbose("Refusing open request in read-only mode");
-               status = SSH2_FX_PERMISSION_DENIED;
+               status = SSH2_FX_PERMISSION_DENIED;
        } else {
                fd = open(name, flags, mode);
                if (fd < 0) {
@@ -695,9 +710,11 @@ process_open(u_int32_t id)
 static void
 process_close(u_int32_t id)
 {
-       int handle, ret, status = SSH2_FX_FAILURE;
+       int r, handle, ret, status = SSH2_FX_FAILURE;
+
+       if ((r = get_handle(iqueue, &handle)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
-       handle = get_handle();
        debug3("request %u: close handle %u", id, handle);
        handle_log_close(handle, NULL);
        ret = handle_close(handle);
@@ -708,14 +725,15 @@ process_close(u_int32_t id)
 static void
 process_read(u_int32_t id)
 {
-       char buf[64*1024];
+       u_char buf[64*1024];
        u_int32_t len;
-       int handle, fd, ret, status = SSH2_FX_FAILURE;
+       int r, handle, fd, ret, status = SSH2_FX_FAILURE;
        u_int64_t off;
 
-       handle = get_handle();
-       off = get_int64();
-       len = get_int();
+       if ((r = get_handle(iqueue, &handle)) != 0 ||
+           (r = sshbuf_get_u64(iqueue, &off)) != 0 ||
+           (r = sshbuf_get_u32(iqueue, &len)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
        debug("request %u: read \"%s\" (handle %d) off %llu len %d",
            id, handle_to_name(handle), handle, (unsigned long long)off, len);
@@ -749,18 +767,19 @@ static void
 process_write(u_int32_t id)
 {
        u_int64_t off;
-       u_int len;
-       int handle, fd, ret, status;
-       char *data;
+       size_t len;
+       int r, handle, fd, ret, status;
+       u_char *data;
 
-       handle = get_handle();
-       off = get_int64();
-       data = get_string(&len);
+       if ((r = get_handle(iqueue, &handle)) != 0 ||
+           (r = sshbuf_get_u64(iqueue, &off)) != 0 ||
+           (r = sshbuf_get_string(iqueue, &data, &len)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
-       debug("request %u: write \"%s\" (handle %d) off %llu len %d",
+       debug("request %u: write \"%s\" (handle %d) off %llu len %zu",
            id, handle_to_name(handle), handle, (unsigned long long)off, len);
        fd = handle_to_fd(handle);
-       
+
        if (fd < 0)
                status = SSH2_FX_FAILURE;
        else {
@@ -793,13 +812,15 @@ process_do_stat(u_int32_t id, int do_lstat)
        Attrib a;
        struct stat st;
        char *name;
-       int ret, status = SSH2_FX_FAILURE;
+       int r, status = SSH2_FX_FAILURE;
+
+       if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
-       name = get_string(NULL);
        debug3("request %u: %sstat", id, do_lstat ? "l" : "");
        verbose("%sstat name \"%s\"", do_lstat ? "l" : "", name);
-       ret = do_lstat ? lstat(name, &st) : stat(name, &st);
-       if (ret < 0) {
+       r = do_lstat ? lstat(name, &st) : stat(name, &st);
+       if (r < 0) {
                status = errno_to_portable(errno);
        } else {
                stat_to_attrib(&st, &a);
@@ -828,15 +849,16 @@ process_fstat(u_int32_t id)
 {
        Attrib a;
        struct stat st;
-       int fd, ret, handle, status = SSH2_FX_FAILURE;
+       int fd, r, handle, status = SSH2_FX_FAILURE;
 
-       handle = get_handle();
+       if ((r = get_handle(iqueue, &handle)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
        debug("request %u: fstat \"%s\" (handle %u)",
            id, handle_to_name(handle), handle);
        fd = handle_to_fd(handle);
        if (fd >= 0) {
-               ret = fstat(fd, &st);
-               if (ret < 0) {
+               r = fstat(fd, &st);
+               if (r < 0) {
                        status = errno_to_portable(errno);
                } else {
                        stat_to_attrib(&st, &a);
@@ -863,42 +885,44 @@ attrib_to_tv(const Attrib *a)
 static void
 process_setstat(u_int32_t id)
 {
-       Attrib *a;
+       Attrib a;
        char *name;
-       int status = SSH2_FX_OK, ret;
+       int r, status = SSH2_FX_OK;
+
+       if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
+           (r = decode_attrib(iqueue, &a)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
-       name = get_string(NULL);
-       a = get_attrib();
        debug("request %u: setstat name \"%s\"", id, name);
-       if (a->flags & SSH2_FILEXFER_ATTR_SIZE) {
+       if (a.flags & SSH2_FILEXFER_ATTR_SIZE) {
                logit("set \"%s\" size %llu",
-                   name, (unsigned long long)a->size);
-               ret = truncate(name, a->size);
-               if (ret == -1)
+                   name, (unsigned long long)a.size);
+               r = truncate(name, a.size);
+               if (r == -1)
                        status = errno_to_portable(errno);
        }
-       if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
-               logit("set \"%s\" mode %04o", name, a->perm);
-               ret = chmod(name, a->perm & 07777);
-               if (ret == -1)
+       if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
+               logit("set \"%s\" mode %04o", name, a.perm);
+               r = chmod(name, a.perm & 07777);
+               if (r == -1)
                        status = errno_to_portable(errno);
        }
-       if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
+       if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
                char buf[64];
-               time_t t = a->mtime;
+               time_t t = a.mtime;
 
                strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S",
                    localtime(&t));
                logit("set \"%s\" modtime %s", name, buf);
-               ret = utimes(name, attrib_to_tv(a));
-               if (ret == -1)
+               r = utimes(name, attrib_to_tv(&a));
+               if (r == -1)
                        status = errno_to_portable(errno);
        }
-       if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
+       if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) {
                logit("set \"%s\" owner %lu group %lu", name,
-                   (u_long)a->uid, (u_long)a->gid);
-               ret = chown(name, a->uid, a->gid);
-               if (ret == -1)
+                   (u_long)a.uid, (u_long)a.gid);
+               r = chown(name, a.uid, a.gid);
+               if (r == -1)
                        status = errno_to_portable(errno);
        }
        send_status(id, status);
@@ -908,12 +932,14 @@ process_setstat(u_int32_t id)
 static void
 process_fsetstat(u_int32_t id)
 {
-       Attrib *a;
-       int handle, fd, ret;
+       Attrib a;
+       int handle, fd, r;
        int status = SSH2_FX_OK;
 
-       handle = get_handle();
-       a = get_attrib();
+       if ((r = get_handle(iqueue, &handle)) != 0 ||
+           (r = decode_attrib(iqueue, &a)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
+
        debug("request %u: fsetstat handle %d", id, handle);
        fd = handle_to_fd(handle);
        if (fd < 0)
@@ -921,35 +947,35 @@ process_fsetstat(u_int32_t id)
        else {
                char *name = handle_to_name(handle);
 
-               if (a->flags & SSH2_FILEXFER_ATTR_SIZE) {
+               if (a.flags & SSH2_FILEXFER_ATTR_SIZE) {
                        logit("set \"%s\" size %llu",
-                           name, (unsigned long long)a->size);
-                       ret = ftruncate(fd, a->size);
-                       if (ret == -1)
+                           name, (unsigned long long)a.size);
+                       r = ftruncate(fd, a.size);
+                       if (r == -1)
                                status = errno_to_portable(errno);
                }
-               if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
-                       logit("set \"%s\" mode %04o", name, a->perm);
-                       ret = fchmod(fd, a->perm & 07777);
-                       if (ret == -1)
+               if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
+                       logit("set \"%s\" mode %04o", name, a.perm);
+                       r = fchmod(fd, a.perm & 07777);
+                       if (r == -1)
                                status = errno_to_portable(errno);
                }
-               if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
+               if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
                        char buf[64];
-                       time_t t = a->mtime;
+                       time_t t = a.mtime;
 
                        strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S",
                            localtime(&t));
                        logit("set \"%s\" modtime %s", name, buf);
-                       ret = futimes(fd, attrib_to_tv(a));
-                       if (ret == -1)
+                       r = futimes(fd, attrib_to_tv(&a));
+                       if (r == -1)
                                status = errno_to_portable(errno);
                }
-               if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
+               if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) {
                        logit("set \"%s\" owner %lu group %lu", name,
-                           (u_long)a->uid, (u_long)a->gid);
-                       ret = fchown(fd, a->uid, a->gid);
-                       if (ret == -1)
+                           (u_long)a.uid, (u_long)a.gid);
+                       r = fchown(fd, a.uid, a.gid);
+                       if (r == -1)
                                status = errno_to_portable(errno);
                }
        }
@@ -961,9 +987,11 @@ process_opendir(u_int32_t id)
 {
        DIR *dirp = NULL;
        char *path;
-       int handle, status = SSH2_FX_FAILURE;
+       int r, handle, status = SSH2_FX_FAILURE;
+
+       if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
-       path = get_string(NULL);
        debug3("request %u: opendir", id);
        logit("opendir \"%s\"", path);
        dirp = opendir(path);
@@ -990,9 +1018,11 @@ process_readdir(u_int32_t id)
        DIR *dirp;
        struct dirent *dp;
        char *path;
-       int handle;
+       int r, handle;
+
+       if ((r = get_handle(iqueue, &handle)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
-       handle = get_handle();
        debug("request %u: readdir \"%s\" (handle %d)", id,
            handle_to_name(handle), handle);
        dirp = handle_to_dir(handle);
@@ -1042,14 +1072,15 @@ static void
 process_remove(u_int32_t id)
 {
        char *name;
-       int status = SSH2_FX_FAILURE;
-       int ret;
+       int r, status = SSH2_FX_FAILURE;
+
+       if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
-       name = get_string(NULL);
        debug3("request %u: remove", id);
        logit("remove name \"%s\"", name);
-       ret = unlink(name);
-       status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
+       r = unlink(name);
+       status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
        send_status(id, status);
        free(name);
 }
@@ -1057,18 +1088,20 @@ process_remove(u_int32_t id)
 static void
 process_mkdir(u_int32_t id)
 {
-       Attrib *a;
+       Attrib a;
        char *name;
-       int ret, mode, status = SSH2_FX_FAILURE;
+       int r, mode, status = SSH2_FX_FAILURE;
+
+       if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
+           (r = decode_attrib(iqueue, &a)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
-       name = get_string(NULL);
-       a = get_attrib();
-       mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ?
-           a->perm & 07777 : 0777;
+       mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ?
+           a.perm & 07777 : 0777;
        debug3("request %u: mkdir", id);
        logit("mkdir name \"%s\" mode 0%o", name, mode);
-       ret = mkdir(name, mode);
-       status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
+       r = mkdir(name, mode);
+       status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
        send_status(id, status);
        free(name);
 }
@@ -1077,13 +1110,15 @@ static void
 process_rmdir(u_int32_t id)
 {
        char *name;
-       int ret, status;
+       int r, status;
+
+       if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
-       name = get_string(NULL);
        debug3("request %u: rmdir", id);
        logit("rmdir name \"%s\"", name);
-       ret = rmdir(name);
-       status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
+       r = rmdir(name);
+       status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
        send_status(id, status);
        free(name);
 }
@@ -1093,8 +1128,11 @@ process_realpath(u_int32_t id)
 {
        char resolvedname[MAXPATHLEN];
        char *path;
+       int r;
+
+       if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
-       path = get_string(NULL);
        if (path[0] == '\0') {
                free(path);
                path = xstrdup(".");
@@ -1116,11 +1154,13 @@ static void
 process_rename(u_int32_t id)
 {
        char *oldpath, *newpath;
-       int status;
+       int r, status;
        struct stat sb;
 
-       oldpath = get_string(NULL);
-       newpath = get_string(NULL);
+       if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
+           (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
+
        debug3("request %u: rename", id);
        logit("rename old \"%s\" new \"%s\"", oldpath, newpath);
        status = SSH2_FX_FAILURE;
@@ -1166,11 +1206,13 @@ process_rename(u_int32_t id)
 static void
 process_readlink(u_int32_t id)
 {
-       int len;
+       int r, len;
        char buf[MAXPATHLEN];
        char *path;
 
-       path = get_string(NULL);
+       if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
+
        debug3("request %u: readlink", id);
        verbose("readlink \"%s\"", path);
        if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1)
@@ -1190,15 +1232,17 @@ static void
 process_symlink(u_int32_t id)
 {
        char *oldpath, *newpath;
-       int ret, status;
+       int r, status;
+
+       if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
+           (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
-       oldpath = get_string(NULL);
-       newpath = get_string(NULL);
        debug3("request %u: symlink", id);
        logit("symlink old \"%s\" new \"%s\"", oldpath, newpath);
        /* this will fail if 'newpath' exists */
-       ret = symlink(oldpath, newpath);
-       status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
+       r = symlink(oldpath, newpath);
+       status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
        send_status(id, status);
        free(oldpath);
        free(newpath);
@@ -1208,14 +1252,16 @@ static void
 process_extended_posix_rename(u_int32_t id)
 {
        char *oldpath, *newpath;
-       int ret, status;
+       int r, status;
+
+       if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
+           (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
-       oldpath = get_string(NULL);
-       newpath = get_string(NULL);
        debug3("request %u: posix-rename", id);
        logit("posix-rename old \"%s\" new \"%s\"", oldpath, newpath);
-       ret = rename(oldpath, newpath);
-       status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
+       r = rename(oldpath, newpath);
+       status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
        send_status(id, status);
        free(oldpath);
        free(newpath);
@@ -1226,8 +1272,10 @@ process_extended_statvfs(u_int32_t id)
 {
        char *path;
        struct statvfs st;
+       int r;
 
-       path = get_string(NULL);
+       if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
        debug3("request %u: statvfs", id);
        logit("statvfs \"%s\"", path);
 
@@ -1241,10 +1289,11 @@ process_extended_statvfs(u_int32_t id)
 static void
 process_extended_fstatvfs(u_int32_t id)
 {
-       int handle, fd;
+       int r, handle, fd;
        struct statvfs st;
 
-       handle = get_handle();
+       if ((r = get_handle(iqueue, &handle)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
        debug("request %u: fstatvfs \"%s\" (handle %u)",
            id, handle_to_name(handle), handle);
        if ((fd = handle_to_fd(handle)) < 0) {
@@ -1261,14 +1310,16 @@ static void
 process_extended_hardlink(u_int32_t id)
 {
        char *oldpath, *newpath;
-       int ret, status;
+       int r, status;
+
+       if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
+           (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
-       oldpath = get_string(NULL);
-       newpath = get_string(NULL);
        debug3("request %u: hardlink", id);
        logit("hardlink old \"%s\" new \"%s\"", oldpath, newpath);
-       ret = link(oldpath, newpath);
-       status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
+       r = link(oldpath, newpath);
+       status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
        send_status(id, status);
        free(oldpath);
        free(newpath);
@@ -1277,16 +1328,17 @@ process_extended_hardlink(u_int32_t id)
 static void
 process_extended_fsync(u_int32_t id)
 {
-       int handle, fd, ret, status = SSH2_FX_OP_UNSUPPORTED;
+       int handle, fd, r, status = SSH2_FX_OP_UNSUPPORTED;
 
-       handle = get_handle();
+       if ((r = get_handle(iqueue, &handle)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
        debug3("request %u: fsync (handle %u)", id, handle);
        verbose("fsync \"%s\"", handle_to_name(handle));
        if ((fd = handle_to_fd(handle)) < 0)
                status = SSH2_FX_NO_SUCH_FILE;
        else if (handle_is_ok(handle, HANDLE_FILE)) {
-               ret = fsync(fd);
-               status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
+               r = fsync(fd);
+               status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
        }
        send_status(id, status);
 }
@@ -1295,9 +1347,10 @@ static void
 process_extended(u_int32_t id)
 {
        char *request;
-       u_int i;
+       int i, r;
 
-       request = get_string(NULL);
+       if ((r = sshbuf_get_cstring(iqueue, &request, NULL)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
        for (i = 0; extended_handlers[i].handler != NULL; i++) {
                if (strcmp(request, extended_handlers[i].ext_name) == 0) {
                        if (!request_permitted(&extended_handlers[i]))
@@ -1319,14 +1372,18 @@ process_extended(u_int32_t id)
 static void
 process(void)
 {
-       u_int msg_len, buf_len, consumed, type, i;
-       u_char *cp;
+       u_int msg_len;
+       u_int buf_len;
+       u_int consumed;
+       u_char type;
+       const u_char *cp;
+       int i, r;
        u_int32_t id;
 
-       buf_len = buffer_len(&iqueue);
+       buf_len = sshbuf_len(iqueue);
        if (buf_len < 5)
                return;         /* Incomplete message. */
-       cp = buffer_ptr(&iqueue);
+       cp = sshbuf_ptr(iqueue);
        msg_len = get_u32(cp);
        if (msg_len > SFTP_MAX_MSG_LENGTH) {
                error("bad message from %s local user %s",
@@ -1335,9 +1392,11 @@ process(void)
        }
        if (buf_len < msg_len + 4)
                return;
-       buffer_consume(&iqueue, 4);
+       if ((r = sshbuf_consume(iqueue, 4)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
        buf_len -= 4;
-       type = buffer_get_char(&iqueue);
+       if ((r = sshbuf_get_u8(iqueue, &type)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
        switch (type) {
        case SSH2_FXP_INIT:
@@ -1347,13 +1406,15 @@ process(void)
        case SSH2_FXP_EXTENDED:
                if (!init_done)
                        fatal("Received extended request before init");
-               id = get_int();
+               if ((r = sshbuf_get_u32(iqueue, &id)) != 0)
+                       fatal("%s: buffer error: %s", __func__, ssh_err(r));
                process_extended(id);
                break;
        default:
                if (!init_done)
                        fatal("Received %u request before init", type);
-               id = get_int();
+               if ((r = sshbuf_get_u32(iqueue, &id)) != 0)
+                       fatal("%s: buffer error: %s", __func__, ssh_err(r));
                for (i = 0; handlers[i].handler != NULL; i++) {
                        if (type == handlers[i].type) {
                                if (!request_permitted(&handlers[i])) {
@@ -1369,17 +1430,18 @@ process(void)
                        error("Unknown message %u", type);
        }
        /* discard the remaining bytes from the current packet */
-       if (buf_len < buffer_len(&iqueue)) {
+       if (buf_len < sshbuf_len(iqueue)) {
                error("iqueue grew unexpectedly");
                sftp_server_cleanup_exit(255);
        }
-       consumed = buf_len - buffer_len(&iqueue);
+       consumed = buf_len - sshbuf_len(iqueue);
        if (msg_len < consumed) {
                error("msg_len %u < consumed %u", msg_len, consumed);
                sftp_server_cleanup_exit(255);
        }
-       if (msg_len > consumed)
-               buffer_consume(&iqueue, msg_len - consumed);
+       if (msg_len > consumed &&
+           (r = sshbuf_consume(iqueue, msg_len - consumed)) != 0)
+               fatal("%s: buffer error: %s", __func__, ssh_err(r));
 }
 
 /* Cleanup handler that logs active handles upon normal exit */
@@ -1412,7 +1474,7 @@ int
 sftp_server_main(int argc, char **argv, struct passwd *user_pw)
 {
        fd_set *rset, *wset;
-       int i, in, out, max, ch, skipargs = 0, log_stderr = 0;
+       int i, r, in, out, max, ch, skipargs = 0, log_stderr = 0;
        ssize_t len, olen, set_size;
        SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
        char *cp, *homedir = NULL, buf[4*4096];
@@ -1517,8 +1579,10 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
        if (out > max)
                max = out;
 
-       buffer_init(&iqueue);
-       buffer_init(&oqueue);
+       if ((iqueue = sshbuf_new()) == NULL)
+               fatal("%s: sshbuf_new failed", __func__);
+       if ((oqueue = sshbuf_new()) == NULL)
+               fatal("%s: sshbuf_new failed", __func__);
 
        set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask);
        rset = (fd_set *)xmalloc(set_size);
@@ -1540,11 +1604,15 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
                 * the worst-case length packet it can generate,
                 * otherwise apply backpressure by stopping reads.
                 */
-               if (buffer_check_alloc(&iqueue, sizeof(buf)) &&
-                   buffer_check_alloc(&oqueue, SFTP_MAX_MSG_LENGTH))
+               if ((r = sshbuf_check_reserve(iqueue, sizeof(buf))) == 0 &&
+                   (r = sshbuf_check_reserve(oqueue,
+                   SFTP_MAX_MSG_LENGTH)) == 0)
                        FD_SET(in, rset);
+               else if (r != SSH_ERR_NO_BUFFER_SPACE)
+                       fatal("%s: sshbuf_check_reserve failed: %s",
+                           __func__, ssh_err(r));
 
-               olen = buffer_len(&oqueue);
+               olen = sshbuf_len(oqueue);
                if (olen > 0)
                        FD_SET(out, wset);
 
@@ -1564,18 +1632,20 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
                        } else if (len < 0) {
                                error("read: %s", strerror(errno));
                                sftp_server_cleanup_exit(1);
-                       } else {
-                               buffer_append(&iqueue, buf, len);
+                       } else if ((r = sshbuf_put(iqueue, buf, len)) != 0) {
+                               fatal("%s: buffer error: %s",
+                                   __func__, ssh_err(r));
                        }
                }
                /* send oqueue to stdout */
                if (FD_ISSET(out, wset)) {
-                       len = write(out, buffer_ptr(&oqueue), olen);
+                       len = write(out, sshbuf_ptr(oqueue), olen);
                        if (len < 0) {
                                error("write: %s", strerror(errno));
                                sftp_server_cleanup_exit(1);
-                       } else {
-                               buffer_consume(&oqueue, len);
+                       } else if ((r = sshbuf_consume(oqueue, len)) != 0) {
+                               fatal("%s: buffer error: %s",
+                                   __func__, ssh_err(r));
                        }
                }
 
@@ -1584,7 +1654,11 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
                 * into the output buffer, otherwise stop processing input
                 * and let the output queue drain.
                 */
-               if (buffer_check_alloc(&oqueue, SFTP_MAX_MSG_LENGTH))
+               r = sshbuf_check_reserve(oqueue, SFTP_MAX_MSG_LENGTH);
+               if (r == 0)
                        process();
+               else if (r != SSH_ERR_NO_BUFFER_SPACE)
+                       fatal("%s: sshbuf_check_reserve: %s",
+                           __func__, ssh_err(r));
        }
 }
index 12d30d6..e378f18 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp.c,v 1.168 2014/11/26 18:34:51 millert Exp $ */
+/* $OpenBSD: sftp.c,v 1.169 2015/01/14 13:54:13 djm Exp $ */
 /*
  * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
  *
@@ -44,7 +44,8 @@
 #include "misc.h"
 
 #include "sftp.h"
-#include "buffer.h"
+#include "ssherr.h"
+#include "sshbuf.h"
 #include "sftp-common.h"
 #include "sftp-client.h"