sftp-server.c revision 323129
1/* $OpenBSD: sftp-server.c,v 1.109 2016/02/15 09:47:49 dtucker Exp $ */ 2/* 3 * Copyright (c) 2000-2004 Markus Friedl. All rights reserved. 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18#include "includes.h" 19 20#include <sys/param.h> /* MIN */ 21#include <sys/types.h> 22#include <sys/stat.h> 23#ifdef HAVE_SYS_TIME_H 24# include <sys/time.h> 25#endif 26#ifdef HAVE_SYS_MOUNT_H 27#include <sys/mount.h> 28#endif 29#ifdef HAVE_SYS_STATVFS_H 30#include <sys/statvfs.h> 31#endif 32 33#include <dirent.h> 34#include <errno.h> 35#include <fcntl.h> 36#include <pwd.h> 37#include <stdlib.h> 38#include <stdio.h> 39#include <string.h> 40#include <time.h> 41#include <unistd.h> 42#include <stdarg.h> 43 44#include "xmalloc.h" 45#include "sshbuf.h" 46#include "ssherr.h" 47#include "log.h" 48#include "misc.h" 49#include "match.h" 50#include "uidswap.h" 51 52#include "sftp.h" 53#include "sftp-common.h" 54 55/* Our verbosity */ 56static LogLevel log_level = SYSLOG_LEVEL_ERROR; 57 58/* Our client */ 59static struct passwd *pw = NULL; 60static char *client_addr = NULL; 61 62/* input and output queue */ 63struct sshbuf *iqueue; 64struct sshbuf *oqueue; 65 66/* Version of client */ 67static u_int version; 68 69/* SSH2_FXP_INIT received */ 70static int init_done; 71 72/* Disable writes */ 73static int readonly; 74 75/* Requests that are allowed/denied */ 76static char *request_whitelist, *request_blacklist; 77 78/* portable attributes, etc. */ 79typedef struct Stat Stat; 80 81struct Stat { 82 char *name; 83 char *long_name; 84 Attrib attrib; 85}; 86 87/* Packet handlers */ 88static void process_open(u_int32_t id); 89static void process_close(u_int32_t id); 90static void process_read(u_int32_t id); 91static void process_write(u_int32_t id); 92static void process_stat(u_int32_t id); 93static void process_lstat(u_int32_t id); 94static void process_fstat(u_int32_t id); 95static void process_setstat(u_int32_t id); 96static void process_fsetstat(u_int32_t id); 97static void process_opendir(u_int32_t id); 98static void process_readdir(u_int32_t id); 99static void process_remove(u_int32_t id); 100static void process_mkdir(u_int32_t id); 101static void process_rmdir(u_int32_t id); 102static void process_realpath(u_int32_t id); 103static void process_rename(u_int32_t id); 104static void process_readlink(u_int32_t id); 105static void process_symlink(u_int32_t id); 106static void process_extended_posix_rename(u_int32_t id); 107static void process_extended_statvfs(u_int32_t id); 108static void process_extended_fstatvfs(u_int32_t id); 109static void process_extended_hardlink(u_int32_t id); 110static void process_extended_fsync(u_int32_t id); 111static void process_extended(u_int32_t id); 112 113struct sftp_handler { 114 const char *name; /* user-visible name for fine-grained perms */ 115 const char *ext_name; /* extended request name */ 116 u_int type; /* packet type, for non extended packets */ 117 void (*handler)(u_int32_t); 118 int does_write; /* if nonzero, banned for readonly mode */ 119}; 120 121struct sftp_handler handlers[] = { 122 /* NB. SSH2_FXP_OPEN does the readonly check in the handler itself */ 123 { "open", NULL, SSH2_FXP_OPEN, process_open, 0 }, 124 { "close", NULL, SSH2_FXP_CLOSE, process_close, 0 }, 125 { "read", NULL, SSH2_FXP_READ, process_read, 0 }, 126 { "write", NULL, SSH2_FXP_WRITE, process_write, 1 }, 127 { "lstat", NULL, SSH2_FXP_LSTAT, process_lstat, 0 }, 128 { "fstat", NULL, SSH2_FXP_FSTAT, process_fstat, 0 }, 129 { "setstat", NULL, SSH2_FXP_SETSTAT, process_setstat, 1 }, 130 { "fsetstat", NULL, SSH2_FXP_FSETSTAT, process_fsetstat, 1 }, 131 { "opendir", NULL, SSH2_FXP_OPENDIR, process_opendir, 0 }, 132 { "readdir", NULL, SSH2_FXP_READDIR, process_readdir, 0 }, 133 { "remove", NULL, SSH2_FXP_REMOVE, process_remove, 1 }, 134 { "mkdir", NULL, SSH2_FXP_MKDIR, process_mkdir, 1 }, 135 { "rmdir", NULL, SSH2_FXP_RMDIR, process_rmdir, 1 }, 136 { "realpath", NULL, SSH2_FXP_REALPATH, process_realpath, 0 }, 137 { "stat", NULL, SSH2_FXP_STAT, process_stat, 0 }, 138 { "rename", NULL, SSH2_FXP_RENAME, process_rename, 1 }, 139 { "readlink", NULL, SSH2_FXP_READLINK, process_readlink, 0 }, 140 { "symlink", NULL, SSH2_FXP_SYMLINK, process_symlink, 1 }, 141 { NULL, NULL, 0, NULL, 0 } 142}; 143 144/* SSH2_FXP_EXTENDED submessages */ 145struct sftp_handler extended_handlers[] = { 146 { "posix-rename", "posix-rename@openssh.com", 0, 147 process_extended_posix_rename, 1 }, 148 { "statvfs", "statvfs@openssh.com", 0, process_extended_statvfs, 0 }, 149 { "fstatvfs", "fstatvfs@openssh.com", 0, process_extended_fstatvfs, 0 }, 150 { "hardlink", "hardlink@openssh.com", 0, process_extended_hardlink, 1 }, 151 { "fsync", "fsync@openssh.com", 0, process_extended_fsync, 1 }, 152 { NULL, NULL, 0, NULL, 0 } 153}; 154 155static int 156request_permitted(struct sftp_handler *h) 157{ 158 char *result; 159 160 if (readonly && h->does_write) { 161 verbose("Refusing %s request in read-only mode", h->name); 162 return 0; 163 } 164 if (request_blacklist != NULL && 165 ((result = match_list(h->name, request_blacklist, NULL))) != NULL) { 166 free(result); 167 verbose("Refusing blacklisted %s request", h->name); 168 return 0; 169 } 170 if (request_whitelist != NULL && 171 ((result = match_list(h->name, request_whitelist, NULL))) != NULL) { 172 free(result); 173 debug2("Permitting whitelisted %s request", h->name); 174 return 1; 175 } 176 if (request_whitelist != NULL) { 177 verbose("Refusing non-whitelisted %s request", h->name); 178 return 0; 179 } 180 return 1; 181} 182 183static int 184errno_to_portable(int unixerrno) 185{ 186 int ret = 0; 187 188 switch (unixerrno) { 189 case 0: 190 ret = SSH2_FX_OK; 191 break; 192 case ENOENT: 193 case ENOTDIR: 194 case EBADF: 195 case ELOOP: 196 ret = SSH2_FX_NO_SUCH_FILE; 197 break; 198 case EPERM: 199 case EACCES: 200 case EFAULT: 201 ret = SSH2_FX_PERMISSION_DENIED; 202 break; 203 case ENAMETOOLONG: 204 case EINVAL: 205 ret = SSH2_FX_BAD_MESSAGE; 206 break; 207 case ENOSYS: 208 ret = SSH2_FX_OP_UNSUPPORTED; 209 break; 210 default: 211 ret = SSH2_FX_FAILURE; 212 break; 213 } 214 return ret; 215} 216 217static int 218flags_from_portable(int pflags) 219{ 220 int flags = 0; 221 222 if ((pflags & SSH2_FXF_READ) && 223 (pflags & SSH2_FXF_WRITE)) { 224 flags = O_RDWR; 225 } else if (pflags & SSH2_FXF_READ) { 226 flags = O_RDONLY; 227 } else if (pflags & SSH2_FXF_WRITE) { 228 flags = O_WRONLY; 229 } 230 if (pflags & SSH2_FXF_APPEND) 231 flags |= O_APPEND; 232 if (pflags & SSH2_FXF_CREAT) 233 flags |= O_CREAT; 234 if (pflags & SSH2_FXF_TRUNC) 235 flags |= O_TRUNC; 236 if (pflags & SSH2_FXF_EXCL) 237 flags |= O_EXCL; 238 return flags; 239} 240 241static const char * 242string_from_portable(int pflags) 243{ 244 static char ret[128]; 245 246 *ret = '\0'; 247 248#define PAPPEND(str) { \ 249 if (*ret != '\0') \ 250 strlcat(ret, ",", sizeof(ret)); \ 251 strlcat(ret, str, sizeof(ret)); \ 252 } 253 254 if (pflags & SSH2_FXF_READ) 255 PAPPEND("READ") 256 if (pflags & SSH2_FXF_WRITE) 257 PAPPEND("WRITE") 258 if (pflags & SSH2_FXF_APPEND) 259 PAPPEND("APPEND") 260 if (pflags & SSH2_FXF_CREAT) 261 PAPPEND("CREATE") 262 if (pflags & SSH2_FXF_TRUNC) 263 PAPPEND("TRUNCATE") 264 if (pflags & SSH2_FXF_EXCL) 265 PAPPEND("EXCL") 266 267 return ret; 268} 269 270/* handle handles */ 271 272typedef struct Handle Handle; 273struct Handle { 274 int use; 275 DIR *dirp; 276 int fd; 277 int flags; 278 char *name; 279 u_int64_t bytes_read, bytes_write; 280 int next_unused; 281}; 282 283enum { 284 HANDLE_UNUSED, 285 HANDLE_DIR, 286 HANDLE_FILE 287}; 288 289Handle *handles = NULL; 290u_int num_handles = 0; 291int first_unused_handle = -1; 292 293static void handle_unused(int i) 294{ 295 handles[i].use = HANDLE_UNUSED; 296 handles[i].next_unused = first_unused_handle; 297 first_unused_handle = i; 298} 299 300static int 301handle_new(int use, const char *name, int fd, int flags, DIR *dirp) 302{ 303 int i; 304 305 if (first_unused_handle == -1) { 306 if (num_handles + 1 <= num_handles) 307 return -1; 308 num_handles++; 309 handles = xreallocarray(handles, num_handles, sizeof(Handle)); 310 handle_unused(num_handles - 1); 311 } 312 313 i = first_unused_handle; 314 first_unused_handle = handles[i].next_unused; 315 316 handles[i].use = use; 317 handles[i].dirp = dirp; 318 handles[i].fd = fd; 319 handles[i].flags = flags; 320 handles[i].name = xstrdup(name); 321 handles[i].bytes_read = handles[i].bytes_write = 0; 322 323 return i; 324} 325 326static int 327handle_is_ok(int i, int type) 328{ 329 return i >= 0 && (u_int)i < num_handles && handles[i].use == type; 330} 331 332static int 333handle_to_string(int handle, u_char **stringp, int *hlenp) 334{ 335 if (stringp == NULL || hlenp == NULL) 336 return -1; 337 *stringp = xmalloc(sizeof(int32_t)); 338 put_u32(*stringp, handle); 339 *hlenp = sizeof(int32_t); 340 return 0; 341} 342 343static int 344handle_from_string(const u_char *handle, u_int hlen) 345{ 346 int val; 347 348 if (hlen != sizeof(int32_t)) 349 return -1; 350 val = get_u32(handle); 351 if (handle_is_ok(val, HANDLE_FILE) || 352 handle_is_ok(val, HANDLE_DIR)) 353 return val; 354 return -1; 355} 356 357static char * 358handle_to_name(int handle) 359{ 360 if (handle_is_ok(handle, HANDLE_DIR)|| 361 handle_is_ok(handle, HANDLE_FILE)) 362 return handles[handle].name; 363 return NULL; 364} 365 366static DIR * 367handle_to_dir(int handle) 368{ 369 if (handle_is_ok(handle, HANDLE_DIR)) 370 return handles[handle].dirp; 371 return NULL; 372} 373 374static int 375handle_to_fd(int handle) 376{ 377 if (handle_is_ok(handle, HANDLE_FILE)) 378 return handles[handle].fd; 379 return -1; 380} 381 382static int 383handle_to_flags(int handle) 384{ 385 if (handle_is_ok(handle, HANDLE_FILE)) 386 return handles[handle].flags; 387 return 0; 388} 389 390static void 391handle_update_read(int handle, ssize_t bytes) 392{ 393 if (handle_is_ok(handle, HANDLE_FILE) && bytes > 0) 394 handles[handle].bytes_read += bytes; 395} 396 397static void 398handle_update_write(int handle, ssize_t bytes) 399{ 400 if (handle_is_ok(handle, HANDLE_FILE) && bytes > 0) 401 handles[handle].bytes_write += bytes; 402} 403 404static u_int64_t 405handle_bytes_read(int handle) 406{ 407 if (handle_is_ok(handle, HANDLE_FILE)) 408 return (handles[handle].bytes_read); 409 return 0; 410} 411 412static u_int64_t 413handle_bytes_write(int handle) 414{ 415 if (handle_is_ok(handle, HANDLE_FILE)) 416 return (handles[handle].bytes_write); 417 return 0; 418} 419 420static int 421handle_close(int handle) 422{ 423 int ret = -1; 424 425 if (handle_is_ok(handle, HANDLE_FILE)) { 426 ret = close(handles[handle].fd); 427 free(handles[handle].name); 428 handle_unused(handle); 429 } else if (handle_is_ok(handle, HANDLE_DIR)) { 430 ret = closedir(handles[handle].dirp); 431 free(handles[handle].name); 432 handle_unused(handle); 433 } else { 434 errno = ENOENT; 435 } 436 return ret; 437} 438 439static void 440handle_log_close(int handle, char *emsg) 441{ 442 if (handle_is_ok(handle, HANDLE_FILE)) { 443 logit("%s%sclose \"%s\" bytes read %llu written %llu", 444 emsg == NULL ? "" : emsg, emsg == NULL ? "" : " ", 445 handle_to_name(handle), 446 (unsigned long long)handle_bytes_read(handle), 447 (unsigned long long)handle_bytes_write(handle)); 448 } else { 449 logit("%s%sclosedir \"%s\"", 450 emsg == NULL ? "" : emsg, emsg == NULL ? "" : " ", 451 handle_to_name(handle)); 452 } 453} 454 455static void 456handle_log_exit(void) 457{ 458 u_int i; 459 460 for (i = 0; i < num_handles; i++) 461 if (handles[i].use != HANDLE_UNUSED) 462 handle_log_close(i, "forced"); 463} 464 465static int 466get_handle(struct sshbuf *queue, int *hp) 467{ 468 u_char *handle; 469 int r; 470 size_t hlen; 471 472 *hp = -1; 473 if ((r = sshbuf_get_string(queue, &handle, &hlen)) != 0) 474 return r; 475 if (hlen < 256) 476 *hp = handle_from_string(handle, hlen); 477 free(handle); 478 return 0; 479} 480 481/* send replies */ 482 483static void 484send_msg(struct sshbuf *m) 485{ 486 int r; 487 488 if ((r = sshbuf_put_stringb(oqueue, m)) != 0) 489 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 490 sshbuf_reset(m); 491} 492 493static const char * 494status_to_message(u_int32_t status) 495{ 496 const char *status_messages[] = { 497 "Success", /* SSH_FX_OK */ 498 "End of file", /* SSH_FX_EOF */ 499 "No such file", /* SSH_FX_NO_SUCH_FILE */ 500 "Permission denied", /* SSH_FX_PERMISSION_DENIED */ 501 "Failure", /* SSH_FX_FAILURE */ 502 "Bad message", /* SSH_FX_BAD_MESSAGE */ 503 "No connection", /* SSH_FX_NO_CONNECTION */ 504 "Connection lost", /* SSH_FX_CONNECTION_LOST */ 505 "Operation unsupported", /* SSH_FX_OP_UNSUPPORTED */ 506 "Unknown error" /* Others */ 507 }; 508 return (status_messages[MIN(status,SSH2_FX_MAX)]); 509} 510 511static void 512send_status(u_int32_t id, u_int32_t status) 513{ 514 struct sshbuf *msg; 515 int r; 516 517 debug3("request %u: sent status %u", id, status); 518 if (log_level > SYSLOG_LEVEL_VERBOSE || 519 (status != SSH2_FX_OK && status != SSH2_FX_EOF)) 520 logit("sent status %s", status_to_message(status)); 521 if ((msg = sshbuf_new()) == NULL) 522 fatal("%s: sshbuf_new failed", __func__); 523 if ((r = sshbuf_put_u8(msg, SSH2_FXP_STATUS)) != 0 || 524 (r = sshbuf_put_u32(msg, id)) != 0 || 525 (r = sshbuf_put_u32(msg, status)) != 0) 526 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 527 if (version >= 3) { 528 if ((r = sshbuf_put_cstring(msg, 529 status_to_message(status))) != 0 || 530 (r = sshbuf_put_cstring(msg, "")) != 0) 531 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 532 } 533 send_msg(msg); 534 sshbuf_free(msg); 535} 536static void 537send_data_or_handle(char type, u_int32_t id, const u_char *data, int dlen) 538{ 539 struct sshbuf *msg; 540 int r; 541 542 if ((msg = sshbuf_new()) == NULL) 543 fatal("%s: sshbuf_new failed", __func__); 544 if ((r = sshbuf_put_u8(msg, type)) != 0 || 545 (r = sshbuf_put_u32(msg, id)) != 0 || 546 (r = sshbuf_put_string(msg, data, dlen)) != 0) 547 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 548 send_msg(msg); 549 sshbuf_free(msg); 550} 551 552static void 553send_data(u_int32_t id, const u_char *data, int dlen) 554{ 555 debug("request %u: sent data len %d", id, dlen); 556 send_data_or_handle(SSH2_FXP_DATA, id, data, dlen); 557} 558 559static void 560send_handle(u_int32_t id, int handle) 561{ 562 u_char *string; 563 int hlen; 564 565 handle_to_string(handle, &string, &hlen); 566 debug("request %u: sent handle handle %d", id, handle); 567 send_data_or_handle(SSH2_FXP_HANDLE, id, string, hlen); 568 free(string); 569} 570 571static void 572send_names(u_int32_t id, int count, const Stat *stats) 573{ 574 struct sshbuf *msg; 575 int i, r; 576 577 if ((msg = sshbuf_new()) == NULL) 578 fatal("%s: sshbuf_new failed", __func__); 579 if ((r = sshbuf_put_u8(msg, SSH2_FXP_NAME)) != 0 || 580 (r = sshbuf_put_u32(msg, id)) != 0 || 581 (r = sshbuf_put_u32(msg, count)) != 0) 582 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 583 debug("request %u: sent names count %d", id, count); 584 for (i = 0; i < count; i++) { 585 if ((r = sshbuf_put_cstring(msg, stats[i].name)) != 0 || 586 (r = sshbuf_put_cstring(msg, stats[i].long_name)) != 0 || 587 (r = encode_attrib(msg, &stats[i].attrib)) != 0) 588 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 589 } 590 send_msg(msg); 591 sshbuf_free(msg); 592} 593 594static void 595send_attrib(u_int32_t id, const Attrib *a) 596{ 597 struct sshbuf *msg; 598 int r; 599 600 debug("request %u: sent attrib have 0x%x", id, a->flags); 601 if ((msg = sshbuf_new()) == NULL) 602 fatal("%s: sshbuf_new failed", __func__); 603 if ((r = sshbuf_put_u8(msg, SSH2_FXP_ATTRS)) != 0 || 604 (r = sshbuf_put_u32(msg, id)) != 0 || 605 (r = encode_attrib(msg, a)) != 0) 606 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 607 send_msg(msg); 608 sshbuf_free(msg); 609} 610 611static void 612send_statvfs(u_int32_t id, struct statvfs *st) 613{ 614 struct sshbuf *msg; 615 u_int64_t flag; 616 int r; 617 618 flag = (st->f_flag & ST_RDONLY) ? SSH2_FXE_STATVFS_ST_RDONLY : 0; 619 flag |= (st->f_flag & ST_NOSUID) ? SSH2_FXE_STATVFS_ST_NOSUID : 0; 620 621 if ((msg = sshbuf_new()) == NULL) 622 fatal("%s: sshbuf_new failed", __func__); 623 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED_REPLY)) != 0 || 624 (r = sshbuf_put_u32(msg, id)) != 0 || 625 (r = sshbuf_put_u64(msg, st->f_bsize)) != 0 || 626 (r = sshbuf_put_u64(msg, st->f_frsize)) != 0 || 627 (r = sshbuf_put_u64(msg, st->f_blocks)) != 0 || 628 (r = sshbuf_put_u64(msg, st->f_bfree)) != 0 || 629 (r = sshbuf_put_u64(msg, st->f_bavail)) != 0 || 630 (r = sshbuf_put_u64(msg, st->f_files)) != 0 || 631 (r = sshbuf_put_u64(msg, st->f_ffree)) != 0 || 632 (r = sshbuf_put_u64(msg, st->f_favail)) != 0 || 633 (r = sshbuf_put_u64(msg, FSID_TO_ULONG(st->f_fsid))) != 0 || 634 (r = sshbuf_put_u64(msg, flag)) != 0 || 635 (r = sshbuf_put_u64(msg, st->f_namemax)) != 0) 636 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 637 send_msg(msg); 638 sshbuf_free(msg); 639} 640 641/* parse incoming */ 642 643static void 644process_init(void) 645{ 646 struct sshbuf *msg; 647 int r; 648 649 if ((r = sshbuf_get_u32(iqueue, &version)) != 0) 650 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 651 verbose("received client version %u", version); 652 if ((msg = sshbuf_new()) == NULL) 653 fatal("%s: sshbuf_new failed", __func__); 654 if ((r = sshbuf_put_u8(msg, SSH2_FXP_VERSION)) != 0 || 655 (r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0 || 656 /* POSIX rename extension */ 657 (r = sshbuf_put_cstring(msg, "posix-rename@openssh.com")) != 0 || 658 (r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */ 659 /* statvfs extension */ 660 (r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 || 661 (r = sshbuf_put_cstring(msg, "2")) != 0 || /* version */ 662 /* fstatvfs extension */ 663 (r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 || 664 (r = sshbuf_put_cstring(msg, "2")) != 0 || /* version */ 665 /* hardlink extension */ 666 (r = sshbuf_put_cstring(msg, "hardlink@openssh.com")) != 0 || 667 (r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */ 668 /* fsync extension */ 669 (r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 || 670 (r = sshbuf_put_cstring(msg, "1")) != 0) /* version */ 671 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 672 send_msg(msg); 673 sshbuf_free(msg); 674} 675 676static void 677process_open(u_int32_t id) 678{ 679 u_int32_t pflags; 680 Attrib a; 681 char *name; 682 int r, handle, fd, flags, mode, status = SSH2_FX_FAILURE; 683 684 if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || 685 (r = sshbuf_get_u32(iqueue, &pflags)) != 0 || /* portable flags */ 686 (r = decode_attrib(iqueue, &a)) != 0) 687 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 688 689 debug3("request %u: open flags %d", id, pflags); 690 flags = flags_from_portable(pflags); 691 mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a.perm : 0666; 692 logit("open \"%s\" flags %s mode 0%o", 693 name, string_from_portable(pflags), mode); 694 if (readonly && 695 ((flags & O_ACCMODE) == O_WRONLY || 696 (flags & O_ACCMODE) == O_RDWR)) { 697 verbose("Refusing open request in read-only mode"); 698 status = SSH2_FX_PERMISSION_DENIED; 699 } else { 700 fd = open(name, flags, mode); 701 if (fd < 0) { 702 status = errno_to_portable(errno); 703 } else { 704 handle = handle_new(HANDLE_FILE, name, fd, flags, NULL); 705 if (handle < 0) { 706 close(fd); 707 } else { 708 send_handle(id, handle); 709 status = SSH2_FX_OK; 710 } 711 } 712 } 713 if (status != SSH2_FX_OK) 714 send_status(id, status); 715 free(name); 716} 717 718static void 719process_close(u_int32_t id) 720{ 721 int r, handle, ret, status = SSH2_FX_FAILURE; 722 723 if ((r = get_handle(iqueue, &handle)) != 0) 724 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 725 726 debug3("request %u: close handle %u", id, handle); 727 handle_log_close(handle, NULL); 728 ret = handle_close(handle); 729 status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 730 send_status(id, status); 731} 732 733static void 734process_read(u_int32_t id) 735{ 736 u_char buf[64*1024]; 737 u_int32_t len; 738 int r, handle, fd, ret, status = SSH2_FX_FAILURE; 739 u_int64_t off; 740 741 if ((r = get_handle(iqueue, &handle)) != 0 || 742 (r = sshbuf_get_u64(iqueue, &off)) != 0 || 743 (r = sshbuf_get_u32(iqueue, &len)) != 0) 744 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 745 746 debug("request %u: read \"%s\" (handle %d) off %llu len %d", 747 id, handle_to_name(handle), handle, (unsigned long long)off, len); 748 if (len > sizeof buf) { 749 len = sizeof buf; 750 debug2("read change len %d", len); 751 } 752 fd = handle_to_fd(handle); 753 if (fd >= 0) { 754 if (lseek(fd, off, SEEK_SET) < 0) { 755 error("process_read: seek failed"); 756 status = errno_to_portable(errno); 757 } else { 758 ret = read(fd, buf, len); 759 if (ret < 0) { 760 status = errno_to_portable(errno); 761 } else if (ret == 0) { 762 status = SSH2_FX_EOF; 763 } else { 764 send_data(id, buf, ret); 765 status = SSH2_FX_OK; 766 handle_update_read(handle, ret); 767 } 768 } 769 } 770 if (status != SSH2_FX_OK) 771 send_status(id, status); 772} 773 774static void 775process_write(u_int32_t id) 776{ 777 u_int64_t off; 778 size_t len; 779 int r, handle, fd, ret, status; 780 u_char *data; 781 782 if ((r = get_handle(iqueue, &handle)) != 0 || 783 (r = sshbuf_get_u64(iqueue, &off)) != 0 || 784 (r = sshbuf_get_string(iqueue, &data, &len)) != 0) 785 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 786 787 debug("request %u: write \"%s\" (handle %d) off %llu len %zu", 788 id, handle_to_name(handle), handle, (unsigned long long)off, len); 789 fd = handle_to_fd(handle); 790 791 if (fd < 0) 792 status = SSH2_FX_FAILURE; 793 else { 794 if (!(handle_to_flags(handle) & O_APPEND) && 795 lseek(fd, off, SEEK_SET) < 0) { 796 status = errno_to_portable(errno); 797 error("process_write: seek failed"); 798 } else { 799/* XXX ATOMICIO ? */ 800 ret = write(fd, data, len); 801 if (ret < 0) { 802 error("process_write: write failed"); 803 status = errno_to_portable(errno); 804 } else if ((size_t)ret == len) { 805 status = SSH2_FX_OK; 806 handle_update_write(handle, ret); 807 } else { 808 debug2("nothing at all written"); 809 status = SSH2_FX_FAILURE; 810 } 811 } 812 } 813 send_status(id, status); 814 free(data); 815} 816 817static void 818process_do_stat(u_int32_t id, int do_lstat) 819{ 820 Attrib a; 821 struct stat st; 822 char *name; 823 int r, status = SSH2_FX_FAILURE; 824 825 if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0) 826 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 827 828 debug3("request %u: %sstat", id, do_lstat ? "l" : ""); 829 verbose("%sstat name \"%s\"", do_lstat ? "l" : "", name); 830 r = do_lstat ? lstat(name, &st) : stat(name, &st); 831 if (r < 0) { 832 status = errno_to_portable(errno); 833 } else { 834 stat_to_attrib(&st, &a); 835 send_attrib(id, &a); 836 status = SSH2_FX_OK; 837 } 838 if (status != SSH2_FX_OK) 839 send_status(id, status); 840 free(name); 841} 842 843static void 844process_stat(u_int32_t id) 845{ 846 process_do_stat(id, 0); 847} 848 849static void 850process_lstat(u_int32_t id) 851{ 852 process_do_stat(id, 1); 853} 854 855static void 856process_fstat(u_int32_t id) 857{ 858 Attrib a; 859 struct stat st; 860 int fd, r, handle, status = SSH2_FX_FAILURE; 861 862 if ((r = get_handle(iqueue, &handle)) != 0) 863 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 864 debug("request %u: fstat \"%s\" (handle %u)", 865 id, handle_to_name(handle), handle); 866 fd = handle_to_fd(handle); 867 if (fd >= 0) { 868 r = fstat(fd, &st); 869 if (r < 0) { 870 status = errno_to_portable(errno); 871 } else { 872 stat_to_attrib(&st, &a); 873 send_attrib(id, &a); 874 status = SSH2_FX_OK; 875 } 876 } 877 if (status != SSH2_FX_OK) 878 send_status(id, status); 879} 880 881static struct timeval * 882attrib_to_tv(const Attrib *a) 883{ 884 static struct timeval tv[2]; 885 886 tv[0].tv_sec = a->atime; 887 tv[0].tv_usec = 0; 888 tv[1].tv_sec = a->mtime; 889 tv[1].tv_usec = 0; 890 return tv; 891} 892 893static void 894process_setstat(u_int32_t id) 895{ 896 Attrib a; 897 char *name; 898 int r, status = SSH2_FX_OK; 899 900 if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || 901 (r = decode_attrib(iqueue, &a)) != 0) 902 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 903 904 debug("request %u: setstat name \"%s\"", id, name); 905 if (a.flags & SSH2_FILEXFER_ATTR_SIZE) { 906 logit("set \"%s\" size %llu", 907 name, (unsigned long long)a.size); 908 r = truncate(name, a.size); 909 if (r == -1) 910 status = errno_to_portable(errno); 911 } 912 if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { 913 logit("set \"%s\" mode %04o", name, a.perm); 914 r = chmod(name, a.perm & 07777); 915 if (r == -1) 916 status = errno_to_portable(errno); 917 } 918 if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) { 919 char buf[64]; 920 time_t t = a.mtime; 921 922 strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S", 923 localtime(&t)); 924 logit("set \"%s\" modtime %s", name, buf); 925 r = utimes(name, attrib_to_tv(&a)); 926 if (r == -1) 927 status = errno_to_portable(errno); 928 } 929 if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) { 930 logit("set \"%s\" owner %lu group %lu", name, 931 (u_long)a.uid, (u_long)a.gid); 932 r = chown(name, a.uid, a.gid); 933 if (r == -1) 934 status = errno_to_portable(errno); 935 } 936 send_status(id, status); 937 free(name); 938} 939 940static void 941process_fsetstat(u_int32_t id) 942{ 943 Attrib a; 944 int handle, fd, r; 945 int status = SSH2_FX_OK; 946 947 if ((r = get_handle(iqueue, &handle)) != 0 || 948 (r = decode_attrib(iqueue, &a)) != 0) 949 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 950 951 debug("request %u: fsetstat handle %d", id, handle); 952 fd = handle_to_fd(handle); 953 if (fd < 0) 954 status = SSH2_FX_FAILURE; 955 else { 956 char *name = handle_to_name(handle); 957 958 if (a.flags & SSH2_FILEXFER_ATTR_SIZE) { 959 logit("set \"%s\" size %llu", 960 name, (unsigned long long)a.size); 961 r = ftruncate(fd, a.size); 962 if (r == -1) 963 status = errno_to_portable(errno); 964 } 965 if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { 966 logit("set \"%s\" mode %04o", name, a.perm); 967#ifdef HAVE_FCHMOD 968 r = fchmod(fd, a.perm & 07777); 969#else 970 r = chmod(name, a.perm & 07777); 971#endif 972 if (r == -1) 973 status = errno_to_portable(errno); 974 } 975 if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) { 976 char buf[64]; 977 time_t t = a.mtime; 978 979 strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S", 980 localtime(&t)); 981 logit("set \"%s\" modtime %s", name, buf); 982#ifdef HAVE_FUTIMES 983 r = futimes(fd, attrib_to_tv(&a)); 984#else 985 r = utimes(name, attrib_to_tv(&a)); 986#endif 987 if (r == -1) 988 status = errno_to_portable(errno); 989 } 990 if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) { 991 logit("set \"%s\" owner %lu group %lu", name, 992 (u_long)a.uid, (u_long)a.gid); 993#ifdef HAVE_FCHOWN 994 r = fchown(fd, a.uid, a.gid); 995#else 996 r = chown(name, a.uid, a.gid); 997#endif 998 if (r == -1) 999 status = errno_to_portable(errno); 1000 } 1001 } 1002 send_status(id, status); 1003} 1004 1005static void 1006process_opendir(u_int32_t id) 1007{ 1008 DIR *dirp = NULL; 1009 char *path; 1010 int r, handle, status = SSH2_FX_FAILURE; 1011 1012 if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) 1013 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1014 1015 debug3("request %u: opendir", id); 1016 logit("opendir \"%s\"", path); 1017 dirp = opendir(path); 1018 if (dirp == NULL) { 1019 status = errno_to_portable(errno); 1020 } else { 1021 handle = handle_new(HANDLE_DIR, path, 0, 0, dirp); 1022 if (handle < 0) { 1023 closedir(dirp); 1024 } else { 1025 send_handle(id, handle); 1026 status = SSH2_FX_OK; 1027 } 1028 1029 } 1030 if (status != SSH2_FX_OK) 1031 send_status(id, status); 1032 free(path); 1033} 1034 1035static void 1036process_readdir(u_int32_t id) 1037{ 1038 DIR *dirp; 1039 struct dirent *dp; 1040 char *path; 1041 int r, handle; 1042 1043 if ((r = get_handle(iqueue, &handle)) != 0) 1044 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1045 1046 debug("request %u: readdir \"%s\" (handle %d)", id, 1047 handle_to_name(handle), handle); 1048 dirp = handle_to_dir(handle); 1049 path = handle_to_name(handle); 1050 if (dirp == NULL || path == NULL) { 1051 send_status(id, SSH2_FX_FAILURE); 1052 } else { 1053 struct stat st; 1054 char pathname[PATH_MAX]; 1055 Stat *stats; 1056 int nstats = 10, count = 0, i; 1057 1058 stats = xcalloc(nstats, sizeof(Stat)); 1059 while ((dp = readdir(dirp)) != NULL) { 1060 if (count >= nstats) { 1061 nstats *= 2; 1062 stats = xreallocarray(stats, nstats, sizeof(Stat)); 1063 } 1064/* XXX OVERFLOW ? */ 1065 snprintf(pathname, sizeof pathname, "%s%s%s", path, 1066 strcmp(path, "/") ? "/" : "", dp->d_name); 1067 if (lstat(pathname, &st) < 0) 1068 continue; 1069 stat_to_attrib(&st, &(stats[count].attrib)); 1070 stats[count].name = xstrdup(dp->d_name); 1071 stats[count].long_name = ls_file(dp->d_name, &st, 0, 0); 1072 count++; 1073 /* send up to 100 entries in one message */ 1074 /* XXX check packet size instead */ 1075 if (count == 100) 1076 break; 1077 } 1078 if (count > 0) { 1079 send_names(id, count, stats); 1080 for (i = 0; i < count; i++) { 1081 free(stats[i].name); 1082 free(stats[i].long_name); 1083 } 1084 } else { 1085 send_status(id, SSH2_FX_EOF); 1086 } 1087 free(stats); 1088 } 1089} 1090 1091static void 1092process_remove(u_int32_t id) 1093{ 1094 char *name; 1095 int r, status = SSH2_FX_FAILURE; 1096 1097 if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0) 1098 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1099 1100 debug3("request %u: remove", id); 1101 logit("remove name \"%s\"", name); 1102 r = unlink(name); 1103 status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 1104 send_status(id, status); 1105 free(name); 1106} 1107 1108static void 1109process_mkdir(u_int32_t id) 1110{ 1111 Attrib a; 1112 char *name; 1113 int r, mode, status = SSH2_FX_FAILURE; 1114 1115 if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || 1116 (r = decode_attrib(iqueue, &a)) != 0) 1117 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1118 1119 mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? 1120 a.perm & 07777 : 0777; 1121 debug3("request %u: mkdir", id); 1122 logit("mkdir name \"%s\" mode 0%o", name, mode); 1123 r = mkdir(name, mode); 1124 status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 1125 send_status(id, status); 1126 free(name); 1127} 1128 1129static void 1130process_rmdir(u_int32_t id) 1131{ 1132 char *name; 1133 int r, status; 1134 1135 if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0) 1136 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1137 1138 debug3("request %u: rmdir", id); 1139 logit("rmdir name \"%s\"", name); 1140 r = rmdir(name); 1141 status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 1142 send_status(id, status); 1143 free(name); 1144} 1145 1146static void 1147process_realpath(u_int32_t id) 1148{ 1149 char resolvedname[PATH_MAX]; 1150 char *path; 1151 int r; 1152 1153 if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) 1154 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1155 1156 if (path[0] == '\0') { 1157 free(path); 1158 path = xstrdup("."); 1159 } 1160 debug3("request %u: realpath", id); 1161 verbose("realpath \"%s\"", path); 1162 if (realpath(path, resolvedname) == NULL) { 1163 send_status(id, errno_to_portable(errno)); 1164 } else { 1165 Stat s; 1166 attrib_clear(&s.attrib); 1167 s.name = s.long_name = resolvedname; 1168 send_names(id, 1, &s); 1169 } 1170 free(path); 1171} 1172 1173static void 1174process_rename(u_int32_t id) 1175{ 1176 char *oldpath, *newpath; 1177 int r, status; 1178 struct stat sb; 1179 1180 if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 || 1181 (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0) 1182 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1183 1184 debug3("request %u: rename", id); 1185 logit("rename old \"%s\" new \"%s\"", oldpath, newpath); 1186 status = SSH2_FX_FAILURE; 1187 if (lstat(oldpath, &sb) == -1) 1188 status = errno_to_portable(errno); 1189 else if (S_ISREG(sb.st_mode)) { 1190 /* Race-free rename of regular files */ 1191 if (link(oldpath, newpath) == -1) { 1192 if (errno == EOPNOTSUPP || errno == ENOSYS 1193#ifdef EXDEV 1194 || errno == EXDEV 1195#endif 1196#ifdef LINK_OPNOTSUPP_ERRNO 1197 || errno == LINK_OPNOTSUPP_ERRNO 1198#endif 1199 ) { 1200 struct stat st; 1201 1202 /* 1203 * fs doesn't support links, so fall back to 1204 * stat+rename. This is racy. 1205 */ 1206 if (stat(newpath, &st) == -1) { 1207 if (rename(oldpath, newpath) == -1) 1208 status = 1209 errno_to_portable(errno); 1210 else 1211 status = SSH2_FX_OK; 1212 } 1213 } else { 1214 status = errno_to_portable(errno); 1215 } 1216 } else if (unlink(oldpath) == -1) { 1217 status = errno_to_portable(errno); 1218 /* clean spare link */ 1219 unlink(newpath); 1220 } else 1221 status = SSH2_FX_OK; 1222 } else if (stat(newpath, &sb) == -1) { 1223 if (rename(oldpath, newpath) == -1) 1224 status = errno_to_portable(errno); 1225 else 1226 status = SSH2_FX_OK; 1227 } 1228 send_status(id, status); 1229 free(oldpath); 1230 free(newpath); 1231} 1232 1233static void 1234process_readlink(u_int32_t id) 1235{ 1236 int r, len; 1237 char buf[PATH_MAX]; 1238 char *path; 1239 1240 if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) 1241 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1242 1243 debug3("request %u: readlink", id); 1244 verbose("readlink \"%s\"", path); 1245 if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1) 1246 send_status(id, errno_to_portable(errno)); 1247 else { 1248 Stat s; 1249 1250 buf[len] = '\0'; 1251 attrib_clear(&s.attrib); 1252 s.name = s.long_name = buf; 1253 send_names(id, 1, &s); 1254 } 1255 free(path); 1256} 1257 1258static void 1259process_symlink(u_int32_t id) 1260{ 1261 char *oldpath, *newpath; 1262 int r, status; 1263 1264 if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 || 1265 (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0) 1266 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1267 1268 debug3("request %u: symlink", id); 1269 logit("symlink old \"%s\" new \"%s\"", oldpath, newpath); 1270 /* this will fail if 'newpath' exists */ 1271 r = symlink(oldpath, newpath); 1272 status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 1273 send_status(id, status); 1274 free(oldpath); 1275 free(newpath); 1276} 1277 1278static void 1279process_extended_posix_rename(u_int32_t id) 1280{ 1281 char *oldpath, *newpath; 1282 int r, status; 1283 1284 if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 || 1285 (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0) 1286 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1287 1288 debug3("request %u: posix-rename", id); 1289 logit("posix-rename old \"%s\" new \"%s\"", oldpath, newpath); 1290 r = rename(oldpath, newpath); 1291 status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 1292 send_status(id, status); 1293 free(oldpath); 1294 free(newpath); 1295} 1296 1297static void 1298process_extended_statvfs(u_int32_t id) 1299{ 1300 char *path; 1301 struct statvfs st; 1302 int r; 1303 1304 if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) 1305 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1306 debug3("request %u: statvfs", id); 1307 logit("statvfs \"%s\"", path); 1308 1309 if (statvfs(path, &st) != 0) 1310 send_status(id, errno_to_portable(errno)); 1311 else 1312 send_statvfs(id, &st); 1313 free(path); 1314} 1315 1316static void 1317process_extended_fstatvfs(u_int32_t id) 1318{ 1319 int r, handle, fd; 1320 struct statvfs st; 1321 1322 if ((r = get_handle(iqueue, &handle)) != 0) 1323 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1324 debug("request %u: fstatvfs \"%s\" (handle %u)", 1325 id, handle_to_name(handle), handle); 1326 if ((fd = handle_to_fd(handle)) < 0) { 1327 send_status(id, SSH2_FX_FAILURE); 1328 return; 1329 } 1330 if (fstatvfs(fd, &st) != 0) 1331 send_status(id, errno_to_portable(errno)); 1332 else 1333 send_statvfs(id, &st); 1334} 1335 1336static void 1337process_extended_hardlink(u_int32_t id) 1338{ 1339 char *oldpath, *newpath; 1340 int r, status; 1341 1342 if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 || 1343 (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0) 1344 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1345 1346 debug3("request %u: hardlink", id); 1347 logit("hardlink old \"%s\" new \"%s\"", oldpath, newpath); 1348 r = link(oldpath, newpath); 1349 status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 1350 send_status(id, status); 1351 free(oldpath); 1352 free(newpath); 1353} 1354 1355static void 1356process_extended_fsync(u_int32_t id) 1357{ 1358 int handle, fd, r, status = SSH2_FX_OP_UNSUPPORTED; 1359 1360 if ((r = get_handle(iqueue, &handle)) != 0) 1361 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1362 debug3("request %u: fsync (handle %u)", id, handle); 1363 verbose("fsync \"%s\"", handle_to_name(handle)); 1364 if ((fd = handle_to_fd(handle)) < 0) 1365 status = SSH2_FX_NO_SUCH_FILE; 1366 else if (handle_is_ok(handle, HANDLE_FILE)) { 1367 r = fsync(fd); 1368 status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 1369 } 1370 send_status(id, status); 1371} 1372 1373static void 1374process_extended(u_int32_t id) 1375{ 1376 char *request; 1377 int i, r; 1378 1379 if ((r = sshbuf_get_cstring(iqueue, &request, NULL)) != 0) 1380 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1381 for (i = 0; extended_handlers[i].handler != NULL; i++) { 1382 if (strcmp(request, extended_handlers[i].ext_name) == 0) { 1383 if (!request_permitted(&extended_handlers[i])) 1384 send_status(id, SSH2_FX_PERMISSION_DENIED); 1385 else 1386 extended_handlers[i].handler(id); 1387 break; 1388 } 1389 } 1390 if (extended_handlers[i].handler == NULL) { 1391 error("Unknown extended request \"%.100s\"", request); 1392 send_status(id, SSH2_FX_OP_UNSUPPORTED); /* MUST */ 1393 } 1394 free(request); 1395} 1396 1397/* stolen from ssh-agent */ 1398 1399static void 1400process(void) 1401{ 1402 u_int msg_len; 1403 u_int buf_len; 1404 u_int consumed; 1405 u_char type; 1406 const u_char *cp; 1407 int i, r; 1408 u_int32_t id; 1409 1410 buf_len = sshbuf_len(iqueue); 1411 if (buf_len < 5) 1412 return; /* Incomplete message. */ 1413 cp = sshbuf_ptr(iqueue); 1414 msg_len = get_u32(cp); 1415 if (msg_len > SFTP_MAX_MSG_LENGTH) { 1416 error("bad message from %s local user %s", 1417 client_addr, pw->pw_name); 1418 sftp_server_cleanup_exit(11); 1419 } 1420 if (buf_len < msg_len + 4) 1421 return; 1422 if ((r = sshbuf_consume(iqueue, 4)) != 0) 1423 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1424 buf_len -= 4; 1425 if ((r = sshbuf_get_u8(iqueue, &type)) != 0) 1426 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1427 1428 switch (type) { 1429 case SSH2_FXP_INIT: 1430 process_init(); 1431 init_done = 1; 1432 break; 1433 case SSH2_FXP_EXTENDED: 1434 if (!init_done) 1435 fatal("Received extended request before init"); 1436 if ((r = sshbuf_get_u32(iqueue, &id)) != 0) 1437 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1438 process_extended(id); 1439 break; 1440 default: 1441 if (!init_done) 1442 fatal("Received %u request before init", type); 1443 if ((r = sshbuf_get_u32(iqueue, &id)) != 0) 1444 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1445 for (i = 0; handlers[i].handler != NULL; i++) { 1446 if (type == handlers[i].type) { 1447 if (!request_permitted(&handlers[i])) { 1448 send_status(id, 1449 SSH2_FX_PERMISSION_DENIED); 1450 } else { 1451 handlers[i].handler(id); 1452 } 1453 break; 1454 } 1455 } 1456 if (handlers[i].handler == NULL) 1457 error("Unknown message %u", type); 1458 } 1459 /* discard the remaining bytes from the current packet */ 1460 if (buf_len < sshbuf_len(iqueue)) { 1461 error("iqueue grew unexpectedly"); 1462 sftp_server_cleanup_exit(255); 1463 } 1464 consumed = buf_len - sshbuf_len(iqueue); 1465 if (msg_len < consumed) { 1466 error("msg_len %u < consumed %u", msg_len, consumed); 1467 sftp_server_cleanup_exit(255); 1468 } 1469 if (msg_len > consumed && 1470 (r = sshbuf_consume(iqueue, msg_len - consumed)) != 0) 1471 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1472} 1473 1474/* Cleanup handler that logs active handles upon normal exit */ 1475void 1476sftp_server_cleanup_exit(int i) 1477{ 1478 if (pw != NULL && client_addr != NULL) { 1479 handle_log_exit(); 1480 logit("session closed for local user %s from [%s]", 1481 pw->pw_name, client_addr); 1482 } 1483 _exit(i); 1484} 1485 1486static void 1487sftp_server_usage(void) 1488{ 1489 extern char *__progname; 1490 1491 fprintf(stderr, 1492 "usage: %s [-ehR] [-d start_directory] [-f log_facility] " 1493 "[-l log_level]\n\t[-P blacklisted_requests] " 1494 "[-p whitelisted_requests] [-u umask]\n" 1495 " %s -Q protocol_feature\n", 1496 __progname, __progname); 1497 exit(1); 1498} 1499 1500int 1501sftp_server_main(int argc, char **argv, struct passwd *user_pw) 1502{ 1503 fd_set *rset, *wset; 1504 int i, r, in, out, max, ch, skipargs = 0, log_stderr = 0; 1505 ssize_t len, olen, set_size; 1506 SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; 1507 char *cp, *homedir = NULL, buf[4*4096]; 1508 long mask; 1509 1510 extern char *optarg; 1511 extern char *__progname; 1512 1513 ssh_malloc_init(); /* must be called before any mallocs */ 1514 __progname = ssh_get_progname(argv[0]); 1515 log_init(__progname, log_level, log_facility, log_stderr); 1516 1517 pw = pwcopy(user_pw); 1518 1519 while (!skipargs && (ch = getopt(argc, argv, 1520 "d:f:l:P:p:Q:u:cehR")) != -1) { 1521 switch (ch) { 1522 case 'Q': 1523 if (strcasecmp(optarg, "requests") != 0) { 1524 fprintf(stderr, "Invalid query type\n"); 1525 exit(1); 1526 } 1527 for (i = 0; handlers[i].handler != NULL; i++) 1528 printf("%s\n", handlers[i].name); 1529 for (i = 0; extended_handlers[i].handler != NULL; i++) 1530 printf("%s\n", extended_handlers[i].name); 1531 exit(0); 1532 break; 1533 case 'R': 1534 readonly = 1; 1535 break; 1536 case 'c': 1537 /* 1538 * Ignore all arguments if we are invoked as a 1539 * shell using "sftp-server -c command" 1540 */ 1541 skipargs = 1; 1542 break; 1543 case 'e': 1544 log_stderr = 1; 1545 break; 1546 case 'l': 1547 log_level = log_level_number(optarg); 1548 if (log_level == SYSLOG_LEVEL_NOT_SET) 1549 error("Invalid log level \"%s\"", optarg); 1550 break; 1551 case 'f': 1552 log_facility = log_facility_number(optarg); 1553 if (log_facility == SYSLOG_FACILITY_NOT_SET) 1554 error("Invalid log facility \"%s\"", optarg); 1555 break; 1556 case 'd': 1557 cp = tilde_expand_filename(optarg, user_pw->pw_uid); 1558 homedir = percent_expand(cp, "d", user_pw->pw_dir, 1559 "u", user_pw->pw_name, (char *)NULL); 1560 free(cp); 1561 break; 1562 case 'p': 1563 if (request_whitelist != NULL) 1564 fatal("Permitted requests already set"); 1565 request_whitelist = xstrdup(optarg); 1566 break; 1567 case 'P': 1568 if (request_blacklist != NULL) 1569 fatal("Refused requests already set"); 1570 request_blacklist = xstrdup(optarg); 1571 break; 1572 case 'u': 1573 errno = 0; 1574 mask = strtol(optarg, &cp, 8); 1575 if (mask < 0 || mask > 0777 || *cp != '\0' || 1576 cp == optarg || (mask == 0 && errno != 0)) 1577 fatal("Invalid umask \"%s\"", optarg); 1578 (void)umask((mode_t)mask); 1579 break; 1580 case 'h': 1581 default: 1582 sftp_server_usage(); 1583 } 1584 } 1585 1586 log_init(__progname, log_level, log_facility, log_stderr); 1587 1588 /* 1589 * On platforms where we can, avoid making /proc/self/{mem,maps} 1590 * available to the user so that sftp access doesn't automatically 1591 * imply arbitrary code execution access that will break 1592 * restricted configurations. 1593 */ 1594 platform_disable_tracing(1); /* strict */ 1595 1596 /* Drop any fine-grained privileges we don't need */ 1597 platform_pledge_sftp_server(); 1598 1599 if ((cp = getenv("SSH_CONNECTION")) != NULL) { 1600 client_addr = xstrdup(cp); 1601 if ((cp = strchr(client_addr, ' ')) == NULL) { 1602 error("Malformed SSH_CONNECTION variable: \"%s\"", 1603 getenv("SSH_CONNECTION")); 1604 sftp_server_cleanup_exit(255); 1605 } 1606 *cp = '\0'; 1607 } else 1608 client_addr = xstrdup("UNKNOWN"); 1609 1610 logit("session opened for local user %s from [%s]", 1611 pw->pw_name, client_addr); 1612 1613 in = STDIN_FILENO; 1614 out = STDOUT_FILENO; 1615 1616#ifdef HAVE_CYGWIN 1617 setmode(in, O_BINARY); 1618 setmode(out, O_BINARY); 1619#endif 1620 1621 max = 0; 1622 if (in > max) 1623 max = in; 1624 if (out > max) 1625 max = out; 1626 1627 if ((iqueue = sshbuf_new()) == NULL) 1628 fatal("%s: sshbuf_new failed", __func__); 1629 if ((oqueue = sshbuf_new()) == NULL) 1630 fatal("%s: sshbuf_new failed", __func__); 1631 1632 rset = xcalloc(howmany(max + 1, NFDBITS), sizeof(fd_mask)); 1633 wset = xcalloc(howmany(max + 1, NFDBITS), sizeof(fd_mask)); 1634 1635 if (homedir != NULL) { 1636 if (chdir(homedir) != 0) { 1637 error("chdir to \"%s\" failed: %s", homedir, 1638 strerror(errno)); 1639 } 1640 } 1641 1642 set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask); 1643 for (;;) { 1644 memset(rset, 0, set_size); 1645 memset(wset, 0, set_size); 1646 1647 /* 1648 * Ensure that we can read a full buffer and handle 1649 * the worst-case length packet it can generate, 1650 * otherwise apply backpressure by stopping reads. 1651 */ 1652 if ((r = sshbuf_check_reserve(iqueue, sizeof(buf))) == 0 && 1653 (r = sshbuf_check_reserve(oqueue, 1654 SFTP_MAX_MSG_LENGTH)) == 0) 1655 FD_SET(in, rset); 1656 else if (r != SSH_ERR_NO_BUFFER_SPACE) 1657 fatal("%s: sshbuf_check_reserve failed: %s", 1658 __func__, ssh_err(r)); 1659 1660 olen = sshbuf_len(oqueue); 1661 if (olen > 0) 1662 FD_SET(out, wset); 1663 1664 if (select(max+1, rset, wset, NULL, NULL) < 0) { 1665 if (errno == EINTR) 1666 continue; 1667 error("select: %s", strerror(errno)); 1668 sftp_server_cleanup_exit(2); 1669 } 1670 1671 /* copy stdin to iqueue */ 1672 if (FD_ISSET(in, rset)) { 1673 len = read(in, buf, sizeof buf); 1674 if (len == 0) { 1675 debug("read eof"); 1676 sftp_server_cleanup_exit(0); 1677 } else if (len < 0) { 1678 error("read: %s", strerror(errno)); 1679 sftp_server_cleanup_exit(1); 1680 } else if ((r = sshbuf_put(iqueue, buf, len)) != 0) { 1681 fatal("%s: buffer error: %s", 1682 __func__, ssh_err(r)); 1683 } 1684 } 1685 /* send oqueue to stdout */ 1686 if (FD_ISSET(out, wset)) { 1687 len = write(out, sshbuf_ptr(oqueue), olen); 1688 if (len < 0) { 1689 error("write: %s", strerror(errno)); 1690 sftp_server_cleanup_exit(1); 1691 } else if ((r = sshbuf_consume(oqueue, len)) != 0) { 1692 fatal("%s: buffer error: %s", 1693 __func__, ssh_err(r)); 1694 } 1695 } 1696 1697 /* 1698 * Process requests from client if we can fit the results 1699 * into the output buffer, otherwise stop processing input 1700 * and let the output queue drain. 1701 */ 1702 r = sshbuf_check_reserve(oqueue, SFTP_MAX_MSG_LENGTH); 1703 if (r == 0) 1704 process(); 1705 else if (r != SSH_ERR_NO_BUFFER_SPACE) 1706 fatal("%s: sshbuf_check_reserve: %s", 1707 __func__, ssh_err(r)); 1708 } 1709} 1710