diff options
Diffstat (limited to 'sftp-server.c')
-rw-r--r-- | sftp-server.c | 592 |
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 */ |
64 | static LogLevel log_level = SYSLOG_LEVEL_ERROR; | 60 | static LogLevel log_level = SYSLOG_LEVEL_ERROR; |
65 | 61 | ||
@@ -68,8 +64,8 @@ static struct passwd *pw = NULL; | |||
68 | static char *client_addr = NULL; | 64 | static char *client_addr = NULL; |
69 | 65 | ||
70 | /* input and output queue */ | 66 | /* input and output queue */ |
71 | static Buffer iqueue; | 67 | struct sshbuf *iqueue; |
72 | static Buffer oqueue; | 68 | struct sshbuf *oqueue; |
73 | 69 | ||
74 | /* Version of client */ | 70 | /* Version of client */ |
75 | static u_int version; | 71 | static u_int version; |
@@ -275,12 +271,6 @@ string_from_portable(int pflags) | |||
275 | return ret; | 271 | return ret; |
276 | } | 272 | } |
277 | 273 | ||
278 | static Attrib * | ||
279 | get_attrib(void) | ||
280 | { | ||
281 | return decode_attrib(&iqueue); | ||
282 | } | ||
283 | |||
284 | /* handle handles */ | 274 | /* handle handles */ |
285 | 275 | ||
286 | typedef struct Handle Handle; | 276 | typedef struct Handle Handle; |
@@ -344,7 +334,7 @@ handle_is_ok(int i, int type) | |||
344 | } | 334 | } |
345 | 335 | ||
346 | static int | 336 | static int |
347 | handle_to_string(int handle, char **stringp, int *hlenp) | 337 | handle_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 | ||
357 | static int | 347 | static int |
358 | handle_from_string(const char *handle, u_int hlen) | 348 | handle_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 | ||
479 | static int | 469 | static int |
480 | get_handle(void) | 470 | get_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 | ||
495 | static void | 487 | static void |
496 | send_msg(Buffer *m) | 488 | send_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 | ||
505 | static const char * | 497 | static const char * |
@@ -523,38 +515,46 @@ status_to_message(u_int32_t status) | |||
523 | static void | 515 | static void |
524 | send_status(u_int32_t id, u_int32_t status) | 516 | send_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 | } |
543 | static void | 540 | static void |
544 | send_data_or_handle(char type, u_int32_t id, const char *data, int dlen) | 541 | send_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 | ||
556 | static void | 556 | static void |
557 | send_data(u_int32_t id, const char *data, int dlen) | 557 | send_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) | |||
563 | static void | 563 | static void |
564 | send_handle(u_int32_t id, int handle) | 564 | send_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) | |||
575 | static void | 575 | static void |
576 | send_names(u_int32_t id, int count, const Stat *stats) | 576 | send_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 | ||
595 | static void | 598 | static void |
596 | send_attrib(u_int32_t id, const Attrib *a) | 599 | send_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 | ||
609 | static void | 615 | static void |
610 | send_statvfs(u_int32_t id, struct statvfs *st) | 616 | send_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) | |||
638 | static void | 647 | static void |
639 | process_init(void) | 648 | process_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 | ||
667 | static void | 680 | static void |
668 | process_open(u_int32_t id) | 681 | process_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) | |||
707 | static void | 722 | static void |
708 | process_close(u_int32_t id) | 723 | process_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) | |||
720 | static void | 737 | static void |
721 | process_read(u_int32_t id) | 738 | process_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 | |||
761 | process_write(u_int32_t id) | 779 | process_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) | |||
875 | static void | 897 | static void |
876 | process_setstat(u_int32_t id) | 898 | process_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) | |||
920 | static void | 944 | static void |
921 | process_fsetstat(u_int32_t id) | 945 | process_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 | |||
1066 | process_remove(u_int32_t id) | 1096 | process_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) | |||
1081 | static void | 1112 | static void |
1082 | process_mkdir(u_int32_t id) | 1113 | process_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 | |||
1101 | process_rmdir(u_int32_t id) | 1134 | process_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) | |||
1115 | static void | 1150 | static void |
1116 | process_realpath(u_int32_t id) | 1151 | process_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 | |||
1140 | process_rename(u_int32_t id) | 1178 | process_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) | |||
1197 | static void | 1237 | static void |
1198 | process_readlink(u_int32_t id) | 1238 | process_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 | |||
1221 | process_symlink(u_int32_t id) | 1263 | process_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 | |||
1239 | process_extended_posix_rename(u_int32_t id) | 1283 | process_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) | |||
1272 | static void | 1320 | static void |
1273 | process_extended_fstatvfs(u_int32_t id) | 1321 | process_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 | |||
1292 | process_extended_hardlink(u_int32_t id) | 1341 | process_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) | |||
1308 | static void | 1359 | static void |
1309 | process_extended_fsync(u_int32_t id) | 1360 | process_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 | |||
1326 | process_extended(u_int32_t id) | 1378 | process_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) | |||
1350 | static void | 1403 | static void |
1351 | process(void) | 1404 | process(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 | |||
1443 | sftp_server_main(int argc, char **argv, struct passwd *user_pw) | 1505 | sftp_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 | } |