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