summaryrefslogtreecommitdiff
path: root/sftp-server.c
diff options
context:
space:
mode:
Diffstat (limited to 'sftp-server.c')
-rw-r--r--sftp-server.c592
1 files changed, 333 insertions, 259 deletions
diff --git a/sftp-server.c b/sftp-server.c
index 0177130cf..4f735cd93 100644
--- a/sftp-server.c
+++ b/sftp-server.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sftp-server.c,v 1.103 2014/01/17 06:23:24 dtucker Exp $ */ 1/* $OpenBSD: sftp-server.c,v 1.105 2015/01/20 23:14:00 deraadt Exp $ */
2/* 2/*
3 * Copyright (c) 2000-2004 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000-2004 Markus Friedl. All rights reserved.
4 * 4 *
@@ -17,8 +17,8 @@
17 17
18#include "includes.h" 18#include "includes.h"
19 19
20#include <sys/param.h> /* MIN */
20#include <sys/types.h> 21#include <sys/types.h>
21#include <sys/param.h>
22#include <sys/stat.h> 22#include <sys/stat.h>
23#ifdef HAVE_SYS_TIME_H 23#ifdef HAVE_SYS_TIME_H
24# include <sys/time.h> 24# include <sys/time.h>
@@ -46,7 +46,8 @@
46#include <stdarg.h> 46#include <stdarg.h>
47 47
48#include "xmalloc.h" 48#include "xmalloc.h"
49#include "buffer.h" 49#include "sshbuf.h"
50#include "ssherr.h"
50#include "log.h" 51#include "log.h"
51#include "misc.h" 52#include "misc.h"
52#include "match.h" 53#include "match.h"
@@ -55,11 +56,6 @@
55#include "sftp.h" 56#include "sftp.h"
56#include "sftp-common.h" 57#include "sftp-common.h"
57 58
58/* helper */
59#define get_int64() buffer_get_int64(&iqueue);
60#define get_int() buffer_get_int(&iqueue);
61#define get_string(lenp) buffer_get_string(&iqueue, lenp);
62
63/* Our verbosity */ 59/* Our verbosity */
64static LogLevel log_level = SYSLOG_LEVEL_ERROR; 60static LogLevel log_level = SYSLOG_LEVEL_ERROR;
65 61
@@ -68,8 +64,8 @@ static struct passwd *pw = NULL;
68static char *client_addr = NULL; 64static char *client_addr = NULL;
69 65
70/* input and output queue */ 66/* input and output queue */
71static Buffer iqueue; 67struct sshbuf *iqueue;
72static Buffer oqueue; 68struct sshbuf *oqueue;
73 69
74/* Version of client */ 70/* Version of client */
75static u_int version; 71static u_int version;
@@ -275,12 +271,6 @@ string_from_portable(int pflags)
275 return ret; 271 return ret;
276} 272}
277 273
278static Attrib *
279get_attrib(void)
280{
281 return decode_attrib(&iqueue);
282}
283
284/* handle handles */ 274/* handle handles */
285 275
286typedef struct Handle Handle; 276typedef struct Handle Handle;
@@ -344,7 +334,7 @@ handle_is_ok(int i, int type)
344} 334}
345 335
346static int 336static int
347handle_to_string(int handle, char **stringp, int *hlenp) 337handle_to_string(int handle, u_char **stringp, int *hlenp)
348{ 338{
349 if (stringp == NULL || hlenp == NULL) 339 if (stringp == NULL || hlenp == NULL)
350 return -1; 340 return -1;
@@ -355,7 +345,7 @@ handle_to_string(int handle, char **stringp, int *hlenp)
355} 345}
356 346
357static int 347static int
358handle_from_string(const char *handle, u_int hlen) 348handle_from_string(const u_char *handle, u_int hlen)
359{ 349{
360 int val; 350 int val;
361 351
@@ -477,29 +467,31 @@ handle_log_exit(void)
477} 467}
478 468
479static int 469static int
480get_handle(void) 470get_handle(struct sshbuf *queue, int *hp)
481{ 471{
482 char *handle; 472 u_char *handle;
483 int val = -1; 473 int r;
484 u_int hlen; 474 size_t hlen;
485 475
486 handle = get_string(&hlen); 476 *hp = -1;
477 if ((r = sshbuf_get_string(queue, &handle, &hlen)) != 0)
478 return r;
487 if (hlen < 256) 479 if (hlen < 256)
488 val = handle_from_string(handle, hlen); 480 *hp = handle_from_string(handle, hlen);
489 free(handle); 481 free(handle);
490 return val; 482 return 0;
491} 483}
492 484
493/* send replies */ 485/* send replies */
494 486
495static void 487static void
496send_msg(Buffer *m) 488send_msg(struct sshbuf *m)
497{ 489{
498 int mlen = buffer_len(m); 490 int r;
499 491
500 buffer_put_int(&oqueue, mlen); 492 if ((r = sshbuf_put_stringb(oqueue, m)) != 0)
501 buffer_append(&oqueue, buffer_ptr(m), mlen); 493 fatal("%s: buffer error: %s", __func__, ssh_err(r));
502 buffer_consume(m, mlen); 494 sshbuf_reset(m);
503} 495}
504 496
505static const char * 497static const char *
@@ -523,38 +515,46 @@ status_to_message(u_int32_t status)
523static void 515static void
524send_status(u_int32_t id, u_int32_t status) 516send_status(u_int32_t id, u_int32_t status)
525{ 517{
526 Buffer msg; 518 struct sshbuf *msg;
519 int r;
527 520
528 debug3("request %u: sent status %u", id, status); 521 debug3("request %u: sent status %u", id, status);
529 if (log_level > SYSLOG_LEVEL_VERBOSE || 522 if (log_level > SYSLOG_LEVEL_VERBOSE ||
530 (status != SSH2_FX_OK && status != SSH2_FX_EOF)) 523 (status != SSH2_FX_OK && status != SSH2_FX_EOF))
531 logit("sent status %s", status_to_message(status)); 524 logit("sent status %s", status_to_message(status));
532 buffer_init(&msg); 525 if ((msg = sshbuf_new()) == NULL)
533 buffer_put_char(&msg, SSH2_FXP_STATUS); 526 fatal("%s: sshbuf_new failed", __func__);
534 buffer_put_int(&msg, id); 527 if ((r = sshbuf_put_u8(msg, SSH2_FXP_STATUS)) != 0 ||
535 buffer_put_int(&msg, status); 528 (r = sshbuf_put_u32(msg, id)) != 0 ||
529 (r = sshbuf_put_u32(msg, status)) != 0)
530 fatal("%s: buffer error: %s", __func__, ssh_err(r));
536 if (version >= 3) { 531 if (version >= 3) {
537 buffer_put_cstring(&msg, status_to_message(status)); 532 if ((r = sshbuf_put_cstring(msg,
538 buffer_put_cstring(&msg, ""); 533 status_to_message(status))) != 0 ||
534 (r = sshbuf_put_cstring(msg, "")) != 0)
535 fatal("%s: buffer error: %s", __func__, ssh_err(r));
539 } 536 }
540 send_msg(&msg); 537 send_msg(msg);
541 buffer_free(&msg); 538 sshbuf_free(msg);
542} 539}
543static void 540static void
544send_data_or_handle(char type, u_int32_t id, const char *data, int dlen) 541send_data_or_handle(char type, u_int32_t id, const u_char *data, int dlen)
545{ 542{
546 Buffer msg; 543 struct sshbuf *msg;
547 544 int r;
548 buffer_init(&msg); 545
549 buffer_put_char(&msg, type); 546 if ((msg = sshbuf_new()) == NULL)
550 buffer_put_int(&msg, id); 547 fatal("%s: sshbuf_new failed", __func__);
551 buffer_put_string(&msg, data, dlen); 548 if ((r = sshbuf_put_u8(msg, type)) != 0 ||
552 send_msg(&msg); 549 (r = sshbuf_put_u32(msg, id)) != 0 ||
553 buffer_free(&msg); 550 (r = sshbuf_put_string(msg, data, dlen)) != 0)
551 fatal("%s: buffer error: %s", __func__, ssh_err(r));
552 send_msg(msg);
553 sshbuf_free(msg);
554} 554}
555 555
556static void 556static void
557send_data(u_int32_t id, const char *data, int dlen) 557send_data(u_int32_t id, const u_char *data, int dlen)
558{ 558{
559 debug("request %u: sent data len %d", id, dlen); 559 debug("request %u: sent data len %d", id, dlen);
560 send_data_or_handle(SSH2_FXP_DATA, id, data, dlen); 560 send_data_or_handle(SSH2_FXP_DATA, id, data, dlen);
@@ -563,7 +563,7 @@ send_data(u_int32_t id, const char *data, int dlen)
563static void 563static void
564send_handle(u_int32_t id, int handle) 564send_handle(u_int32_t id, int handle)
565{ 565{
566 char *string; 566 u_char *string;
567 int hlen; 567 int hlen;
568 568
569 handle_to_string(handle, &string, &hlen); 569 handle_to_string(handle, &string, &hlen);
@@ -575,62 +575,71 @@ send_handle(u_int32_t id, int handle)
575static void 575static void
576send_names(u_int32_t id, int count, const Stat *stats) 576send_names(u_int32_t id, int count, const Stat *stats)
577{ 577{
578 Buffer msg; 578 struct sshbuf *msg;
579 int i; 579 int i, r;
580 580
581 buffer_init(&msg); 581 if ((msg = sshbuf_new()) == NULL)
582 buffer_put_char(&msg, SSH2_FXP_NAME); 582 fatal("%s: sshbuf_new failed", __func__);
583 buffer_put_int(&msg, id); 583 if ((r = sshbuf_put_u8(msg, SSH2_FXP_NAME)) != 0 ||
584 buffer_put_int(&msg, count); 584 (r = sshbuf_put_u32(msg, id)) != 0 ||
585 (r = sshbuf_put_u32(msg, count)) != 0)
586 fatal("%s: buffer error: %s", __func__, ssh_err(r));
585 debug("request %u: sent names count %d", id, count); 587 debug("request %u: sent names count %d", id, count);
586 for (i = 0; i < count; i++) { 588 for (i = 0; i < count; i++) {
587 buffer_put_cstring(&msg, stats[i].name); 589 if ((r = sshbuf_put_cstring(msg, stats[i].name)) != 0 ||
588 buffer_put_cstring(&msg, stats[i].long_name); 590 (r = sshbuf_put_cstring(msg, stats[i].long_name)) != 0 ||
589 encode_attrib(&msg, &stats[i].attrib); 591 (r = encode_attrib(msg, &stats[i].attrib)) != 0)
592 fatal("%s: buffer error: %s", __func__, ssh_err(r));
590 } 593 }
591 send_msg(&msg); 594 send_msg(msg);
592 buffer_free(&msg); 595 sshbuf_free(msg);
593} 596}
594 597
595static void 598static void
596send_attrib(u_int32_t id, const Attrib *a) 599send_attrib(u_int32_t id, const Attrib *a)
597{ 600{
598 Buffer msg; 601 struct sshbuf *msg;
602 int r;
599 603
600 debug("request %u: sent attrib have 0x%x", id, a->flags); 604 debug("request %u: sent attrib have 0x%x", id, a->flags);
601 buffer_init(&msg); 605 if ((msg = sshbuf_new()) == NULL)
602 buffer_put_char(&msg, SSH2_FXP_ATTRS); 606 fatal("%s: sshbuf_new failed", __func__);
603 buffer_put_int(&msg, id); 607 if ((r = sshbuf_put_u8(msg, SSH2_FXP_ATTRS)) != 0 ||
604 encode_attrib(&msg, a); 608 (r = sshbuf_put_u32(msg, id)) != 0 ||
605 send_msg(&msg); 609 (r = encode_attrib(msg, a)) != 0)
606 buffer_free(&msg); 610 fatal("%s: buffer error: %s", __func__, ssh_err(r));
611 send_msg(msg);
612 sshbuf_free(msg);
607} 613}
608 614
609static void 615static void
610send_statvfs(u_int32_t id, struct statvfs *st) 616send_statvfs(u_int32_t id, struct statvfs *st)
611{ 617{
612 Buffer msg; 618 struct sshbuf *msg;
613 u_int64_t flag; 619 u_int64_t flag;
620 int r;
614 621
615 flag = (st->f_flag & ST_RDONLY) ? SSH2_FXE_STATVFS_ST_RDONLY : 0; 622 flag = (st->f_flag & ST_RDONLY) ? SSH2_FXE_STATVFS_ST_RDONLY : 0;
616 flag |= (st->f_flag & ST_NOSUID) ? SSH2_FXE_STATVFS_ST_NOSUID : 0; 623 flag |= (st->f_flag & ST_NOSUID) ? SSH2_FXE_STATVFS_ST_NOSUID : 0;
617 624
618 buffer_init(&msg); 625 if ((msg = sshbuf_new()) == NULL)
619 buffer_put_char(&msg, SSH2_FXP_EXTENDED_REPLY); 626 fatal("%s: sshbuf_new failed", __func__);
620 buffer_put_int(&msg, id); 627 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED_REPLY)) != 0 ||
621 buffer_put_int64(&msg, st->f_bsize); 628 (r = sshbuf_put_u32(msg, id)) != 0 ||
622 buffer_put_int64(&msg, st->f_frsize); 629 (r = sshbuf_put_u64(msg, st->f_bsize)) != 0 ||
623 buffer_put_int64(&msg, st->f_blocks); 630 (r = sshbuf_put_u64(msg, st->f_frsize)) != 0 ||
624 buffer_put_int64(&msg, st->f_bfree); 631 (r = sshbuf_put_u64(msg, st->f_blocks)) != 0 ||
625 buffer_put_int64(&msg, st->f_bavail); 632 (r = sshbuf_put_u64(msg, st->f_bfree)) != 0 ||
626 buffer_put_int64(&msg, st->f_files); 633 (r = sshbuf_put_u64(msg, st->f_bavail)) != 0 ||
627 buffer_put_int64(&msg, st->f_ffree); 634 (r = sshbuf_put_u64(msg, st->f_files)) != 0 ||
628 buffer_put_int64(&msg, st->f_favail); 635 (r = sshbuf_put_u64(msg, st->f_ffree)) != 0 ||
629 buffer_put_int64(&msg, FSID_TO_ULONG(st->f_fsid)); 636 (r = sshbuf_put_u64(msg, st->f_favail)) != 0 ||
630 buffer_put_int64(&msg, flag); 637 (r = sshbuf_put_u64(msg, FSID_TO_ULONG(st->f_fsid))) != 0 ||
631 buffer_put_int64(&msg, st->f_namemax); 638 (r = sshbuf_put_u64(msg, flag)) != 0 ||
632 send_msg(&msg); 639 (r = sshbuf_put_u64(msg, st->f_namemax)) != 0)
633 buffer_free(&msg); 640 fatal("%s: buffer error: %s", __func__, ssh_err(r));
641 send_msg(msg);
642 sshbuf_free(msg);
634} 643}
635 644
636/* parse incoming */ 645/* parse incoming */
@@ -638,53 +647,59 @@ send_statvfs(u_int32_t id, struct statvfs *st)
638static void 647static void
639process_init(void) 648process_init(void)
640{ 649{
641 Buffer msg; 650 struct sshbuf *msg;
651 int r;
642 652
643 version = get_int(); 653 if ((r = sshbuf_get_u32(iqueue, &version)) != 0)
654 fatal("%s: buffer error: %s", __func__, ssh_err(r));
644 verbose("received client version %u", version); 655 verbose("received client version %u", version);
645 buffer_init(&msg); 656 if ((msg = sshbuf_new()) == NULL)
646 buffer_put_char(&msg, SSH2_FXP_VERSION); 657 fatal("%s: sshbuf_new failed", __func__);
647 buffer_put_int(&msg, SSH2_FILEXFER_VERSION); 658 if ((r = sshbuf_put_u8(msg, SSH2_FXP_VERSION)) != 0 ||
648 /* POSIX rename extension */ 659 (r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0 ||
649 buffer_put_cstring(&msg, "posix-rename@openssh.com"); 660 /* POSIX rename extension */
650 buffer_put_cstring(&msg, "1"); /* version */ 661 (r = sshbuf_put_cstring(msg, "posix-rename@openssh.com")) != 0 ||
651 /* statvfs extension */ 662 (r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */
652 buffer_put_cstring(&msg, "statvfs@openssh.com"); 663 /* statvfs extension */
653 buffer_put_cstring(&msg, "2"); /* version */ 664 (r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 ||
654 /* fstatvfs extension */ 665 (r = sshbuf_put_cstring(msg, "2")) != 0 || /* version */
655 buffer_put_cstring(&msg, "fstatvfs@openssh.com"); 666 /* fstatvfs extension */
656 buffer_put_cstring(&msg, "2"); /* version */ 667 (r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 ||
657 /* hardlink extension */ 668 (r = sshbuf_put_cstring(msg, "2")) != 0 || /* version */
658 buffer_put_cstring(&msg, "hardlink@openssh.com"); 669 /* hardlink extension */
659 buffer_put_cstring(&msg, "1"); /* version */ 670 (r = sshbuf_put_cstring(msg, "hardlink@openssh.com")) != 0 ||
660 /* fsync extension */ 671 (r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */
661 buffer_put_cstring(&msg, "fsync@openssh.com"); 672 /* fsync extension */
662 buffer_put_cstring(&msg, "1"); /* version */ 673 (r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 ||
663 send_msg(&msg); 674 (r = sshbuf_put_cstring(msg, "1")) != 0) /* version */
664 buffer_free(&msg); 675 fatal("%s: buffer error: %s", __func__, ssh_err(r));
676 send_msg(msg);
677 sshbuf_free(msg);
665} 678}
666 679
667static void 680static void
668process_open(u_int32_t id) 681process_open(u_int32_t id)
669{ 682{
670 u_int32_t pflags; 683 u_int32_t pflags;
671 Attrib *a; 684 Attrib a;
672 char *name; 685 char *name;
673 int handle, fd, flags, mode, status = SSH2_FX_FAILURE; 686 int r, handle, fd, flags, mode, status = SSH2_FX_FAILURE;
687
688 if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
689 (r = sshbuf_get_u32(iqueue, &pflags)) != 0 || /* portable flags */
690 (r = decode_attrib(iqueue, &a)) != 0)
691 fatal("%s: buffer error: %s", __func__, ssh_err(r));
674 692
675 name = get_string(NULL);
676 pflags = get_int(); /* portable flags */
677 debug3("request %u: open flags %d", id, pflags); 693 debug3("request %u: open flags %d", id, pflags);
678 a = get_attrib();
679 flags = flags_from_portable(pflags); 694 flags = flags_from_portable(pflags);
680 mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666; 695 mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a.perm : 0666;
681 logit("open \"%s\" flags %s mode 0%o", 696 logit("open \"%s\" flags %s mode 0%o",
682 name, string_from_portable(pflags), mode); 697 name, string_from_portable(pflags), mode);
683 if (readonly && 698 if (readonly &&
684 ((flags & O_ACCMODE) == O_WRONLY || 699 ((flags & O_ACCMODE) == O_WRONLY ||
685 (flags & O_ACCMODE) == O_RDWR)) { 700 (flags & O_ACCMODE) == O_RDWR)) {
686 verbose("Refusing open request in read-only mode"); 701 verbose("Refusing open request in read-only mode");
687 status = SSH2_FX_PERMISSION_DENIED; 702 status = SSH2_FX_PERMISSION_DENIED;
688 } else { 703 } else {
689 fd = open(name, flags, mode); 704 fd = open(name, flags, mode);
690 if (fd < 0) { 705 if (fd < 0) {
@@ -707,9 +722,11 @@ process_open(u_int32_t id)
707static void 722static void
708process_close(u_int32_t id) 723process_close(u_int32_t id)
709{ 724{
710 int handle, ret, status = SSH2_FX_FAILURE; 725 int r, handle, ret, status = SSH2_FX_FAILURE;
726
727 if ((r = get_handle(iqueue, &handle)) != 0)
728 fatal("%s: buffer error: %s", __func__, ssh_err(r));
711 729
712 handle = get_handle();
713 debug3("request %u: close handle %u", id, handle); 730 debug3("request %u: close handle %u", id, handle);
714 handle_log_close(handle, NULL); 731 handle_log_close(handle, NULL);
715 ret = handle_close(handle); 732 ret = handle_close(handle);
@@ -720,14 +737,15 @@ process_close(u_int32_t id)
720static void 737static void
721process_read(u_int32_t id) 738process_read(u_int32_t id)
722{ 739{
723 char buf[64*1024]; 740 u_char buf[64*1024];
724 u_int32_t len; 741 u_int32_t len;
725 int handle, fd, ret, status = SSH2_FX_FAILURE; 742 int r, handle, fd, ret, status = SSH2_FX_FAILURE;
726 u_int64_t off; 743 u_int64_t off;
727 744
728 handle = get_handle(); 745 if ((r = get_handle(iqueue, &handle)) != 0 ||
729 off = get_int64(); 746 (r = sshbuf_get_u64(iqueue, &off)) != 0 ||
730 len = get_int(); 747 (r = sshbuf_get_u32(iqueue, &len)) != 0)
748 fatal("%s: buffer error: %s", __func__, ssh_err(r));
731 749
732 debug("request %u: read \"%s\" (handle %d) off %llu len %d", 750 debug("request %u: read \"%s\" (handle %d) off %llu len %d",
733 id, handle_to_name(handle), handle, (unsigned long long)off, len); 751 id, handle_to_name(handle), handle, (unsigned long long)off, len);
@@ -761,18 +779,19 @@ static void
761process_write(u_int32_t id) 779process_write(u_int32_t id)
762{ 780{
763 u_int64_t off; 781 u_int64_t off;
764 u_int len; 782 size_t len;
765 int handle, fd, ret, status; 783 int r, handle, fd, ret, status;
766 char *data; 784 u_char *data;
767 785
768 handle = get_handle(); 786 if ((r = get_handle(iqueue, &handle)) != 0 ||
769 off = get_int64(); 787 (r = sshbuf_get_u64(iqueue, &off)) != 0 ||
770 data = get_string(&len); 788 (r = sshbuf_get_string(iqueue, &data, &len)) != 0)
789 fatal("%s: buffer error: %s", __func__, ssh_err(r));
771 790
772 debug("request %u: write \"%s\" (handle %d) off %llu len %d", 791 debug("request %u: write \"%s\" (handle %d) off %llu len %zu",
773 id, handle_to_name(handle), handle, (unsigned long long)off, len); 792 id, handle_to_name(handle), handle, (unsigned long long)off, len);
774 fd = handle_to_fd(handle); 793 fd = handle_to_fd(handle);
775 794
776 if (fd < 0) 795 if (fd < 0)
777 status = SSH2_FX_FAILURE; 796 status = SSH2_FX_FAILURE;
778 else { 797 else {
@@ -805,13 +824,15 @@ process_do_stat(u_int32_t id, int do_lstat)
805 Attrib a; 824 Attrib a;
806 struct stat st; 825 struct stat st;
807 char *name; 826 char *name;
808 int ret, status = SSH2_FX_FAILURE; 827 int r, status = SSH2_FX_FAILURE;
828
829 if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0)
830 fatal("%s: buffer error: %s", __func__, ssh_err(r));
809 831
810 name = get_string(NULL);
811 debug3("request %u: %sstat", id, do_lstat ? "l" : ""); 832 debug3("request %u: %sstat", id, do_lstat ? "l" : "");
812 verbose("%sstat name \"%s\"", do_lstat ? "l" : "", name); 833 verbose("%sstat name \"%s\"", do_lstat ? "l" : "", name);
813 ret = do_lstat ? lstat(name, &st) : stat(name, &st); 834 r = do_lstat ? lstat(name, &st) : stat(name, &st);
814 if (ret < 0) { 835 if (r < 0) {
815 status = errno_to_portable(errno); 836 status = errno_to_portable(errno);
816 } else { 837 } else {
817 stat_to_attrib(&st, &a); 838 stat_to_attrib(&st, &a);
@@ -840,15 +861,16 @@ process_fstat(u_int32_t id)
840{ 861{
841 Attrib a; 862 Attrib a;
842 struct stat st; 863 struct stat st;
843 int fd, ret, handle, status = SSH2_FX_FAILURE; 864 int fd, r, handle, status = SSH2_FX_FAILURE;
844 865
845 handle = get_handle(); 866 if ((r = get_handle(iqueue, &handle)) != 0)
867 fatal("%s: buffer error: %s", __func__, ssh_err(r));
846 debug("request %u: fstat \"%s\" (handle %u)", 868 debug("request %u: fstat \"%s\" (handle %u)",
847 id, handle_to_name(handle), handle); 869 id, handle_to_name(handle), handle);
848 fd = handle_to_fd(handle); 870 fd = handle_to_fd(handle);
849 if (fd >= 0) { 871 if (fd >= 0) {
850 ret = fstat(fd, &st); 872 r = fstat(fd, &st);
851 if (ret < 0) { 873 if (r < 0) {
852 status = errno_to_portable(errno); 874 status = errno_to_portable(errno);
853 } else { 875 } else {
854 stat_to_attrib(&st, &a); 876 stat_to_attrib(&st, &a);
@@ -875,42 +897,44 @@ attrib_to_tv(const Attrib *a)
875static void 897static void
876process_setstat(u_int32_t id) 898process_setstat(u_int32_t id)
877{ 899{
878 Attrib *a; 900 Attrib a;
879 char *name; 901 char *name;
880 int status = SSH2_FX_OK, ret; 902 int r, status = SSH2_FX_OK;
903
904 if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
905 (r = decode_attrib(iqueue, &a)) != 0)
906 fatal("%s: buffer error: %s", __func__, ssh_err(r));
881 907
882 name = get_string(NULL);
883 a = get_attrib();
884 debug("request %u: setstat name \"%s\"", id, name); 908 debug("request %u: setstat name \"%s\"", id, name);
885 if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { 909 if (a.flags & SSH2_FILEXFER_ATTR_SIZE) {
886 logit("set \"%s\" size %llu", 910 logit("set \"%s\" size %llu",
887 name, (unsigned long long)a->size); 911 name, (unsigned long long)a.size);
888 ret = truncate(name, a->size); 912 r = truncate(name, a.size);
889 if (ret == -1) 913 if (r == -1)
890 status = errno_to_portable(errno); 914 status = errno_to_portable(errno);
891 } 915 }
892 if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { 916 if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
893 logit("set \"%s\" mode %04o", name, a->perm); 917 logit("set \"%s\" mode %04o", name, a.perm);
894 ret = chmod(name, a->perm & 07777); 918 r = chmod(name, a.perm & 07777);
895 if (ret == -1) 919 if (r == -1)
896 status = errno_to_portable(errno); 920 status = errno_to_portable(errno);
897 } 921 }
898 if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { 922 if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
899 char buf[64]; 923 char buf[64];
900 time_t t = a->mtime; 924 time_t t = a.mtime;
901 925
902 strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S", 926 strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S",
903 localtime(&t)); 927 localtime(&t));
904 logit("set \"%s\" modtime %s", name, buf); 928 logit("set \"%s\" modtime %s", name, buf);
905 ret = utimes(name, attrib_to_tv(a)); 929 r = utimes(name, attrib_to_tv(&a));
906 if (ret == -1) 930 if (r == -1)
907 status = errno_to_portable(errno); 931 status = errno_to_portable(errno);
908 } 932 }
909 if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { 933 if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) {
910 logit("set \"%s\" owner %lu group %lu", name, 934 logit("set \"%s\" owner %lu group %lu", name,
911 (u_long)a->uid, (u_long)a->gid); 935 (u_long)a.uid, (u_long)a.gid);
912 ret = chown(name, a->uid, a->gid); 936 r = chown(name, a.uid, a.gid);
913 if (ret == -1) 937 if (r == -1)
914 status = errno_to_portable(errno); 938 status = errno_to_portable(errno);
915 } 939 }
916 send_status(id, status); 940 send_status(id, status);
@@ -920,12 +944,14 @@ process_setstat(u_int32_t id)
920static void 944static void
921process_fsetstat(u_int32_t id) 945process_fsetstat(u_int32_t id)
922{ 946{
923 Attrib *a; 947 Attrib a;
924 int handle, fd, ret; 948 int handle, fd, r;
925 int status = SSH2_FX_OK; 949 int status = SSH2_FX_OK;
926 950
927 handle = get_handle(); 951 if ((r = get_handle(iqueue, &handle)) != 0 ||
928 a = get_attrib(); 952 (r = decode_attrib(iqueue, &a)) != 0)
953 fatal("%s: buffer error: %s", __func__, ssh_err(r));
954
929 debug("request %u: fsetstat handle %d", id, handle); 955 debug("request %u: fsetstat handle %d", id, handle);
930 fd = handle_to_fd(handle); 956 fd = handle_to_fd(handle);
931 if (fd < 0) 957 if (fd < 0)
@@ -933,47 +959,47 @@ process_fsetstat(u_int32_t id)
933 else { 959 else {
934 char *name = handle_to_name(handle); 960 char *name = handle_to_name(handle);
935 961
936 if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { 962 if (a.flags & SSH2_FILEXFER_ATTR_SIZE) {
937 logit("set \"%s\" size %llu", 963 logit("set \"%s\" size %llu",
938 name, (unsigned long long)a->size); 964 name, (unsigned long long)a.size);
939 ret = ftruncate(fd, a->size); 965 r = ftruncate(fd, a.size);
940 if (ret == -1) 966 if (r == -1)
941 status = errno_to_portable(errno); 967 status = errno_to_portable(errno);
942 } 968 }
943 if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { 969 if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
944 logit("set \"%s\" mode %04o", name, a->perm); 970 logit("set \"%s\" mode %04o", name, a.perm);
945#ifdef HAVE_FCHMOD 971#ifdef HAVE_FCHMOD
946 ret = fchmod(fd, a->perm & 07777); 972 r = fchmod(fd, a.perm & 07777);
947#else 973#else
948 ret = chmod(name, a->perm & 07777); 974 r = chmod(name, a.perm & 07777);
949#endif 975#endif
950 if (ret == -1) 976 if (r == -1)
951 status = errno_to_portable(errno); 977 status = errno_to_portable(errno);
952 } 978 }
953 if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { 979 if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
954 char buf[64]; 980 char buf[64];
955 time_t t = a->mtime; 981 time_t t = a.mtime;
956 982
957 strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S", 983 strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S",
958 localtime(&t)); 984 localtime(&t));
959 logit("set \"%s\" modtime %s", name, buf); 985 logit("set \"%s\" modtime %s", name, buf);
960#ifdef HAVE_FUTIMES 986#ifdef HAVE_FUTIMES
961 ret = futimes(fd, attrib_to_tv(a)); 987 r = futimes(fd, attrib_to_tv(&a));
962#else 988#else
963 ret = utimes(name, attrib_to_tv(a)); 989 r = utimes(name, attrib_to_tv(&a));
964#endif 990#endif
965 if (ret == -1) 991 if (r == -1)
966 status = errno_to_portable(errno); 992 status = errno_to_portable(errno);
967 } 993 }
968 if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) { 994 if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) {
969 logit("set \"%s\" owner %lu group %lu", name, 995 logit("set \"%s\" owner %lu group %lu", name,
970 (u_long)a->uid, (u_long)a->gid); 996 (u_long)a.uid, (u_long)a.gid);
971#ifdef HAVE_FCHOWN 997#ifdef HAVE_FCHOWN
972 ret = fchown(fd, a->uid, a->gid); 998 r = fchown(fd, a.uid, a.gid);
973#else 999#else
974 ret = chown(name, a->uid, a->gid); 1000 r = chown(name, a.uid, a.gid);
975#endif 1001#endif
976 if (ret == -1) 1002 if (r == -1)
977 status = errno_to_portable(errno); 1003 status = errno_to_portable(errno);
978 } 1004 }
979 } 1005 }
@@ -985,9 +1011,11 @@ process_opendir(u_int32_t id)
985{ 1011{
986 DIR *dirp = NULL; 1012 DIR *dirp = NULL;
987 char *path; 1013 char *path;
988 int handle, status = SSH2_FX_FAILURE; 1014 int r, handle, status = SSH2_FX_FAILURE;
1015
1016 if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
1017 fatal("%s: buffer error: %s", __func__, ssh_err(r));
989 1018
990 path = get_string(NULL);
991 debug3("request %u: opendir", id); 1019 debug3("request %u: opendir", id);
992 logit("opendir \"%s\"", path); 1020 logit("opendir \"%s\"", path);
993 dirp = opendir(path); 1021 dirp = opendir(path);
@@ -1014,9 +1042,11 @@ process_readdir(u_int32_t id)
1014 DIR *dirp; 1042 DIR *dirp;
1015 struct dirent *dp; 1043 struct dirent *dp;
1016 char *path; 1044 char *path;
1017 int handle; 1045 int r, handle;
1046
1047 if ((r = get_handle(iqueue, &handle)) != 0)
1048 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1018 1049
1019 handle = get_handle();
1020 debug("request %u: readdir \"%s\" (handle %d)", id, 1050 debug("request %u: readdir \"%s\" (handle %d)", id,
1021 handle_to_name(handle), handle); 1051 handle_to_name(handle), handle);
1022 dirp = handle_to_dir(handle); 1052 dirp = handle_to_dir(handle);
@@ -1025,7 +1055,7 @@ process_readdir(u_int32_t id)
1025 send_status(id, SSH2_FX_FAILURE); 1055 send_status(id, SSH2_FX_FAILURE);
1026 } else { 1056 } else {
1027 struct stat st; 1057 struct stat st;
1028 char pathname[MAXPATHLEN]; 1058 char pathname[PATH_MAX];
1029 Stat *stats; 1059 Stat *stats;
1030 int nstats = 10, count = 0, i; 1060 int nstats = 10, count = 0, i;
1031 1061
@@ -1066,14 +1096,15 @@ static void
1066process_remove(u_int32_t id) 1096process_remove(u_int32_t id)
1067{ 1097{
1068 char *name; 1098 char *name;
1069 int status = SSH2_FX_FAILURE; 1099 int r, status = SSH2_FX_FAILURE;
1070 int ret; 1100
1101 if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0)
1102 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1071 1103
1072 name = get_string(NULL);
1073 debug3("request %u: remove", id); 1104 debug3("request %u: remove", id);
1074 logit("remove name \"%s\"", name); 1105 logit("remove name \"%s\"", name);
1075 ret = unlink(name); 1106 r = unlink(name);
1076 status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 1107 status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
1077 send_status(id, status); 1108 send_status(id, status);
1078 free(name); 1109 free(name);
1079} 1110}
@@ -1081,18 +1112,20 @@ process_remove(u_int32_t id)
1081static void 1112static void
1082process_mkdir(u_int32_t id) 1113process_mkdir(u_int32_t id)
1083{ 1114{
1084 Attrib *a; 1115 Attrib a;
1085 char *name; 1116 char *name;
1086 int ret, mode, status = SSH2_FX_FAILURE; 1117 int r, mode, status = SSH2_FX_FAILURE;
1118
1119 if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
1120 (r = decode_attrib(iqueue, &a)) != 0)
1121 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1087 1122
1088 name = get_string(NULL); 1123 mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ?
1089 a = get_attrib(); 1124 a.perm & 07777 : 0777;
1090 mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ?
1091 a->perm & 07777 : 0777;
1092 debug3("request %u: mkdir", id); 1125 debug3("request %u: mkdir", id);
1093 logit("mkdir name \"%s\" mode 0%o", name, mode); 1126 logit("mkdir name \"%s\" mode 0%o", name, mode);
1094 ret = mkdir(name, mode); 1127 r = mkdir(name, mode);
1095 status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 1128 status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
1096 send_status(id, status); 1129 send_status(id, status);
1097 free(name); 1130 free(name);
1098} 1131}
@@ -1101,13 +1134,15 @@ static void
1101process_rmdir(u_int32_t id) 1134process_rmdir(u_int32_t id)
1102{ 1135{
1103 char *name; 1136 char *name;
1104 int ret, status; 1137 int r, status;
1138
1139 if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0)
1140 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1105 1141
1106 name = get_string(NULL);
1107 debug3("request %u: rmdir", id); 1142 debug3("request %u: rmdir", id);
1108 logit("rmdir name \"%s\"", name); 1143 logit("rmdir name \"%s\"", name);
1109 ret = rmdir(name); 1144 r = rmdir(name);
1110 status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 1145 status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
1111 send_status(id, status); 1146 send_status(id, status);
1112 free(name); 1147 free(name);
1113} 1148}
@@ -1115,10 +1150,13 @@ process_rmdir(u_int32_t id)
1115static void 1150static void
1116process_realpath(u_int32_t id) 1151process_realpath(u_int32_t id)
1117{ 1152{
1118 char resolvedname[MAXPATHLEN]; 1153 char resolvedname[PATH_MAX];
1119 char *path; 1154 char *path;
1155 int r;
1156
1157 if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
1158 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1120 1159
1121 path = get_string(NULL);
1122 if (path[0] == '\0') { 1160 if (path[0] == '\0') {
1123 free(path); 1161 free(path);
1124 path = xstrdup("."); 1162 path = xstrdup(".");
@@ -1140,11 +1178,13 @@ static void
1140process_rename(u_int32_t id) 1178process_rename(u_int32_t id)
1141{ 1179{
1142 char *oldpath, *newpath; 1180 char *oldpath, *newpath;
1143 int status; 1181 int r, status;
1144 struct stat sb; 1182 struct stat sb;
1145 1183
1146 oldpath = get_string(NULL); 1184 if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
1147 newpath = get_string(NULL); 1185 (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
1186 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1187
1148 debug3("request %u: rename", id); 1188 debug3("request %u: rename", id);
1149 logit("rename old \"%s\" new \"%s\"", oldpath, newpath); 1189 logit("rename old \"%s\" new \"%s\"", oldpath, newpath);
1150 status = SSH2_FX_FAILURE; 1190 status = SSH2_FX_FAILURE;
@@ -1197,11 +1237,13 @@ process_rename(u_int32_t id)
1197static void 1237static void
1198process_readlink(u_int32_t id) 1238process_readlink(u_int32_t id)
1199{ 1239{
1200 int len; 1240 int r, len;
1201 char buf[MAXPATHLEN]; 1241 char buf[PATH_MAX];
1202 char *path; 1242 char *path;
1203 1243
1204 path = get_string(NULL); 1244 if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
1245 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1246
1205 debug3("request %u: readlink", id); 1247 debug3("request %u: readlink", id);
1206 verbose("readlink \"%s\"", path); 1248 verbose("readlink \"%s\"", path);
1207 if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1) 1249 if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1)
@@ -1221,15 +1263,17 @@ static void
1221process_symlink(u_int32_t id) 1263process_symlink(u_int32_t id)
1222{ 1264{
1223 char *oldpath, *newpath; 1265 char *oldpath, *newpath;
1224 int ret, status; 1266 int r, status;
1267
1268 if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
1269 (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
1270 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1225 1271
1226 oldpath = get_string(NULL);
1227 newpath = get_string(NULL);
1228 debug3("request %u: symlink", id); 1272 debug3("request %u: symlink", id);
1229 logit("symlink old \"%s\" new \"%s\"", oldpath, newpath); 1273 logit("symlink old \"%s\" new \"%s\"", oldpath, newpath);
1230 /* this will fail if 'newpath' exists */ 1274 /* this will fail if 'newpath' exists */
1231 ret = symlink(oldpath, newpath); 1275 r = symlink(oldpath, newpath);
1232 status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 1276 status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
1233 send_status(id, status); 1277 send_status(id, status);
1234 free(oldpath); 1278 free(oldpath);
1235 free(newpath); 1279 free(newpath);
@@ -1239,14 +1283,16 @@ static void
1239process_extended_posix_rename(u_int32_t id) 1283process_extended_posix_rename(u_int32_t id)
1240{ 1284{
1241 char *oldpath, *newpath; 1285 char *oldpath, *newpath;
1242 int ret, status; 1286 int r, status;
1287
1288 if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
1289 (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
1290 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1243 1291
1244 oldpath = get_string(NULL);
1245 newpath = get_string(NULL);
1246 debug3("request %u: posix-rename", id); 1292 debug3("request %u: posix-rename", id);
1247 logit("posix-rename old \"%s\" new \"%s\"", oldpath, newpath); 1293 logit("posix-rename old \"%s\" new \"%s\"", oldpath, newpath);
1248 ret = rename(oldpath, newpath); 1294 r = rename(oldpath, newpath);
1249 status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 1295 status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
1250 send_status(id, status); 1296 send_status(id, status);
1251 free(oldpath); 1297 free(oldpath);
1252 free(newpath); 1298 free(newpath);
@@ -1257,8 +1303,10 @@ process_extended_statvfs(u_int32_t id)
1257{ 1303{
1258 char *path; 1304 char *path;
1259 struct statvfs st; 1305 struct statvfs st;
1306 int r;
1260 1307
1261 path = get_string(NULL); 1308 if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
1309 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1262 debug3("request %u: statvfs", id); 1310 debug3("request %u: statvfs", id);
1263 logit("statvfs \"%s\"", path); 1311 logit("statvfs \"%s\"", path);
1264 1312
@@ -1272,10 +1320,11 @@ process_extended_statvfs(u_int32_t id)
1272static void 1320static void
1273process_extended_fstatvfs(u_int32_t id) 1321process_extended_fstatvfs(u_int32_t id)
1274{ 1322{
1275 int handle, fd; 1323 int r, handle, fd;
1276 struct statvfs st; 1324 struct statvfs st;
1277 1325
1278 handle = get_handle(); 1326 if ((r = get_handle(iqueue, &handle)) != 0)
1327 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1279 debug("request %u: fstatvfs \"%s\" (handle %u)", 1328 debug("request %u: fstatvfs \"%s\" (handle %u)",
1280 id, handle_to_name(handle), handle); 1329 id, handle_to_name(handle), handle);
1281 if ((fd = handle_to_fd(handle)) < 0) { 1330 if ((fd = handle_to_fd(handle)) < 0) {
@@ -1292,14 +1341,16 @@ static void
1292process_extended_hardlink(u_int32_t id) 1341process_extended_hardlink(u_int32_t id)
1293{ 1342{
1294 char *oldpath, *newpath; 1343 char *oldpath, *newpath;
1295 int ret, status; 1344 int r, status;
1345
1346 if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
1347 (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
1348 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1296 1349
1297 oldpath = get_string(NULL);
1298 newpath = get_string(NULL);
1299 debug3("request %u: hardlink", id); 1350 debug3("request %u: hardlink", id);
1300 logit("hardlink old \"%s\" new \"%s\"", oldpath, newpath); 1351 logit("hardlink old \"%s\" new \"%s\"", oldpath, newpath);
1301 ret = link(oldpath, newpath); 1352 r = link(oldpath, newpath);
1302 status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 1353 status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
1303 send_status(id, status); 1354 send_status(id, status);
1304 free(oldpath); 1355 free(oldpath);
1305 free(newpath); 1356 free(newpath);
@@ -1308,16 +1359,17 @@ process_extended_hardlink(u_int32_t id)
1308static void 1359static void
1309process_extended_fsync(u_int32_t id) 1360process_extended_fsync(u_int32_t id)
1310{ 1361{
1311 int handle, fd, ret, status = SSH2_FX_OP_UNSUPPORTED; 1362 int handle, fd, r, status = SSH2_FX_OP_UNSUPPORTED;
1312 1363
1313 handle = get_handle(); 1364 if ((r = get_handle(iqueue, &handle)) != 0)
1365 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1314 debug3("request %u: fsync (handle %u)", id, handle); 1366 debug3("request %u: fsync (handle %u)", id, handle);
1315 verbose("fsync \"%s\"", handle_to_name(handle)); 1367 verbose("fsync \"%s\"", handle_to_name(handle));
1316 if ((fd = handle_to_fd(handle)) < 0) 1368 if ((fd = handle_to_fd(handle)) < 0)
1317 status = SSH2_FX_NO_SUCH_FILE; 1369 status = SSH2_FX_NO_SUCH_FILE;
1318 else if (handle_is_ok(handle, HANDLE_FILE)) { 1370 else if (handle_is_ok(handle, HANDLE_FILE)) {
1319 ret = fsync(fd); 1371 r = fsync(fd);
1320 status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 1372 status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
1321 } 1373 }
1322 send_status(id, status); 1374 send_status(id, status);
1323} 1375}
@@ -1326,9 +1378,10 @@ static void
1326process_extended(u_int32_t id) 1378process_extended(u_int32_t id)
1327{ 1379{
1328 char *request; 1380 char *request;
1329 u_int i; 1381 int i, r;
1330 1382
1331 request = get_string(NULL); 1383 if ((r = sshbuf_get_cstring(iqueue, &request, NULL)) != 0)
1384 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1332 for (i = 0; extended_handlers[i].handler != NULL; i++) { 1385 for (i = 0; extended_handlers[i].handler != NULL; i++) {
1333 if (strcmp(request, extended_handlers[i].ext_name) == 0) { 1386 if (strcmp(request, extended_handlers[i].ext_name) == 0) {
1334 if (!request_permitted(&extended_handlers[i])) 1387 if (!request_permitted(&extended_handlers[i]))
@@ -1350,14 +1403,18 @@ process_extended(u_int32_t id)
1350static void 1403static void
1351process(void) 1404process(void)
1352{ 1405{
1353 u_int msg_len, buf_len, consumed, type, i; 1406 u_int msg_len;
1354 u_char *cp; 1407 u_int buf_len;
1408 u_int consumed;
1409 u_char type;
1410 const u_char *cp;
1411 int i, r;
1355 u_int32_t id; 1412 u_int32_t id;
1356 1413
1357 buf_len = buffer_len(&iqueue); 1414 buf_len = sshbuf_len(iqueue);
1358 if (buf_len < 5) 1415 if (buf_len < 5)
1359 return; /* Incomplete message. */ 1416 return; /* Incomplete message. */
1360 cp = buffer_ptr(&iqueue); 1417 cp = sshbuf_ptr(iqueue);
1361 msg_len = get_u32(cp); 1418 msg_len = get_u32(cp);
1362 if (msg_len > SFTP_MAX_MSG_LENGTH) { 1419 if (msg_len > SFTP_MAX_MSG_LENGTH) {
1363 error("bad message from %s local user %s", 1420 error("bad message from %s local user %s",
@@ -1366,9 +1423,11 @@ process(void)
1366 } 1423 }
1367 if (buf_len < msg_len + 4) 1424 if (buf_len < msg_len + 4)
1368 return; 1425 return;
1369 buffer_consume(&iqueue, 4); 1426 if ((r = sshbuf_consume(iqueue, 4)) != 0)
1427 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1370 buf_len -= 4; 1428 buf_len -= 4;
1371 type = buffer_get_char(&iqueue); 1429 if ((r = sshbuf_get_u8(iqueue, &type)) != 0)
1430 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1372 1431
1373 switch (type) { 1432 switch (type) {
1374 case SSH2_FXP_INIT: 1433 case SSH2_FXP_INIT:
@@ -1378,13 +1437,15 @@ process(void)
1378 case SSH2_FXP_EXTENDED: 1437 case SSH2_FXP_EXTENDED:
1379 if (!init_done) 1438 if (!init_done)
1380 fatal("Received extended request before init"); 1439 fatal("Received extended request before init");
1381 id = get_int(); 1440 if ((r = sshbuf_get_u32(iqueue, &id)) != 0)
1441 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1382 process_extended(id); 1442 process_extended(id);
1383 break; 1443 break;
1384 default: 1444 default:
1385 if (!init_done) 1445 if (!init_done)
1386 fatal("Received %u request before init", type); 1446 fatal("Received %u request before init", type);
1387 id = get_int(); 1447 if ((r = sshbuf_get_u32(iqueue, &id)) != 0)
1448 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1388 for (i = 0; handlers[i].handler != NULL; i++) { 1449 for (i = 0; handlers[i].handler != NULL; i++) {
1389 if (type == handlers[i].type) { 1450 if (type == handlers[i].type) {
1390 if (!request_permitted(&handlers[i])) { 1451 if (!request_permitted(&handlers[i])) {
@@ -1400,17 +1461,18 @@ process(void)
1400 error("Unknown message %u", type); 1461 error("Unknown message %u", type);
1401 } 1462 }
1402 /* discard the remaining bytes from the current packet */ 1463 /* discard the remaining bytes from the current packet */
1403 if (buf_len < buffer_len(&iqueue)) { 1464 if (buf_len < sshbuf_len(iqueue)) {
1404 error("iqueue grew unexpectedly"); 1465 error("iqueue grew unexpectedly");
1405 sftp_server_cleanup_exit(255); 1466 sftp_server_cleanup_exit(255);
1406 } 1467 }
1407 consumed = buf_len - buffer_len(&iqueue); 1468 consumed = buf_len - sshbuf_len(iqueue);
1408 if (msg_len < consumed) { 1469 if (msg_len < consumed) {
1409 error("msg_len %u < consumed %u", msg_len, consumed); 1470 error("msg_len %u < consumed %u", msg_len, consumed);
1410 sftp_server_cleanup_exit(255); 1471 sftp_server_cleanup_exit(255);
1411 } 1472 }
1412 if (msg_len > consumed) 1473 if (msg_len > consumed &&
1413 buffer_consume(&iqueue, msg_len - consumed); 1474 (r = sshbuf_consume(iqueue, msg_len - consumed)) != 0)
1475 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1414} 1476}
1415 1477
1416/* Cleanup handler that logs active handles upon normal exit */ 1478/* Cleanup handler that logs active handles upon normal exit */
@@ -1443,7 +1505,7 @@ int
1443sftp_server_main(int argc, char **argv, struct passwd *user_pw) 1505sftp_server_main(int argc, char **argv, struct passwd *user_pw)
1444{ 1506{
1445 fd_set *rset, *wset; 1507 fd_set *rset, *wset;
1446 int i, in, out, max, ch, skipargs = 0, log_stderr = 0; 1508 int i, r, in, out, max, ch, skipargs = 0, log_stderr = 0;
1447 ssize_t len, olen, set_size; 1509 ssize_t len, olen, set_size;
1448 SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; 1510 SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
1449 char *cp, *homedir = NULL, buf[4*4096]; 1511 char *cp, *homedir = NULL, buf[4*4096];
@@ -1565,8 +1627,10 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
1565 if (out > max) 1627 if (out > max)
1566 max = out; 1628 max = out;
1567 1629
1568 buffer_init(&iqueue); 1630 if ((iqueue = sshbuf_new()) == NULL)
1569 buffer_init(&oqueue); 1631 fatal("%s: sshbuf_new failed", __func__);
1632 if ((oqueue = sshbuf_new()) == NULL)
1633 fatal("%s: sshbuf_new failed", __func__);
1570 1634
1571 set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask); 1635 set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask);
1572 rset = (fd_set *)xmalloc(set_size); 1636 rset = (fd_set *)xmalloc(set_size);
@@ -1588,11 +1652,15 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
1588 * the worst-case length packet it can generate, 1652 * the worst-case length packet it can generate,
1589 * otherwise apply backpressure by stopping reads. 1653 * otherwise apply backpressure by stopping reads.
1590 */ 1654 */
1591 if (buffer_check_alloc(&iqueue, sizeof(buf)) && 1655 if ((r = sshbuf_check_reserve(iqueue, sizeof(buf))) == 0 &&
1592 buffer_check_alloc(&oqueue, SFTP_MAX_MSG_LENGTH)) 1656 (r = sshbuf_check_reserve(oqueue,
1657 SFTP_MAX_MSG_LENGTH)) == 0)
1593 FD_SET(in, rset); 1658 FD_SET(in, rset);
1659 else if (r != SSH_ERR_NO_BUFFER_SPACE)
1660 fatal("%s: sshbuf_check_reserve failed: %s",
1661 __func__, ssh_err(r));
1594 1662
1595 olen = buffer_len(&oqueue); 1663 olen = sshbuf_len(oqueue);
1596 if (olen > 0) 1664 if (olen > 0)
1597 FD_SET(out, wset); 1665 FD_SET(out, wset);
1598 1666
@@ -1612,18 +1680,20 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
1612 } else if (len < 0) { 1680 } else if (len < 0) {
1613 error("read: %s", strerror(errno)); 1681 error("read: %s", strerror(errno));
1614 sftp_server_cleanup_exit(1); 1682 sftp_server_cleanup_exit(1);
1615 } else { 1683 } else if ((r = sshbuf_put(iqueue, buf, len)) != 0) {
1616 buffer_append(&iqueue, buf, len); 1684 fatal("%s: buffer error: %s",
1685 __func__, ssh_err(r));
1617 } 1686 }
1618 } 1687 }
1619 /* send oqueue to stdout */ 1688 /* send oqueue to stdout */
1620 if (FD_ISSET(out, wset)) { 1689 if (FD_ISSET(out, wset)) {
1621 len = write(out, buffer_ptr(&oqueue), olen); 1690 len = write(out, sshbuf_ptr(oqueue), olen);
1622 if (len < 0) { 1691 if (len < 0) {
1623 error("write: %s", strerror(errno)); 1692 error("write: %s", strerror(errno));
1624 sftp_server_cleanup_exit(1); 1693 sftp_server_cleanup_exit(1);
1625 } else { 1694 } else if ((r = sshbuf_consume(oqueue, len)) != 0) {
1626 buffer_consume(&oqueue, len); 1695 fatal("%s: buffer error: %s",
1696 __func__, ssh_err(r));
1627 } 1697 }
1628 } 1698 }
1629 1699
@@ -1632,7 +1702,11 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
1632 * into the output buffer, otherwise stop processing input 1702 * into the output buffer, otherwise stop processing input
1633 * and let the output queue drain. 1703 * and let the output queue drain.
1634 */ 1704 */
1635 if (buffer_check_alloc(&oqueue, SFTP_MAX_MSG_LENGTH)) 1705 r = sshbuf_check_reserve(oqueue, SFTP_MAX_MSG_LENGTH);
1706 if (r == 0)
1636 process(); 1707 process();
1708 else if (r != SSH_ERR_NO_BUFFER_SPACE)
1709 fatal("%s: sshbuf_check_reserve: %s",
1710 __func__, ssh_err(r));
1637 } 1711 }
1638} 1712}