summaryrefslogtreecommitdiff
path: root/sftp-server.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2015-01-14 13:54:13 +0000
committerDamien Miller <djm@mindrot.org>2015-01-15 02:22:18 +1100
commit7d845f4a0b7ec97887be204c3760e44de8bf1f32 (patch)
treec7f7271203627c22594cc86381745acce479d250 /sftp-server.c
parent139ca81866ec1b219c717d17061e5e7ad1059e2a (diff)
upstream commit
update sftp client and server to new buffer API. pretty much just mechanical changes; with & ok markus
Diffstat (limited to 'sftp-server.c')
-rw-r--r--sftp-server.c610
1 files changed, 374 insertions, 236 deletions
diff --git a/sftp-server.c b/sftp-server.c
index 0177130cf..aeff1aa17 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.104 2015/01/14 13:54:13 djm 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 *
@@ -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,78 @@ 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;
949 int status = SSH2_FX_OK;
950
951 if ((r = get_handle(iqueue, &handle)) != 0 ||
952 (r = decode_attrib(iqueue, &a)) != 0)
953 fatal("%s: buffer error: %s", __func__, ssh_err(r));
954
955 debug("request %u: fsetstat handle %d", id, handle);
956 fd = handle_to_fd(handle);
957 if (fd < 0)
958 status = SSH2_FX_FAILURE;
959 else {
960 char *name = handle_to_name(handle);
961
962 if (a.flags & SSH2_FILEXFER_ATTR_SIZE) {
963 logit("set \"%s\" size %llu",
964 name, (unsigned long long)a.size);
965 r = ftruncate(fd, a.size);
966 if (r == -1)
967 status = errno_to_portable(errno);
968 }
969 if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
970 logit("set \"%s\" mode %04o", name, a.perm);
971#ifdef HAVE_FCHMOD
972 ret = fchmod(fd, a->perm & 07777);
973#else
974 ret = chmod(name, a->perm & 07777);
975#endif
976 if (r == -1)
977 status = errno_to_portable(errno);
978 }
979 if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
980 char buf[64];
981 time_t t = a.mtime;
982
983 strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S",
984 localtime(&t));
985 logit("set \"%s\" modtime %s", name, buf);
986#ifdef HAVE_FUTIMES
987 ret = futimes(fd, attrib_to_tv(a));
988#else
989 ret = utimes(name, attrib_to_tv(a));
990#endif
991 if (r == -1)
992 status = errno_to_portable(errno);
993 }
994 if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) {
995 logit("set \"%s\" owner %lu group %lu", name,
996 (u_long)a.uid, (u_long)a.gid);
997#ifdef HAVE_FCHOWN
998 ret = fchown(fd, a->uid, a->gid);
999#else
1000 ret = chown(name, a->uid, a->gid);
1001#endif
1002 if (r == -1)
1003 status = errno_to_portable(errno);
1004 }
1005 }
1006 send_status(id, status);
1007}
1008static void
1009process_fsetstat(u_int32_t id)
1010{
1011 Attrib a;
1012 int handle, fd, r;
925 int status = SSH2_FX_OK; 1013 int status = SSH2_FX_OK;
926 1014
927 handle = get_handle(); 1015 if ((r = get_handle(iqueue, &handle)) != 0 ||
928 a = get_attrib(); 1016 (r = decode_attrib(iqueue, &a)) != 0)
1017 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1018
929 debug("request %u: fsetstat handle %d", id, handle); 1019 debug("request %u: fsetstat handle %d", id, handle);
930 fd = handle_to_fd(handle); 1020 fd = handle_to_fd(handle);
931 if (fd < 0) 1021 if (fd < 0)
@@ -985,9 +1075,11 @@ process_opendir(u_int32_t id)
985{ 1075{
986 DIR *dirp = NULL; 1076 DIR *dirp = NULL;
987 char *path; 1077 char *path;
988 int handle, status = SSH2_FX_FAILURE; 1078 int r, handle, status = SSH2_FX_FAILURE;
1079
1080 if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
1081 fatal("%s: buffer error: %s", __func__, ssh_err(r));
989 1082
990 path = get_string(NULL);
991 debug3("request %u: opendir", id); 1083 debug3("request %u: opendir", id);
992 logit("opendir \"%s\"", path); 1084 logit("opendir \"%s\"", path);
993 dirp = opendir(path); 1085 dirp = opendir(path);
@@ -1014,9 +1106,11 @@ process_readdir(u_int32_t id)
1014 DIR *dirp; 1106 DIR *dirp;
1015 struct dirent *dp; 1107 struct dirent *dp;
1016 char *path; 1108 char *path;
1017 int handle; 1109 int r, handle;
1110
1111 if ((r = get_handle(iqueue, &handle)) != 0)
1112 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1018 1113
1019 handle = get_handle();
1020 debug("request %u: readdir \"%s\" (handle %d)", id, 1114 debug("request %u: readdir \"%s\" (handle %d)", id,
1021 handle_to_name(handle), handle); 1115 handle_to_name(handle), handle);
1022 dirp = handle_to_dir(handle); 1116 dirp = handle_to_dir(handle);
@@ -1066,14 +1160,15 @@ static void
1066process_remove(u_int32_t id) 1160process_remove(u_int32_t id)
1067{ 1161{
1068 char *name; 1162 char *name;
1069 int status = SSH2_FX_FAILURE; 1163 int r, status = SSH2_FX_FAILURE;
1070 int ret; 1164
1165 if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0)
1166 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1071 1167
1072 name = get_string(NULL);
1073 debug3("request %u: remove", id); 1168 debug3("request %u: remove", id);
1074 logit("remove name \"%s\"", name); 1169 logit("remove name \"%s\"", name);
1075 ret = unlink(name); 1170 r = unlink(name);
1076 status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 1171 status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
1077 send_status(id, status); 1172 send_status(id, status);
1078 free(name); 1173 free(name);
1079} 1174}
@@ -1081,18 +1176,20 @@ process_remove(u_int32_t id)
1081static void 1176static void
1082process_mkdir(u_int32_t id) 1177process_mkdir(u_int32_t id)
1083{ 1178{
1084 Attrib *a; 1179 Attrib a;
1085 char *name; 1180 char *name;
1086 int ret, mode, status = SSH2_FX_FAILURE; 1181 int r, mode, status = SSH2_FX_FAILURE;
1182
1183 if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
1184 (r = decode_attrib(iqueue, &a)) != 0)
1185 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1087 1186
1088 name = get_string(NULL); 1187 mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ?
1089 a = get_attrib(); 1188 a.perm & 07777 : 0777;
1090 mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ?
1091 a->perm & 07777 : 0777;
1092 debug3("request %u: mkdir", id); 1189 debug3("request %u: mkdir", id);
1093 logit("mkdir name \"%s\" mode 0%o", name, mode); 1190 logit("mkdir name \"%s\" mode 0%o", name, mode);
1094 ret = mkdir(name, mode); 1191 r = mkdir(name, mode);
1095 status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 1192 status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
1096 send_status(id, status); 1193 send_status(id, status);
1097 free(name); 1194 free(name);
1098} 1195}
@@ -1101,13 +1198,15 @@ static void
1101process_rmdir(u_int32_t id) 1198process_rmdir(u_int32_t id)
1102{ 1199{
1103 char *name; 1200 char *name;
1104 int ret, status; 1201 int r, status;
1202
1203 if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0)
1204 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1105 1205
1106 name = get_string(NULL);
1107 debug3("request %u: rmdir", id); 1206 debug3("request %u: rmdir", id);
1108 logit("rmdir name \"%s\"", name); 1207 logit("rmdir name \"%s\"", name);
1109 ret = rmdir(name); 1208 r = rmdir(name);
1110 status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 1209 status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
1111 send_status(id, status); 1210 send_status(id, status);
1112 free(name); 1211 free(name);
1113} 1212}
@@ -1117,8 +1216,11 @@ process_realpath(u_int32_t id)
1117{ 1216{
1118 char resolvedname[MAXPATHLEN]; 1217 char resolvedname[MAXPATHLEN];
1119 char *path; 1218 char *path;
1219 int r;
1220
1221 if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
1222 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1120 1223
1121 path = get_string(NULL);
1122 if (path[0] == '\0') { 1224 if (path[0] == '\0') {
1123 free(path); 1225 free(path);
1124 path = xstrdup("."); 1226 path = xstrdup(".");
@@ -1140,11 +1242,13 @@ static void
1140process_rename(u_int32_t id) 1242process_rename(u_int32_t id)
1141{ 1243{
1142 char *oldpath, *newpath; 1244 char *oldpath, *newpath;
1143 int status; 1245 int r, status;
1144 struct stat sb; 1246 struct stat sb;
1145 1247
1146 oldpath = get_string(NULL); 1248 if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
1147 newpath = get_string(NULL); 1249 (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
1250 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1251
1148 debug3("request %u: rename", id); 1252 debug3("request %u: rename", id);
1149 logit("rename old \"%s\" new \"%s\"", oldpath, newpath); 1253 logit("rename old \"%s\" new \"%s\"", oldpath, newpath);
1150 status = SSH2_FX_FAILURE; 1254 status = SSH2_FX_FAILURE;
@@ -1197,11 +1301,13 @@ process_rename(u_int32_t id)
1197static void 1301static void
1198process_readlink(u_int32_t id) 1302process_readlink(u_int32_t id)
1199{ 1303{
1200 int len; 1304 int r, len;
1201 char buf[MAXPATHLEN]; 1305 char buf[MAXPATHLEN];
1202 char *path; 1306 char *path;
1203 1307
1204 path = get_string(NULL); 1308 if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
1309 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1310
1205 debug3("request %u: readlink", id); 1311 debug3("request %u: readlink", id);
1206 verbose("readlink \"%s\"", path); 1312 verbose("readlink \"%s\"", path);
1207 if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1) 1313 if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1)
@@ -1221,15 +1327,17 @@ static void
1221process_symlink(u_int32_t id) 1327process_symlink(u_int32_t id)
1222{ 1328{
1223 char *oldpath, *newpath; 1329 char *oldpath, *newpath;
1224 int ret, status; 1330 int r, status;
1331
1332 if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
1333 (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
1334 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1225 1335
1226 oldpath = get_string(NULL);
1227 newpath = get_string(NULL);
1228 debug3("request %u: symlink", id); 1336 debug3("request %u: symlink", id);
1229 logit("symlink old \"%s\" new \"%s\"", oldpath, newpath); 1337 logit("symlink old \"%s\" new \"%s\"", oldpath, newpath);
1230 /* this will fail if 'newpath' exists */ 1338 /* this will fail if 'newpath' exists */
1231 ret = symlink(oldpath, newpath); 1339 r = symlink(oldpath, newpath);
1232 status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 1340 status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
1233 send_status(id, status); 1341 send_status(id, status);
1234 free(oldpath); 1342 free(oldpath);
1235 free(newpath); 1343 free(newpath);
@@ -1239,14 +1347,16 @@ static void
1239process_extended_posix_rename(u_int32_t id) 1347process_extended_posix_rename(u_int32_t id)
1240{ 1348{
1241 char *oldpath, *newpath; 1349 char *oldpath, *newpath;
1242 int ret, status; 1350 int r, status;
1351
1352 if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
1353 (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
1354 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1243 1355
1244 oldpath = get_string(NULL);
1245 newpath = get_string(NULL);
1246 debug3("request %u: posix-rename", id); 1356 debug3("request %u: posix-rename", id);
1247 logit("posix-rename old \"%s\" new \"%s\"", oldpath, newpath); 1357 logit("posix-rename old \"%s\" new \"%s\"", oldpath, newpath);
1248 ret = rename(oldpath, newpath); 1358 r = rename(oldpath, newpath);
1249 status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 1359 status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
1250 send_status(id, status); 1360 send_status(id, status);
1251 free(oldpath); 1361 free(oldpath);
1252 free(newpath); 1362 free(newpath);
@@ -1257,8 +1367,10 @@ process_extended_statvfs(u_int32_t id)
1257{ 1367{
1258 char *path; 1368 char *path;
1259 struct statvfs st; 1369 struct statvfs st;
1370 int r;
1260 1371
1261 path = get_string(NULL); 1372 if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
1373 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1262 debug3("request %u: statvfs", id); 1374 debug3("request %u: statvfs", id);
1263 logit("statvfs \"%s\"", path); 1375 logit("statvfs \"%s\"", path);
1264 1376
@@ -1272,10 +1384,11 @@ process_extended_statvfs(u_int32_t id)
1272static void 1384static void
1273process_extended_fstatvfs(u_int32_t id) 1385process_extended_fstatvfs(u_int32_t id)
1274{ 1386{
1275 int handle, fd; 1387 int r, handle, fd;
1276 struct statvfs st; 1388 struct statvfs st;
1277 1389
1278 handle = get_handle(); 1390 if ((r = get_handle(iqueue, &handle)) != 0)
1391 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1279 debug("request %u: fstatvfs \"%s\" (handle %u)", 1392 debug("request %u: fstatvfs \"%s\" (handle %u)",
1280 id, handle_to_name(handle), handle); 1393 id, handle_to_name(handle), handle);
1281 if ((fd = handle_to_fd(handle)) < 0) { 1394 if ((fd = handle_to_fd(handle)) < 0) {
@@ -1292,14 +1405,16 @@ static void
1292process_extended_hardlink(u_int32_t id) 1405process_extended_hardlink(u_int32_t id)
1293{ 1406{
1294 char *oldpath, *newpath; 1407 char *oldpath, *newpath;
1295 int ret, status; 1408 int r, status;
1409
1410 if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
1411 (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
1412 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1296 1413
1297 oldpath = get_string(NULL);
1298 newpath = get_string(NULL);
1299 debug3("request %u: hardlink", id); 1414 debug3("request %u: hardlink", id);
1300 logit("hardlink old \"%s\" new \"%s\"", oldpath, newpath); 1415 logit("hardlink old \"%s\" new \"%s\"", oldpath, newpath);
1301 ret = link(oldpath, newpath); 1416 r = link(oldpath, newpath);
1302 status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 1417 status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
1303 send_status(id, status); 1418 send_status(id, status);
1304 free(oldpath); 1419 free(oldpath);
1305 free(newpath); 1420 free(newpath);
@@ -1308,16 +1423,17 @@ process_extended_hardlink(u_int32_t id)
1308static void 1423static void
1309process_extended_fsync(u_int32_t id) 1424process_extended_fsync(u_int32_t id)
1310{ 1425{
1311 int handle, fd, ret, status = SSH2_FX_OP_UNSUPPORTED; 1426 int handle, fd, r, status = SSH2_FX_OP_UNSUPPORTED;
1312 1427
1313 handle = get_handle(); 1428 if ((r = get_handle(iqueue, &handle)) != 0)
1429 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1314 debug3("request %u: fsync (handle %u)", id, handle); 1430 debug3("request %u: fsync (handle %u)", id, handle);
1315 verbose("fsync \"%s\"", handle_to_name(handle)); 1431 verbose("fsync \"%s\"", handle_to_name(handle));
1316 if ((fd = handle_to_fd(handle)) < 0) 1432 if ((fd = handle_to_fd(handle)) < 0)
1317 status = SSH2_FX_NO_SUCH_FILE; 1433 status = SSH2_FX_NO_SUCH_FILE;
1318 else if (handle_is_ok(handle, HANDLE_FILE)) { 1434 else if (handle_is_ok(handle, HANDLE_FILE)) {
1319 ret = fsync(fd); 1435 r = fsync(fd);
1320 status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 1436 status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
1321 } 1437 }
1322 send_status(id, status); 1438 send_status(id, status);
1323} 1439}
@@ -1326,9 +1442,10 @@ static void
1326process_extended(u_int32_t id) 1442process_extended(u_int32_t id)
1327{ 1443{
1328 char *request; 1444 char *request;
1329 u_int i; 1445 int i, r;
1330 1446
1331 request = get_string(NULL); 1447 if ((r = sshbuf_get_cstring(iqueue, &request, NULL)) != 0)
1448 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1332 for (i = 0; extended_handlers[i].handler != NULL; i++) { 1449 for (i = 0; extended_handlers[i].handler != NULL; i++) {
1333 if (strcmp(request, extended_handlers[i].ext_name) == 0) { 1450 if (strcmp(request, extended_handlers[i].ext_name) == 0) {
1334 if (!request_permitted(&extended_handlers[i])) 1451 if (!request_permitted(&extended_handlers[i]))
@@ -1350,14 +1467,18 @@ process_extended(u_int32_t id)
1350static void 1467static void
1351process(void) 1468process(void)
1352{ 1469{
1353 u_int msg_len, buf_len, consumed, type, i; 1470 u_int msg_len;
1354 u_char *cp; 1471 u_int buf_len;
1472 u_int consumed;
1473 u_char type;
1474 const u_char *cp;
1475 int i, r;
1355 u_int32_t id; 1476 u_int32_t id;
1356 1477
1357 buf_len = buffer_len(&iqueue); 1478 buf_len = sshbuf_len(iqueue);
1358 if (buf_len < 5) 1479 if (buf_len < 5)
1359 return; /* Incomplete message. */ 1480 return; /* Incomplete message. */
1360 cp = buffer_ptr(&iqueue); 1481 cp = sshbuf_ptr(iqueue);
1361 msg_len = get_u32(cp); 1482 msg_len = get_u32(cp);
1362 if (msg_len > SFTP_MAX_MSG_LENGTH) { 1483 if (msg_len > SFTP_MAX_MSG_LENGTH) {
1363 error("bad message from %s local user %s", 1484 error("bad message from %s local user %s",
@@ -1366,9 +1487,11 @@ process(void)
1366 } 1487 }
1367 if (buf_len < msg_len + 4) 1488 if (buf_len < msg_len + 4)
1368 return; 1489 return;
1369 buffer_consume(&iqueue, 4); 1490 if ((r = sshbuf_consume(iqueue, 4)) != 0)
1491 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1370 buf_len -= 4; 1492 buf_len -= 4;
1371 type = buffer_get_char(&iqueue); 1493 if ((r = sshbuf_get_u8(iqueue, &type)) != 0)
1494 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1372 1495
1373 switch (type) { 1496 switch (type) {
1374 case SSH2_FXP_INIT: 1497 case SSH2_FXP_INIT:
@@ -1378,13 +1501,15 @@ process(void)
1378 case SSH2_FXP_EXTENDED: 1501 case SSH2_FXP_EXTENDED:
1379 if (!init_done) 1502 if (!init_done)
1380 fatal("Received extended request before init"); 1503 fatal("Received extended request before init");
1381 id = get_int(); 1504 if ((r = sshbuf_get_u32(iqueue, &id)) != 0)
1505 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1382 process_extended(id); 1506 process_extended(id);
1383 break; 1507 break;
1384 default: 1508 default:
1385 if (!init_done) 1509 if (!init_done)
1386 fatal("Received %u request before init", type); 1510 fatal("Received %u request before init", type);
1387 id = get_int(); 1511 if ((r = sshbuf_get_u32(iqueue, &id)) != 0)
1512 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1388 for (i = 0; handlers[i].handler != NULL; i++) { 1513 for (i = 0; handlers[i].handler != NULL; i++) {
1389 if (type == handlers[i].type) { 1514 if (type == handlers[i].type) {
1390 if (!request_permitted(&handlers[i])) { 1515 if (!request_permitted(&handlers[i])) {
@@ -1400,17 +1525,18 @@ process(void)
1400 error("Unknown message %u", type); 1525 error("Unknown message %u", type);
1401 } 1526 }
1402 /* discard the remaining bytes from the current packet */ 1527 /* discard the remaining bytes from the current packet */
1403 if (buf_len < buffer_len(&iqueue)) { 1528 if (buf_len < sshbuf_len(iqueue)) {
1404 error("iqueue grew unexpectedly"); 1529 error("iqueue grew unexpectedly");
1405 sftp_server_cleanup_exit(255); 1530 sftp_server_cleanup_exit(255);
1406 } 1531 }
1407 consumed = buf_len - buffer_len(&iqueue); 1532 consumed = buf_len - sshbuf_len(iqueue);
1408 if (msg_len < consumed) { 1533 if (msg_len < consumed) {
1409 error("msg_len %u < consumed %u", msg_len, consumed); 1534 error("msg_len %u < consumed %u", msg_len, consumed);
1410 sftp_server_cleanup_exit(255); 1535 sftp_server_cleanup_exit(255);
1411 } 1536 }
1412 if (msg_len > consumed) 1537 if (msg_len > consumed &&
1413 buffer_consume(&iqueue, msg_len - consumed); 1538 (r = sshbuf_consume(iqueue, msg_len - consumed)) != 0)
1539 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1414} 1540}
1415 1541
1416/* Cleanup handler that logs active handles upon normal exit */ 1542/* Cleanup handler that logs active handles upon normal exit */
@@ -1443,7 +1569,7 @@ int
1443sftp_server_main(int argc, char **argv, struct passwd *user_pw) 1569sftp_server_main(int argc, char **argv, struct passwd *user_pw)
1444{ 1570{
1445 fd_set *rset, *wset; 1571 fd_set *rset, *wset;
1446 int i, in, out, max, ch, skipargs = 0, log_stderr = 0; 1572 int i, r, in, out, max, ch, skipargs = 0, log_stderr = 0;
1447 ssize_t len, olen, set_size; 1573 ssize_t len, olen, set_size;
1448 SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; 1574 SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
1449 char *cp, *homedir = NULL, buf[4*4096]; 1575 char *cp, *homedir = NULL, buf[4*4096];
@@ -1565,8 +1691,10 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
1565 if (out > max) 1691 if (out > max)
1566 max = out; 1692 max = out;
1567 1693
1568 buffer_init(&iqueue); 1694 if ((iqueue = sshbuf_new()) == NULL)
1569 buffer_init(&oqueue); 1695 fatal("%s: sshbuf_new failed", __func__);
1696 if ((oqueue = sshbuf_new()) == NULL)
1697 fatal("%s: sshbuf_new failed", __func__);
1570 1698
1571 set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask); 1699 set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask);
1572 rset = (fd_set *)xmalloc(set_size); 1700 rset = (fd_set *)xmalloc(set_size);
@@ -1588,11 +1716,15 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
1588 * the worst-case length packet it can generate, 1716 * the worst-case length packet it can generate,
1589 * otherwise apply backpressure by stopping reads. 1717 * otherwise apply backpressure by stopping reads.
1590 */ 1718 */
1591 if (buffer_check_alloc(&iqueue, sizeof(buf)) && 1719 if ((r = sshbuf_check_reserve(iqueue, sizeof(buf))) == 0 &&
1592 buffer_check_alloc(&oqueue, SFTP_MAX_MSG_LENGTH)) 1720 (r = sshbuf_check_reserve(oqueue,
1721 SFTP_MAX_MSG_LENGTH)) == 0)
1593 FD_SET(in, rset); 1722 FD_SET(in, rset);
1723 else if (r != SSH_ERR_NO_BUFFER_SPACE)
1724 fatal("%s: sshbuf_check_reserve failed: %s",
1725 __func__, ssh_err(r));
1594 1726
1595 olen = buffer_len(&oqueue); 1727 olen = sshbuf_len(oqueue);
1596 if (olen > 0) 1728 if (olen > 0)
1597 FD_SET(out, wset); 1729 FD_SET(out, wset);
1598 1730
@@ -1612,18 +1744,20 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
1612 } else if (len < 0) { 1744 } else if (len < 0) {
1613 error("read: %s", strerror(errno)); 1745 error("read: %s", strerror(errno));
1614 sftp_server_cleanup_exit(1); 1746 sftp_server_cleanup_exit(1);
1615 } else { 1747 } else if ((r = sshbuf_put(iqueue, buf, len)) != 0) {
1616 buffer_append(&iqueue, buf, len); 1748 fatal("%s: buffer error: %s",
1749 __func__, ssh_err(r));
1617 } 1750 }
1618 } 1751 }
1619 /* send oqueue to stdout */ 1752 /* send oqueue to stdout */
1620 if (FD_ISSET(out, wset)) { 1753 if (FD_ISSET(out, wset)) {
1621 len = write(out, buffer_ptr(&oqueue), olen); 1754 len = write(out, sshbuf_ptr(oqueue), olen);
1622 if (len < 0) { 1755 if (len < 0) {
1623 error("write: %s", strerror(errno)); 1756 error("write: %s", strerror(errno));
1624 sftp_server_cleanup_exit(1); 1757 sftp_server_cleanup_exit(1);
1625 } else { 1758 } else if ((r = sshbuf_consume(oqueue, len)) != 0) {
1626 buffer_consume(&oqueue, len); 1759 fatal("%s: buffer error: %s",
1760 __func__, ssh_err(r));
1627 } 1761 }
1628 } 1762 }
1629 1763
@@ -1632,7 +1766,11 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
1632 * into the output buffer, otherwise stop processing input 1766 * into the output buffer, otherwise stop processing input
1633 * and let the output queue drain. 1767 * and let the output queue drain.
1634 */ 1768 */
1635 if (buffer_check_alloc(&oqueue, SFTP_MAX_MSG_LENGTH)) 1769 r = sshbuf_check_reserve(oqueue, SFTP_MAX_MSG_LENGTH);
1770 if (r == 0)
1636 process(); 1771 process();
1772 else if (r != SSH_ERR_NO_BUFFER_SPACE)
1773 fatal("%s: sshbuf_check_reserve: %s",
1774 __func__, ssh_err(r));
1637 } 1775 }
1638} 1776}