|
Lines 61-66
Buffer oqueue;
Link Here
|
| 61 |
/* Version of client */ |
61 |
/* Version of client */ |
| 62 |
int version; |
62 |
int version; |
| 63 |
|
63 |
|
|
|
64 |
/* Disable writes */ |
| 65 |
int readonly; |
| 66 |
|
| 64 |
/* portable attributes, etc. */ |
67 |
/* portable attributes, etc. */ |
| 65 |
|
68 |
|
| 66 |
typedef struct Stat Stat; |
69 |
typedef struct Stat Stat; |
|
Lines 544-559
process_open(void)
Link Here
|
| 544 |
mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666; |
547 |
mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666; |
| 545 |
logit("open \"%s\" flags %s mode 0%o", |
548 |
logit("open \"%s\" flags %s mode 0%o", |
| 546 |
name, string_from_portable(pflags), mode); |
549 |
name, string_from_portable(pflags), mode); |
| 547 |
fd = open(name, flags, mode); |
550 |
if (readonly && |
| 548 |
if (fd < 0) { |
551 |
((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR)) |
| 549 |
status = errno_to_portable(errno); |
552 |
status = SSH2_FX_PERMISSION_DENIED; |
| 550 |
} else { |
553 |
else { |
| 551 |
handle = handle_new(HANDLE_FILE, name, fd, NULL); |
554 |
fd = open(name, flags, mode); |
| 552 |
if (handle < 0) { |
555 |
if (fd < 0) { |
| 553 |
close(fd); |
556 |
status = errno_to_portable(errno); |
| 554 |
} else { |
557 |
} else { |
| 555 |
send_handle(id, handle); |
558 |
handle = handle_new(HANDLE_FILE, name, fd, NULL); |
| 556 |
status = SSH2_FX_OK; |
559 |
if (handle < 0) { |
|
|
560 |
close(fd); |
| 561 |
} else { |
| 562 |
send_handle(id, handle); |
| 563 |
status = SSH2_FX_OK; |
| 564 |
} |
| 557 |
} |
565 |
} |
| 558 |
} |
566 |
} |
| 559 |
if (status != SSH2_FX_OK) |
567 |
if (status != SSH2_FX_OK) |
|
Lines 623-629
process_write(void)
Link Here
|
| 623 |
u_int32_t id; |
631 |
u_int32_t id; |
| 624 |
u_int64_t off; |
632 |
u_int64_t off; |
| 625 |
u_int len; |
633 |
u_int len; |
| 626 |
int handle, fd, ret, status = SSH2_FX_FAILURE; |
634 |
int handle, fd, ret, status; |
| 627 |
char *data; |
635 |
char *data; |
| 628 |
|
636 |
|
| 629 |
id = get_int(); |
637 |
id = get_int(); |
|
Lines 634-640
process_write(void)
Link Here
|
| 634 |
debug("request %u: write \"%s\" (handle %d) off %llu len %d", |
642 |
debug("request %u: write \"%s\" (handle %d) off %llu len %d", |
| 635 |
id, handle_to_name(handle), handle, (unsigned long long)off, len); |
643 |
id, handle_to_name(handle), handle, (unsigned long long)off, len); |
| 636 |
fd = handle_to_fd(handle); |
644 |
fd = handle_to_fd(handle); |
| 637 |
if (fd >= 0) { |
645 |
|
|
|
646 |
if (fd < 0) |
| 647 |
status = SSH2_FX_FAILURE; |
| 648 |
else if (readonly) |
| 649 |
status = SSH2_FX_PERMISSION_DENIED; |
| 650 |
else { |
| 638 |
if (lseek(fd, off, SEEK_SET) < 0) { |
651 |
if (lseek(fd, off, SEEK_SET) < 0) { |
| 639 |
status = errno_to_portable(errno); |
652 |
status = errno_to_portable(errno); |
| 640 |
error("process_write: seek failed"); |
653 |
error("process_write: seek failed"); |
|
Lines 649-654
process_write(void)
Link Here
|
| 649 |
handle_update_write(handle, ret); |
662 |
handle_update_write(handle, ret); |
| 650 |
} else { |
663 |
} else { |
| 651 |
debug2("nothing at all written"); |
664 |
debug2("nothing at all written"); |
|
|
665 |
status = SSH2_FX_FAILURE; |
| 652 |
} |
666 |
} |
| 653 |
} |
667 |
} |
| 654 |
} |
668 |
} |
|
Lines 745-750
process_setstat(void)
Link Here
|
| 745 |
name = get_string(NULL); |
759 |
name = get_string(NULL); |
| 746 |
a = get_attrib(); |
760 |
a = get_attrib(); |
| 747 |
debug("request %u: setstat name \"%s\"", id, name); |
761 |
debug("request %u: setstat name \"%s\"", id, name); |
|
|
762 |
if (readonly) { |
| 763 |
status = SSH2_FX_PERMISSION_DENIED; |
| 764 |
a->flags = 0; |
| 765 |
} |
| 748 |
if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { |
766 |
if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { |
| 749 |
logit("set \"%s\" size %llu", |
767 |
logit("set \"%s\" size %llu", |
| 750 |
name, (unsigned long long)a->size); |
768 |
name, (unsigned long long)a->size); |
|
Lines 793-801
process_fsetstat(void)
Link Here
|
| 793 |
a = get_attrib(); |
811 |
a = get_attrib(); |
| 794 |
debug("request %u: fsetstat handle %d", id, handle); |
812 |
debug("request %u: fsetstat handle %d", id, handle); |
| 795 |
fd = handle_to_fd(handle); |
813 |
fd = handle_to_fd(handle); |
| 796 |
if (fd < 0) { |
814 |
if (fd < 0) |
| 797 |
status = SSH2_FX_FAILURE; |
815 |
status = SSH2_FX_FAILURE; |
| 798 |
} else { |
816 |
else if (readonly) |
|
|
817 |
status = SSH2_FX_PERMISSION_DENIED; |
| 818 |
else { |
| 799 |
char *name = handle_to_name(handle); |
819 |
char *name = handle_to_name(handle); |
| 800 |
|
820 |
|
| 801 |
if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { |
821 |
if (a->flags & SSH2_FILEXFER_ATTR_SIZE) { |
|
Lines 931-938
process_remove(void)
Link Here
|
| 931 |
name = get_string(NULL); |
951 |
name = get_string(NULL); |
| 932 |
debug3("request %u: remove", id); |
952 |
debug3("request %u: remove", id); |
| 933 |
logit("remove name \"%s\"", name); |
953 |
logit("remove name \"%s\"", name); |
| 934 |
ret = unlink(name); |
954 |
if (readonly) |
| 935 |
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
955 |
status = SSH2_FX_PERMISSION_DENIED; |
|
|
956 |
else { |
| 957 |
ret = unlink(name); |
| 958 |
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
| 959 |
} |
| 936 |
send_status(id, status); |
960 |
send_status(id, status); |
| 937 |
xfree(name); |
961 |
xfree(name); |
| 938 |
} |
962 |
} |
|
Lines 952-959
process_mkdir(void)
Link Here
|
| 952 |
a->perm & 07777 : 0777; |
976 |
a->perm & 07777 : 0777; |
| 953 |
debug3("request %u: mkdir", id); |
977 |
debug3("request %u: mkdir", id); |
| 954 |
logit("mkdir name \"%s\" mode 0%o", name, mode); |
978 |
logit("mkdir name \"%s\" mode 0%o", name, mode); |
| 955 |
ret = mkdir(name, mode); |
979 |
if (readonly) |
| 956 |
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
980 |
status = SSH2_FX_PERMISSION_DENIED; |
|
|
981 |
else { |
| 982 |
ret = mkdir(name, mode); |
| 983 |
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
| 984 |
} |
| 957 |
send_status(id, status); |
985 |
send_status(id, status); |
| 958 |
xfree(name); |
986 |
xfree(name); |
| 959 |
} |
987 |
} |
|
Lines 969-976
process_rmdir(void)
Link Here
|
| 969 |
name = get_string(NULL); |
997 |
name = get_string(NULL); |
| 970 |
debug3("request %u: rmdir", id); |
998 |
debug3("request %u: rmdir", id); |
| 971 |
logit("rmdir name \"%s\"", name); |
999 |
logit("rmdir name \"%s\"", name); |
| 972 |
ret = rmdir(name); |
1000 |
if (readonly) |
| 973 |
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
1001 |
status = SSH2_FX_PERMISSION_DENIED; |
|
|
1002 |
else { |
| 1003 |
ret = rmdir(name); |
| 1004 |
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
| 1005 |
} |
| 974 |
send_status(id, status); |
1006 |
send_status(id, status); |
| 975 |
xfree(name); |
1007 |
xfree(name); |
| 976 |
} |
1008 |
} |
|
Lines 1015-1021
process_rename(void)
Link Here
|
| 1015 |
debug3("request %u: rename", id); |
1047 |
debug3("request %u: rename", id); |
| 1016 |
logit("rename old \"%s\" new \"%s\"", oldpath, newpath); |
1048 |
logit("rename old \"%s\" new \"%s\"", oldpath, newpath); |
| 1017 |
status = SSH2_FX_FAILURE; |
1049 |
status = SSH2_FX_FAILURE; |
| 1018 |
if (lstat(oldpath, &sb) == -1) |
1050 |
if (readonly) |
|
|
1051 |
status = SSH2_FX_PERMISSION_DENIED; |
| 1052 |
else if (lstat(oldpath, &sb) == -1) |
| 1019 |
status = errno_to_portable(errno); |
1053 |
status = errno_to_portable(errno); |
| 1020 |
else if (S_ISREG(sb.st_mode)) { |
1054 |
else if (S_ISREG(sb.st_mode)) { |
| 1021 |
/* Race-free rename of regular files */ |
1055 |
/* Race-free rename of regular files */ |
|
Lines 1092-1099
process_symlink(void)
Link Here
|
| 1092 |
debug3("request %u: symlink", id); |
1126 |
debug3("request %u: symlink", id); |
| 1093 |
logit("symlink old \"%s\" new \"%s\"", oldpath, newpath); |
1127 |
logit("symlink old \"%s\" new \"%s\"", oldpath, newpath); |
| 1094 |
/* this will fail if 'newpath' exists */ |
1128 |
/* this will fail if 'newpath' exists */ |
| 1095 |
ret = symlink(oldpath, newpath); |
1129 |
if (readonly) |
| 1096 |
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
1130 |
status = SSH2_FX_PERMISSION_DENIED; |
|
|
1131 |
else { |
| 1132 |
ret = symlink(oldpath, newpath); |
| 1133 |
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
| 1134 |
} |
| 1097 |
send_status(id, status); |
1135 |
send_status(id, status); |
| 1098 |
xfree(oldpath); |
1136 |
xfree(oldpath); |
| 1099 |
xfree(newpath); |
1137 |
xfree(newpath); |
|
Lines 1103-1117
static void
Link Here
|
| 1103 |
process_extended_posix_rename(u_int32_t id) |
1141 |
process_extended_posix_rename(u_int32_t id) |
| 1104 |
{ |
1142 |
{ |
| 1105 |
char *oldpath, *newpath; |
1143 |
char *oldpath, *newpath; |
|
|
1144 |
int ret, status; |
| 1106 |
|
1145 |
|
| 1107 |
oldpath = get_string(NULL); |
1146 |
oldpath = get_string(NULL); |
| 1108 |
newpath = get_string(NULL); |
1147 |
newpath = get_string(NULL); |
| 1109 |
debug3("request %u: posix-rename", id); |
1148 |
debug3("request %u: posix-rename", id); |
| 1110 |
logit("posix-rename old \"%s\" new \"%s\"", oldpath, newpath); |
1149 |
logit("posix-rename old \"%s\" new \"%s\"", oldpath, newpath); |
| 1111 |
if (rename(oldpath, newpath) == -1) |
1150 |
if (readonly) |
| 1112 |
send_status(id, errno_to_portable(errno)); |
1151 |
status = SSH2_FX_PERMISSION_DENIED; |
| 1113 |
else |
1152 |
else { |
| 1114 |
send_status(id, SSH2_FX_OK); |
1153 |
ret = rename(oldpath, newpath); |
|
|
1154 |
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; |
| 1155 |
} |
| 1156 |
send_status(id, status); |
| 1115 |
xfree(oldpath); |
1157 |
xfree(oldpath); |
| 1116 |
xfree(newpath); |
1158 |
xfree(newpath); |
| 1117 |
} |
1159 |
} |
|
Lines 1294-1300
sftp_server_usage(void)
Link Here
|
| 1294 |
extern char *__progname; |
1336 |
extern char *__progname; |
| 1295 |
|
1337 |
|
| 1296 |
fprintf(stderr, |
1338 |
fprintf(stderr, |
| 1297 |
"usage: %s [-eh] [-f log_facility] [-l log_level] [-u umask]\n", |
1339 |
"usage: %s [-Reh] [-f log_facility] [-l log_level] [-u umask]\n", |
| 1298 |
__progname); |
1340 |
__progname); |
| 1299 |
exit(1); |
1341 |
exit(1); |
| 1300 |
} |
1342 |
} |
|
Lines 1315-1322
sftp_server_main(int argc, char **argv,
Link Here
|
| 1315 |
|
1357 |
|
| 1316 |
log_init(__progname, log_level, log_facility, log_stderr); |
1358 |
log_init(__progname, log_level, log_facility, log_stderr); |
| 1317 |
|
1359 |
|
| 1318 |
while (!skipargs && (ch = getopt(argc, argv, "f:l:u:che")) != -1) { |
1360 |
while (!skipargs && (ch = getopt(argc, argv, "f:l:u:Rche")) != -1) { |
| 1319 |
switch (ch) { |
1361 |
switch (ch) { |
|
|
1362 |
case 'R': |
| 1363 |
readonly = 1; |
| 1364 |
break; |
| 1320 |
case 'c': |
1365 |
case 'c': |
| 1321 |
/* |
1366 |
/* |
| 1322 |
* Ignore all arguments if we are invoked as a |
1367 |
* Ignore all arguments if we are invoked as a |