1 /* $OpenBSD: sftp-server.c,v 1.147 2023/04/12 08:53:54 jsg 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/types.h> 21 #include <sys/stat.h> 22 #include <sys/resource.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 #ifdef HAVE_POLL_H 37 #include <poll.h> 38 #endif 39 #include <pwd.h> 40 #include <grp.h> 41 #include <stdlib.h> 42 #include <stdio.h> 43 #include <string.h> 44 #include <time.h> 45 #include <unistd.h> 46 #include <stdarg.h> 47 48 #include "atomicio.h" 49 #include "xmalloc.h" 50 #include "sshbuf.h" 51 #include "ssherr.h" 52 #include "log.h" 53 #include "misc.h" 54 #include "match.h" 55 #include "uidswap.h" 56 57 #include "sftp.h" 58 #include "sftp-common.h" 59 60 char *sftp_realpath(const char *, char *); /* sftp-realpath.c */ 61 62 /* Maximum data read that we are willing to accept */ 63 #define SFTP_MAX_READ_LENGTH (SFTP_MAX_MSG_LENGTH - 1024) 64 65 /* Our verbosity */ 66 static LogLevel log_level = SYSLOG_LEVEL_ERROR; 67 68 /* Our client */ 69 static struct passwd *pw = NULL; 70 static char *client_addr = NULL; 71 72 /* input and output queue */ 73 struct sshbuf *iqueue; 74 struct sshbuf *oqueue; 75 76 /* Version of client */ 77 static u_int version; 78 79 /* SSH2_FXP_INIT received */ 80 static int init_done; 81 82 /* Disable writes */ 83 static int readonly; 84 85 /* Requests that are allowed/denied */ 86 static char *request_allowlist, *request_denylist; 87 88 /* portable attributes, etc. */ 89 typedef struct Stat Stat; 90 91 struct Stat { 92 char *name; 93 char *long_name; 94 Attrib attrib; 95 }; 96 97 /* Packet handlers */ 98 static void process_open(u_int32_t id); 99 static void process_close(u_int32_t id); 100 static void process_read(u_int32_t id); 101 static void process_write(u_int32_t id); 102 static void process_stat(u_int32_t id); 103 static void process_lstat(u_int32_t id); 104 static void process_fstat(u_int32_t id); 105 static void process_setstat(u_int32_t id); 106 static void process_fsetstat(u_int32_t id); 107 static void process_opendir(u_int32_t id); 108 static void process_readdir(u_int32_t id); 109 static void process_remove(u_int32_t id); 110 static void process_mkdir(u_int32_t id); 111 static void process_rmdir(u_int32_t id); 112 static void process_realpath(u_int32_t id); 113 static void process_rename(u_int32_t id); 114 static void process_readlink(u_int32_t id); 115 static void process_symlink(u_int32_t id); 116 static void process_extended_posix_rename(u_int32_t id); 117 static void process_extended_statvfs(u_int32_t id); 118 static void process_extended_fstatvfs(u_int32_t id); 119 static void process_extended_hardlink(u_int32_t id); 120 static void process_extended_fsync(u_int32_t id); 121 static void process_extended_lsetstat(u_int32_t id); 122 static void process_extended_limits(u_int32_t id); 123 static void process_extended_expand(u_int32_t id); 124 static void process_extended_copy_data(u_int32_t id); 125 static void process_extended_home_directory(u_int32_t id); 126 static void process_extended_get_users_groups_by_id(u_int32_t id); 127 static void process_extended(u_int32_t id); 128 129 struct sftp_handler { 130 const char *name; /* user-visible name for fine-grained perms */ 131 const char *ext_name; /* extended request name */ 132 u_int type; /* packet type, for non extended packets */ 133 void (*handler)(u_int32_t); 134 int does_write; /* if nonzero, banned for readonly mode */ 135 }; 136 137 static const struct sftp_handler handlers[] = { 138 /* NB. SSH2_FXP_OPEN does the readonly check in the handler itself */ 139 { "open", NULL, SSH2_FXP_OPEN, process_open, 0 }, 140 { "close", NULL, SSH2_FXP_CLOSE, process_close, 0 }, 141 { "read", NULL, SSH2_FXP_READ, process_read, 0 }, 142 { "write", NULL, SSH2_FXP_WRITE, process_write, 1 }, 143 { "lstat", NULL, SSH2_FXP_LSTAT, process_lstat, 0 }, 144 { "fstat", NULL, SSH2_FXP_FSTAT, process_fstat, 0 }, 145 { "setstat", NULL, SSH2_FXP_SETSTAT, process_setstat, 1 }, 146 { "fsetstat", NULL, SSH2_FXP_FSETSTAT, process_fsetstat, 1 }, 147 { "opendir", NULL, SSH2_FXP_OPENDIR, process_opendir, 0 }, 148 { "readdir", NULL, SSH2_FXP_READDIR, process_readdir, 0 }, 149 { "remove", NULL, SSH2_FXP_REMOVE, process_remove, 1 }, 150 { "mkdir", NULL, SSH2_FXP_MKDIR, process_mkdir, 1 }, 151 { "rmdir", NULL, SSH2_FXP_RMDIR, process_rmdir, 1 }, 152 { "realpath", NULL, SSH2_FXP_REALPATH, process_realpath, 0 }, 153 { "stat", NULL, SSH2_FXP_STAT, process_stat, 0 }, 154 { "rename", NULL, SSH2_FXP_RENAME, process_rename, 1 }, 155 { "readlink", NULL, SSH2_FXP_READLINK, process_readlink, 0 }, 156 { "symlink", NULL, SSH2_FXP_SYMLINK, process_symlink, 1 }, 157 { NULL, NULL, 0, NULL, 0 } 158 }; 159 160 /* SSH2_FXP_EXTENDED submessages */ 161 static const struct sftp_handler extended_handlers[] = { 162 { "posix-rename", "posix-rename@openssh.com", 0, 163 process_extended_posix_rename, 1 }, 164 { "statvfs", "statvfs@openssh.com", 0, process_extended_statvfs, 0 }, 165 { "fstatvfs", "fstatvfs@openssh.com", 0, process_extended_fstatvfs, 0 }, 166 { "hardlink", "hardlink@openssh.com", 0, process_extended_hardlink, 1 }, 167 { "fsync", "fsync@openssh.com", 0, process_extended_fsync, 1 }, 168 { "lsetstat", "lsetstat@openssh.com", 0, process_extended_lsetstat, 1 }, 169 { "limits", "limits@openssh.com", 0, process_extended_limits, 0 }, 170 { "expand-path", "expand-path@openssh.com", 0, 171 process_extended_expand, 0 }, 172 { "copy-data", "copy-data", 0, process_extended_copy_data, 1 }, 173 { "home-directory", "home-directory", 0, 174 process_extended_home_directory, 0 }, 175 { "users-groups-by-id", "users-groups-by-id@openssh.com", 0, 176 process_extended_get_users_groups_by_id, 0 }, 177 { NULL, NULL, 0, NULL, 0 } 178 }; 179 180 static const struct sftp_handler * 181 extended_handler_byname(const char *name) 182 { 183 int i; 184 185 for (i = 0; extended_handlers[i].handler != NULL; i++) { 186 if (strcmp(name, extended_handlers[i].ext_name) == 0) 187 return &extended_handlers[i]; 188 } 189 return NULL; 190 } 191 192 static int 193 request_permitted(const struct sftp_handler *h) 194 { 195 char *result; 196 197 if (readonly && h->does_write) { 198 verbose("Refusing %s request in read-only mode", h->name); 199 return 0; 200 } 201 if (request_denylist != NULL && 202 ((result = match_list(h->name, request_denylist, NULL))) != NULL) { 203 free(result); 204 verbose("Refusing denylisted %s request", h->name); 205 return 0; 206 } 207 if (request_allowlist != NULL && 208 ((result = match_list(h->name, request_allowlist, NULL))) != NULL) { 209 free(result); 210 debug2("Permitting allowlisted %s request", h->name); 211 return 1; 212 } 213 if (request_allowlist != NULL) { 214 verbose("Refusing non-allowlisted %s request", h->name); 215 return 0; 216 } 217 return 1; 218 } 219 220 static int 221 errno_to_portable(int unixerrno) 222 { 223 int ret = 0; 224 225 switch (unixerrno) { 226 case 0: 227 ret = SSH2_FX_OK; 228 break; 229 case ENOENT: 230 case ENOTDIR: 231 case EBADF: 232 case ELOOP: 233 ret = SSH2_FX_NO_SUCH_FILE; 234 break; 235 case EPERM: 236 case EACCES: 237 case EFAULT: 238 ret = SSH2_FX_PERMISSION_DENIED; 239 break; 240 case ENAMETOOLONG: 241 case EINVAL: 242 ret = SSH2_FX_BAD_MESSAGE; 243 break; 244 case ENOSYS: 245 ret = SSH2_FX_OP_UNSUPPORTED; 246 break; 247 default: 248 ret = SSH2_FX_FAILURE; 249 break; 250 } 251 return ret; 252 } 253 254 static int 255 flags_from_portable(int pflags) 256 { 257 int flags = 0; 258 259 if ((pflags & SSH2_FXF_READ) && 260 (pflags & SSH2_FXF_WRITE)) { 261 flags = O_RDWR; 262 } else if (pflags & SSH2_FXF_READ) { 263 flags = O_RDONLY; 264 } else if (pflags & SSH2_FXF_WRITE) { 265 flags = O_WRONLY; 266 } 267 if (pflags & SSH2_FXF_APPEND) 268 flags |= O_APPEND; 269 if (pflags & SSH2_FXF_CREAT) 270 flags |= O_CREAT; 271 if (pflags & SSH2_FXF_TRUNC) 272 flags |= O_TRUNC; 273 if (pflags & SSH2_FXF_EXCL) 274 flags |= O_EXCL; 275 return flags; 276 } 277 278 static const char * 279 string_from_portable(int pflags) 280 { 281 static char ret[128]; 282 283 *ret = '\0'; 284 285 #define PAPPEND(str) { \ 286 if (*ret != '\0') \ 287 strlcat(ret, ",", sizeof(ret)); \ 288 strlcat(ret, str, sizeof(ret)); \ 289 } 290 291 if (pflags & SSH2_FXF_READ) 292 PAPPEND("READ") 293 if (pflags & SSH2_FXF_WRITE) 294 PAPPEND("WRITE") 295 if (pflags & SSH2_FXF_APPEND) 296 PAPPEND("APPEND") 297 if (pflags & SSH2_FXF_CREAT) 298 PAPPEND("CREATE") 299 if (pflags & SSH2_FXF_TRUNC) 300 PAPPEND("TRUNCATE") 301 if (pflags & SSH2_FXF_EXCL) 302 PAPPEND("EXCL") 303 304 return ret; 305 } 306 307 /* handle handles */ 308 309 typedef struct Handle Handle; 310 struct Handle { 311 int use; 312 DIR *dirp; 313 int fd; 314 int flags; 315 char *name; 316 u_int64_t bytes_read, bytes_write; 317 int next_unused; 318 }; 319 320 enum { 321 HANDLE_UNUSED, 322 HANDLE_DIR, 323 HANDLE_FILE 324 }; 325 326 static Handle *handles = NULL; 327 static u_int num_handles = 0; 328 static int first_unused_handle = -1; 329 330 static void handle_unused(int i) 331 { 332 handles[i].use = HANDLE_UNUSED; 333 handles[i].next_unused = first_unused_handle; 334 first_unused_handle = i; 335 } 336 337 static int 338 handle_new(int use, const char *name, int fd, int flags, DIR *dirp) 339 { 340 int i; 341 342 if (first_unused_handle == -1) { 343 if (num_handles + 1 <= num_handles) 344 return -1; 345 num_handles++; 346 handles = xreallocarray(handles, num_handles, sizeof(Handle)); 347 handle_unused(num_handles - 1); 348 } 349 350 i = first_unused_handle; 351 first_unused_handle = handles[i].next_unused; 352 353 handles[i].use = use; 354 handles[i].dirp = dirp; 355 handles[i].fd = fd; 356 handles[i].flags = flags; 357 handles[i].name = xstrdup(name); 358 handles[i].bytes_read = handles[i].bytes_write = 0; 359 360 return i; 361 } 362 363 static int 364 handle_is_ok(int i, int type) 365 { 366 return i >= 0 && (u_int)i < num_handles && handles[i].use == type; 367 } 368 369 static int 370 handle_to_string(int handle, u_char **stringp, int *hlenp) 371 { 372 if (stringp == NULL || hlenp == NULL) 373 return -1; 374 *stringp = xmalloc(sizeof(int32_t)); 375 put_u32(*stringp, handle); 376 *hlenp = sizeof(int32_t); 377 return 0; 378 } 379 380 static int 381 handle_from_string(const u_char *handle, u_int hlen) 382 { 383 int val; 384 385 if (hlen != sizeof(int32_t)) 386 return -1; 387 val = get_u32(handle); 388 if (handle_is_ok(val, HANDLE_FILE) || 389 handle_is_ok(val, HANDLE_DIR)) 390 return val; 391 return -1; 392 } 393 394 static char * 395 handle_to_name(int handle) 396 { 397 if (handle_is_ok(handle, HANDLE_DIR)|| 398 handle_is_ok(handle, HANDLE_FILE)) 399 return handles[handle].name; 400 return NULL; 401 } 402 403 static DIR * 404 handle_to_dir(int handle) 405 { 406 if (handle_is_ok(handle, HANDLE_DIR)) 407 return handles[handle].dirp; 408 return NULL; 409 } 410 411 static int 412 handle_to_fd(int handle) 413 { 414 if (handle_is_ok(handle, HANDLE_FILE)) 415 return handles[handle].fd; 416 return -1; 417 } 418 419 static int 420 handle_to_flags(int handle) 421 { 422 if (handle_is_ok(handle, HANDLE_FILE)) 423 return handles[handle].flags; 424 return 0; 425 } 426 427 static void 428 handle_update_read(int handle, ssize_t bytes) 429 { 430 if (handle_is_ok(handle, HANDLE_FILE) && bytes > 0) 431 handles[handle].bytes_read += bytes; 432 } 433 434 static void 435 handle_update_write(int handle, ssize_t bytes) 436 { 437 if (handle_is_ok(handle, HANDLE_FILE) && bytes > 0) 438 handles[handle].bytes_write += bytes; 439 } 440 441 static u_int64_t 442 handle_bytes_read(int handle) 443 { 444 if (handle_is_ok(handle, HANDLE_FILE)) 445 return (handles[handle].bytes_read); 446 return 0; 447 } 448 449 static u_int64_t 450 handle_bytes_write(int handle) 451 { 452 if (handle_is_ok(handle, HANDLE_FILE)) 453 return (handles[handle].bytes_write); 454 return 0; 455 } 456 457 static int 458 handle_close(int handle) 459 { 460 int ret = -1; 461 462 if (handle_is_ok(handle, HANDLE_FILE)) { 463 ret = close(handles[handle].fd); 464 free(handles[handle].name); 465 handle_unused(handle); 466 } else if (handle_is_ok(handle, HANDLE_DIR)) { 467 ret = closedir(handles[handle].dirp); 468 free(handles[handle].name); 469 handle_unused(handle); 470 } else { 471 errno = ENOENT; 472 } 473 return ret; 474 } 475 476 static void 477 handle_log_close(int handle, char *emsg) 478 { 479 if (handle_is_ok(handle, HANDLE_FILE)) { 480 logit("%s%sclose \"%s\" bytes read %llu written %llu", 481 emsg == NULL ? "" : emsg, emsg == NULL ? "" : " ", 482 handle_to_name(handle), 483 (unsigned long long)handle_bytes_read(handle), 484 (unsigned long long)handle_bytes_write(handle)); 485 } else { 486 logit("%s%sclosedir \"%s\"", 487 emsg == NULL ? "" : emsg, emsg == NULL ? "" : " ", 488 handle_to_name(handle)); 489 } 490 } 491 492 static void 493 handle_log_exit(void) 494 { 495 u_int i; 496 497 for (i = 0; i < num_handles; i++) 498 if (handles[i].use != HANDLE_UNUSED) 499 handle_log_close(i, "forced"); 500 } 501 502 static int 503 get_handle(struct sshbuf *queue, int *hp) 504 { 505 u_char *handle; 506 int r; 507 size_t hlen; 508 509 *hp = -1; 510 if ((r = sshbuf_get_string(queue, &handle, &hlen)) != 0) 511 return r; 512 if (hlen < 256) 513 *hp = handle_from_string(handle, hlen); 514 free(handle); 515 return 0; 516 } 517 518 /* send replies */ 519 520 static void 521 send_msg(struct sshbuf *m) 522 { 523 int r; 524 525 if ((r = sshbuf_put_stringb(oqueue, m)) != 0) 526 fatal_fr(r, "enqueue"); 527 sshbuf_reset(m); 528 } 529 530 static const char * 531 status_to_message(u_int32_t status) 532 { 533 static const char * const status_messages[] = { 534 "Success", /* SSH_FX_OK */ 535 "End of file", /* SSH_FX_EOF */ 536 "No such file", /* SSH_FX_NO_SUCH_FILE */ 537 "Permission denied", /* SSH_FX_PERMISSION_DENIED */ 538 "Failure", /* SSH_FX_FAILURE */ 539 "Bad message", /* SSH_FX_BAD_MESSAGE */ 540 "No connection", /* SSH_FX_NO_CONNECTION */ 541 "Connection lost", /* SSH_FX_CONNECTION_LOST */ 542 "Operation unsupported", /* SSH_FX_OP_UNSUPPORTED */ 543 "Unknown error" /* Others */ 544 }; 545 return (status_messages[MINIMUM(status,SSH2_FX_MAX)]); 546 } 547 548 static void 549 send_status_errmsg(u_int32_t id, u_int32_t status, const char *errmsg) 550 { 551 struct sshbuf *msg; 552 int r; 553 554 debug3("request %u: sent status %u", id, status); 555 if (log_level > SYSLOG_LEVEL_VERBOSE || 556 (status != SSH2_FX_OK && status != SSH2_FX_EOF)) 557 logit("sent status %s", status_to_message(status)); 558 if ((msg = sshbuf_new()) == NULL) 559 fatal_f("sshbuf_new failed"); 560 if ((r = sshbuf_put_u8(msg, SSH2_FXP_STATUS)) != 0 || 561 (r = sshbuf_put_u32(msg, id)) != 0 || 562 (r = sshbuf_put_u32(msg, status)) != 0) 563 fatal_fr(r, "compose"); 564 if (version >= 3) { 565 if ((r = sshbuf_put_cstring(msg, errmsg == NULL ? 566 status_to_message(status) : errmsg)) != 0 || 567 (r = sshbuf_put_cstring(msg, "")) != 0) 568 fatal_fr(r, "compose message"); 569 } 570 send_msg(msg); 571 sshbuf_free(msg); 572 } 573 574 static void 575 send_status(u_int32_t id, u_int32_t status) 576 { 577 send_status_errmsg(id, status, NULL); 578 } 579 580 static void 581 send_data_or_handle(char type, u_int32_t id, const u_char *data, int dlen) 582 { 583 struct sshbuf *msg; 584 int r; 585 586 if ((msg = sshbuf_new()) == NULL) 587 fatal_f("sshbuf_new failed"); 588 if ((r = sshbuf_put_u8(msg, type)) != 0 || 589 (r = sshbuf_put_u32(msg, id)) != 0 || 590 (r = sshbuf_put_string(msg, data, dlen)) != 0) 591 fatal_fr(r, "compose"); 592 send_msg(msg); 593 sshbuf_free(msg); 594 } 595 596 static void 597 send_data(u_int32_t id, const u_char *data, int dlen) 598 { 599 debug("request %u: sent data len %d", id, dlen); 600 send_data_or_handle(SSH2_FXP_DATA, id, data, dlen); 601 } 602 603 static void 604 send_handle(u_int32_t id, int handle) 605 { 606 u_char *string; 607 int hlen; 608 609 handle_to_string(handle, &string, &hlen); 610 debug("request %u: sent handle %d", id, handle); 611 send_data_or_handle(SSH2_FXP_HANDLE, id, string, hlen); 612 free(string); 613 } 614 615 static void 616 send_names(u_int32_t id, int count, const Stat *stats) 617 { 618 struct sshbuf *msg; 619 int i, r; 620 621 if ((msg = sshbuf_new()) == NULL) 622 fatal_f("sshbuf_new failed"); 623 if ((r = sshbuf_put_u8(msg, SSH2_FXP_NAME)) != 0 || 624 (r = sshbuf_put_u32(msg, id)) != 0 || 625 (r = sshbuf_put_u32(msg, count)) != 0) 626 fatal_fr(r, "compose"); 627 debug("request %u: sent names count %d", id, count); 628 for (i = 0; i < count; i++) { 629 if ((r = sshbuf_put_cstring(msg, stats[i].name)) != 0 || 630 (r = sshbuf_put_cstring(msg, stats[i].long_name)) != 0 || 631 (r = encode_attrib(msg, &stats[i].attrib)) != 0) 632 fatal_fr(r, "compose filenames/attrib"); 633 } 634 send_msg(msg); 635 sshbuf_free(msg); 636 } 637 638 static void 639 send_attrib(u_int32_t id, const Attrib *a) 640 { 641 struct sshbuf *msg; 642 int r; 643 644 debug("request %u: sent attrib have 0x%x", id, a->flags); 645 if ((msg = sshbuf_new()) == NULL) 646 fatal_f("sshbuf_new failed"); 647 if ((r = sshbuf_put_u8(msg, SSH2_FXP_ATTRS)) != 0 || 648 (r = sshbuf_put_u32(msg, id)) != 0 || 649 (r = encode_attrib(msg, a)) != 0) 650 fatal_fr(r, "compose"); 651 send_msg(msg); 652 sshbuf_free(msg); 653 } 654 655 static void 656 send_statvfs(u_int32_t id, struct statvfs *st) 657 { 658 struct sshbuf *msg; 659 u_int64_t flag; 660 int r; 661 662 flag = (st->f_flag & ST_RDONLY) ? SSH2_FXE_STATVFS_ST_RDONLY : 0; 663 flag |= (st->f_flag & ST_NOSUID) ? SSH2_FXE_STATVFS_ST_NOSUID : 0; 664 665 if ((msg = sshbuf_new()) == NULL) 666 fatal_f("sshbuf_new failed"); 667 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED_REPLY)) != 0 || 668 (r = sshbuf_put_u32(msg, id)) != 0 || 669 (r = sshbuf_put_u64(msg, st->f_bsize)) != 0 || 670 (r = sshbuf_put_u64(msg, st->f_frsize)) != 0 || 671 (r = sshbuf_put_u64(msg, st->f_blocks)) != 0 || 672 (r = sshbuf_put_u64(msg, st->f_bfree)) != 0 || 673 (r = sshbuf_put_u64(msg, st->f_bavail)) != 0 || 674 (r = sshbuf_put_u64(msg, st->f_files)) != 0 || 675 (r = sshbuf_put_u64(msg, st->f_ffree)) != 0 || 676 (r = sshbuf_put_u64(msg, st->f_favail)) != 0 || 677 (r = sshbuf_put_u64(msg, FSID_TO_ULONG(st->f_fsid))) != 0 || 678 (r = sshbuf_put_u64(msg, flag)) != 0 || 679 (r = sshbuf_put_u64(msg, st->f_namemax)) != 0) 680 fatal_fr(r, "compose"); 681 send_msg(msg); 682 sshbuf_free(msg); 683 } 684 685 /* 686 * Prepare SSH2_FXP_VERSION extension advertisement for a single extension. 687 * The extension is checked for permission prior to advertisement. 688 */ 689 static int 690 compose_extension(struct sshbuf *msg, const char *name, const char *ver) 691 { 692 int r; 693 const struct sftp_handler *exthnd; 694 695 if ((exthnd = extended_handler_byname(name)) == NULL) 696 fatal_f("internal error: no handler for %s", name); 697 if (!request_permitted(exthnd)) { 698 debug2_f("refusing to advertise disallowed extension %s", name); 699 return 0; 700 } 701 if ((r = sshbuf_put_cstring(msg, name)) != 0 || 702 (r = sshbuf_put_cstring(msg, ver)) != 0) 703 fatal_fr(r, "compose %s", name); 704 return 0; 705 } 706 707 /* parse incoming */ 708 709 static void 710 process_init(void) 711 { 712 struct sshbuf *msg; 713 int r; 714 715 if ((r = sshbuf_get_u32(iqueue, &version)) != 0) 716 fatal_fr(r, "parse"); 717 verbose("received client version %u", version); 718 if ((msg = sshbuf_new()) == NULL) 719 fatal_f("sshbuf_new failed"); 720 if ((r = sshbuf_put_u8(msg, SSH2_FXP_VERSION)) != 0 || 721 (r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0) 722 fatal_fr(r, "compose"); 723 724 /* extension advertisements */ 725 compose_extension(msg, "posix-rename@openssh.com", "1"); 726 compose_extension(msg, "statvfs@openssh.com", "2"); 727 compose_extension(msg, "fstatvfs@openssh.com", "2"); 728 compose_extension(msg, "hardlink@openssh.com", "1"); 729 compose_extension(msg, "fsync@openssh.com", "1"); 730 compose_extension(msg, "lsetstat@openssh.com", "1"); 731 compose_extension(msg, "limits@openssh.com", "1"); 732 compose_extension(msg, "expand-path@openssh.com", "1"); 733 compose_extension(msg, "copy-data", "1"); 734 compose_extension(msg, "home-directory", "1"); 735 compose_extension(msg, "users-groups-by-id@openssh.com", "1"); 736 737 send_msg(msg); 738 sshbuf_free(msg); 739 } 740 741 static void 742 process_open(u_int32_t id) 743 { 744 u_int32_t pflags; 745 Attrib a; 746 char *name; 747 int r, handle, fd, flags, mode, status = SSH2_FX_FAILURE; 748 749 if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || 750 (r = sshbuf_get_u32(iqueue, &pflags)) != 0 || /* portable flags */ 751 (r = decode_attrib(iqueue, &a)) != 0) 752 fatal_fr(r, "parse"); 753 754 debug3("request %u: open flags %d", id, pflags); 755 flags = flags_from_portable(pflags); 756 mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a.perm : 0666; 757 logit("open \"%s\" flags %s mode 0%o", 758 name, string_from_portable(pflags), mode); 759 if (readonly && 760 ((flags & O_ACCMODE) != O_RDONLY || 761 (flags & (O_CREAT|O_TRUNC)) != 0)) { 762 verbose("Refusing open request in read-only mode"); 763 status = SSH2_FX_PERMISSION_DENIED; 764 } else { 765 fd = open(name, flags, mode); 766 if (fd == -1) { 767 status = errno_to_portable(errno); 768 } else { 769 handle = handle_new(HANDLE_FILE, name, fd, flags, NULL); 770 if (handle < 0) { 771 close(fd); 772 } else { 773 send_handle(id, handle); 774 status = SSH2_FX_OK; 775 } 776 } 777 } 778 if (status != SSH2_FX_OK) 779 send_status(id, status); 780 free(name); 781 } 782 783 static void 784 process_close(u_int32_t id) 785 { 786 int r, handle, ret, status = SSH2_FX_FAILURE; 787 788 if ((r = get_handle(iqueue, &handle)) != 0) 789 fatal_fr(r, "parse"); 790 791 debug3("request %u: close handle %u", id, handle); 792 handle_log_close(handle, NULL); 793 ret = handle_close(handle); 794 status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 795 send_status(id, status); 796 } 797 798 static void 799 process_read(u_int32_t id) 800 { 801 static u_char *buf; 802 static size_t buflen; 803 u_int32_t len; 804 int r, handle, fd, ret, status = SSH2_FX_FAILURE; 805 u_int64_t off; 806 807 if ((r = get_handle(iqueue, &handle)) != 0 || 808 (r = sshbuf_get_u64(iqueue, &off)) != 0 || 809 (r = sshbuf_get_u32(iqueue, &len)) != 0) 810 fatal_fr(r, "parse"); 811 812 debug("request %u: read \"%s\" (handle %d) off %llu len %u", 813 id, handle_to_name(handle), handle, (unsigned long long)off, len); 814 if ((fd = handle_to_fd(handle)) == -1) 815 goto out; 816 if (len > SFTP_MAX_READ_LENGTH) { 817 debug2("read change len %u to %u", len, SFTP_MAX_READ_LENGTH); 818 len = SFTP_MAX_READ_LENGTH; 819 } 820 if (len > buflen) { 821 debug3_f("allocate %zu => %u", buflen, len); 822 if ((buf = realloc(buf, len)) == NULL) 823 fatal_f("realloc failed"); 824 buflen = len; 825 } 826 if (lseek(fd, off, SEEK_SET) == -1) { 827 status = errno_to_portable(errno); 828 error_f("seek \"%.100s\": %s", handle_to_name(handle), 829 strerror(errno)); 830 goto out; 831 } 832 if (len == 0) { 833 /* weird, but not strictly disallowed */ 834 ret = 0; 835 } else if ((ret = read(fd, buf, len)) == -1) { 836 status = errno_to_portable(errno); 837 error_f("read \"%.100s\": %s", handle_to_name(handle), 838 strerror(errno)); 839 goto out; 840 } else if (ret == 0) { 841 status = SSH2_FX_EOF; 842 goto out; 843 } 844 send_data(id, buf, ret); 845 handle_update_read(handle, ret); 846 /* success */ 847 status = SSH2_FX_OK; 848 out: 849 if (status != SSH2_FX_OK) 850 send_status(id, status); 851 } 852 853 static void 854 process_write(u_int32_t id) 855 { 856 u_int64_t off; 857 size_t len; 858 int r, handle, fd, ret, status; 859 u_char *data; 860 861 if ((r = get_handle(iqueue, &handle)) != 0 || 862 (r = sshbuf_get_u64(iqueue, &off)) != 0 || 863 (r = sshbuf_get_string(iqueue, &data, &len)) != 0) 864 fatal_fr(r, "parse"); 865 866 debug("request %u: write \"%s\" (handle %d) off %llu len %zu", 867 id, handle_to_name(handle), handle, (unsigned long long)off, len); 868 fd = handle_to_fd(handle); 869 870 if (fd < 0) 871 status = SSH2_FX_FAILURE; 872 else { 873 if (!(handle_to_flags(handle) & O_APPEND) && 874 lseek(fd, off, SEEK_SET) == -1) { 875 status = errno_to_portable(errno); 876 error_f("seek \"%.100s\": %s", handle_to_name(handle), 877 strerror(errno)); 878 } else { 879 /* XXX ATOMICIO ? */ 880 ret = write(fd, data, len); 881 if (ret == -1) { 882 status = errno_to_portable(errno); 883 error_f("write \"%.100s\": %s", 884 handle_to_name(handle), strerror(errno)); 885 } else if ((size_t)ret == len) { 886 status = SSH2_FX_OK; 887 handle_update_write(handle, ret); 888 } else { 889 debug2_f("nothing at all written"); 890 status = SSH2_FX_FAILURE; 891 } 892 } 893 } 894 send_status(id, status); 895 free(data); 896 } 897 898 static void 899 process_do_stat(u_int32_t id, int do_lstat) 900 { 901 Attrib a; 902 struct stat st; 903 char *name; 904 int r, status = SSH2_FX_FAILURE; 905 906 if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0) 907 fatal_fr(r, "parse"); 908 909 debug3("request %u: %sstat", id, do_lstat ? "l" : ""); 910 verbose("%sstat name \"%s\"", do_lstat ? "l" : "", name); 911 r = do_lstat ? lstat(name, &st) : stat(name, &st); 912 if (r == -1) { 913 status = errno_to_portable(errno); 914 } else { 915 stat_to_attrib(&st, &a); 916 send_attrib(id, &a); 917 status = SSH2_FX_OK; 918 } 919 if (status != SSH2_FX_OK) 920 send_status(id, status); 921 free(name); 922 } 923 924 static void 925 process_stat(u_int32_t id) 926 { 927 process_do_stat(id, 0); 928 } 929 930 static void 931 process_lstat(u_int32_t id) 932 { 933 process_do_stat(id, 1); 934 } 935 936 static void 937 process_fstat(u_int32_t id) 938 { 939 Attrib a; 940 struct stat st; 941 int fd, r, handle, status = SSH2_FX_FAILURE; 942 943 if ((r = get_handle(iqueue, &handle)) != 0) 944 fatal_fr(r, "parse"); 945 debug("request %u: fstat \"%s\" (handle %u)", 946 id, handle_to_name(handle), handle); 947 fd = handle_to_fd(handle); 948 if (fd >= 0) { 949 r = fstat(fd, &st); 950 if (r == -1) { 951 status = errno_to_portable(errno); 952 } else { 953 stat_to_attrib(&st, &a); 954 send_attrib(id, &a); 955 status = SSH2_FX_OK; 956 } 957 } 958 if (status != SSH2_FX_OK) 959 send_status(id, status); 960 } 961 962 static struct timeval * 963 attrib_to_tv(const Attrib *a) 964 { 965 static struct timeval tv[2]; 966 967 tv[0].tv_sec = a->atime; 968 tv[0].tv_usec = 0; 969 tv[1].tv_sec = a->mtime; 970 tv[1].tv_usec = 0; 971 return tv; 972 } 973 974 static struct timespec * 975 attrib_to_ts(const Attrib *a) 976 { 977 static struct timespec ts[2]; 978 979 ts[0].tv_sec = a->atime; 980 ts[0].tv_nsec = 0; 981 ts[1].tv_sec = a->mtime; 982 ts[1].tv_nsec = 0; 983 return ts; 984 } 985 986 static void 987 process_setstat(u_int32_t id) 988 { 989 Attrib a; 990 char *name; 991 int r, status = SSH2_FX_OK; 992 993 if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || 994 (r = decode_attrib(iqueue, &a)) != 0) 995 fatal_fr(r, "parse"); 996 997 debug("request %u: setstat name \"%s\"", id, name); 998 if (a.flags & SSH2_FILEXFER_ATTR_SIZE) { 999 logit("set \"%s\" size %llu", 1000 name, (unsigned long long)a.size); 1001 r = truncate(name, a.size); 1002 if (r == -1) 1003 status = errno_to_portable(errno); 1004 } 1005 if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { 1006 logit("set \"%s\" mode %04o", name, a.perm); 1007 r = chmod(name, a.perm & 07777); 1008 if (r == -1) 1009 status = errno_to_portable(errno); 1010 } 1011 if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) { 1012 char buf[64]; 1013 time_t t = a.mtime; 1014 1015 strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S", 1016 localtime(&t)); 1017 logit("set \"%s\" modtime %s", name, buf); 1018 r = utimes(name, attrib_to_tv(&a)); 1019 if (r == -1) 1020 status = errno_to_portable(errno); 1021 } 1022 if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) { 1023 logit("set \"%s\" owner %lu group %lu", name, 1024 (u_long)a.uid, (u_long)a.gid); 1025 r = chown(name, a.uid, a.gid); 1026 if (r == -1) 1027 status = errno_to_portable(errno); 1028 } 1029 send_status(id, status); 1030 free(name); 1031 } 1032 1033 static void 1034 process_fsetstat(u_int32_t id) 1035 { 1036 Attrib a; 1037 int handle, fd, r; 1038 int status = SSH2_FX_OK; 1039 1040 if ((r = get_handle(iqueue, &handle)) != 0 || 1041 (r = decode_attrib(iqueue, &a)) != 0) 1042 fatal_fr(r, "parse"); 1043 1044 debug("request %u: fsetstat handle %d", id, handle); 1045 fd = handle_to_fd(handle); 1046 if (fd < 0) 1047 status = SSH2_FX_FAILURE; 1048 else { 1049 char *name = handle_to_name(handle); 1050 1051 if (a.flags & SSH2_FILEXFER_ATTR_SIZE) { 1052 logit("set \"%s\" size %llu", 1053 name, (unsigned long long)a.size); 1054 r = ftruncate(fd, a.size); 1055 if (r == -1) 1056 status = errno_to_portable(errno); 1057 } 1058 if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { 1059 logit("set \"%s\" mode %04o", name, a.perm); 1060 #ifdef HAVE_FCHMOD 1061 r = fchmod(fd, a.perm & 07777); 1062 #else 1063 r = chmod(name, a.perm & 07777); 1064 #endif 1065 if (r == -1) 1066 status = errno_to_portable(errno); 1067 } 1068 if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) { 1069 char buf[64]; 1070 time_t t = a.mtime; 1071 1072 strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S", 1073 localtime(&t)); 1074 logit("set \"%s\" modtime %s", name, buf); 1075 #ifdef HAVE_FUTIMES 1076 r = futimes(fd, attrib_to_tv(&a)); 1077 #else 1078 r = utimes(name, attrib_to_tv(&a)); 1079 #endif 1080 if (r == -1) 1081 status = errno_to_portable(errno); 1082 } 1083 if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) { 1084 logit("set \"%s\" owner %lu group %lu", name, 1085 (u_long)a.uid, (u_long)a.gid); 1086 #ifdef HAVE_FCHOWN 1087 r = fchown(fd, a.uid, a.gid); 1088 #else 1089 r = chown(name, a.uid, a.gid); 1090 #endif 1091 if (r == -1) 1092 status = errno_to_portable(errno); 1093 } 1094 } 1095 send_status(id, status); 1096 } 1097 1098 static void 1099 process_opendir(u_int32_t id) 1100 { 1101 DIR *dirp = NULL; 1102 char *path; 1103 int r, handle, status = SSH2_FX_FAILURE; 1104 1105 if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) 1106 fatal_fr(r, "parse"); 1107 1108 debug3("request %u: opendir", id); 1109 logit("opendir \"%s\"", path); 1110 dirp = opendir(path); 1111 if (dirp == NULL) { 1112 status = errno_to_portable(errno); 1113 } else { 1114 handle = handle_new(HANDLE_DIR, path, 0, 0, dirp); 1115 if (handle < 0) { 1116 closedir(dirp); 1117 } else { 1118 send_handle(id, handle); 1119 status = SSH2_FX_OK; 1120 } 1121 1122 } 1123 if (status != SSH2_FX_OK) 1124 send_status(id, status); 1125 free(path); 1126 } 1127 1128 static void 1129 process_readdir(u_int32_t id) 1130 { 1131 DIR *dirp; 1132 struct dirent *dp; 1133 char *path; 1134 int r, handle; 1135 1136 if ((r = get_handle(iqueue, &handle)) != 0) 1137 fatal_fr(r, "parse"); 1138 1139 debug("request %u: readdir \"%s\" (handle %d)", id, 1140 handle_to_name(handle), handle); 1141 dirp = handle_to_dir(handle); 1142 path = handle_to_name(handle); 1143 if (dirp == NULL || path == NULL) { 1144 send_status(id, SSH2_FX_FAILURE); 1145 } else { 1146 struct stat st; 1147 char pathname[PATH_MAX]; 1148 Stat *stats; 1149 int nstats = 10, count = 0, i; 1150 1151 stats = xcalloc(nstats, sizeof(Stat)); 1152 while ((dp = readdir(dirp)) != NULL) { 1153 if (count >= nstats) { 1154 nstats *= 2; 1155 stats = xreallocarray(stats, nstats, sizeof(Stat)); 1156 } 1157 /* XXX OVERFLOW ? */ 1158 snprintf(pathname, sizeof pathname, "%s%s%s", path, 1159 strcmp(path, "/") ? "/" : "", dp->d_name); 1160 if (lstat(pathname, &st) == -1) 1161 continue; 1162 stat_to_attrib(&st, &(stats[count].attrib)); 1163 stats[count].name = xstrdup(dp->d_name); 1164 stats[count].long_name = ls_file(dp->d_name, &st, 1165 0, 0, NULL, NULL); 1166 count++; 1167 /* send up to 100 entries in one message */ 1168 /* XXX check packet size instead */ 1169 if (count == 100) 1170 break; 1171 } 1172 if (count > 0) { 1173 send_names(id, count, stats); 1174 for (i = 0; i < count; i++) { 1175 free(stats[i].name); 1176 free(stats[i].long_name); 1177 } 1178 } else { 1179 send_status(id, SSH2_FX_EOF); 1180 } 1181 free(stats); 1182 } 1183 } 1184 1185 static void 1186 process_remove(u_int32_t id) 1187 { 1188 char *name; 1189 int r, status = SSH2_FX_FAILURE; 1190 1191 if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0) 1192 fatal_fr(r, "parse"); 1193 1194 debug3("request %u: remove", id); 1195 logit("remove name \"%s\"", name); 1196 r = unlink(name); 1197 status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 1198 send_status(id, status); 1199 free(name); 1200 } 1201 1202 static void 1203 process_mkdir(u_int32_t id) 1204 { 1205 Attrib a; 1206 char *name; 1207 int r, mode, status = SSH2_FX_FAILURE; 1208 1209 if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || 1210 (r = decode_attrib(iqueue, &a)) != 0) 1211 fatal_fr(r, "parse"); 1212 1213 mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? 1214 a.perm & 07777 : 0777; 1215 debug3("request %u: mkdir", id); 1216 logit("mkdir name \"%s\" mode 0%o", name, mode); 1217 r = mkdir(name, mode); 1218 status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 1219 send_status(id, status); 1220 free(name); 1221 } 1222 1223 static void 1224 process_rmdir(u_int32_t id) 1225 { 1226 char *name; 1227 int r, status; 1228 1229 if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0) 1230 fatal_fr(r, "parse"); 1231 1232 debug3("request %u: rmdir", id); 1233 logit("rmdir name \"%s\"", name); 1234 r = rmdir(name); 1235 status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 1236 send_status(id, status); 1237 free(name); 1238 } 1239 1240 static void 1241 process_realpath(u_int32_t id) 1242 { 1243 char resolvedname[PATH_MAX]; 1244 char *path; 1245 int r; 1246 1247 if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) 1248 fatal_fr(r, "parse"); 1249 1250 if (path[0] == '\0') { 1251 free(path); 1252 path = xstrdup("."); 1253 } 1254 debug3("request %u: realpath", id); 1255 verbose("realpath \"%s\"", path); 1256 if (sftp_realpath(path, resolvedname) == NULL) { 1257 send_status(id, errno_to_portable(errno)); 1258 } else { 1259 Stat s; 1260 attrib_clear(&s.attrib); 1261 s.name = s.long_name = resolvedname; 1262 send_names(id, 1, &s); 1263 } 1264 free(path); 1265 } 1266 1267 static void 1268 process_rename(u_int32_t id) 1269 { 1270 char *oldpath, *newpath; 1271 int r, status; 1272 struct stat sb; 1273 1274 if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 || 1275 (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0) 1276 fatal_fr(r, "parse"); 1277 1278 debug3("request %u: rename", id); 1279 logit("rename old \"%s\" new \"%s\"", oldpath, newpath); 1280 status = SSH2_FX_FAILURE; 1281 if (lstat(oldpath, &sb) == -1) 1282 status = errno_to_portable(errno); 1283 else if (S_ISREG(sb.st_mode)) { 1284 /* Race-free rename of regular files */ 1285 if (link(oldpath, newpath) == -1) { 1286 if (errno == EOPNOTSUPP || errno == ENOSYS 1287 #ifdef EXDEV 1288 || errno == EXDEV 1289 #endif 1290 #ifdef LINK_OPNOTSUPP_ERRNO 1291 || errno == LINK_OPNOTSUPP_ERRNO 1292 #endif 1293 ) { 1294 struct stat st; 1295 1296 /* 1297 * fs doesn't support links, so fall back to 1298 * stat+rename. This is racy. 1299 */ 1300 if (stat(newpath, &st) == -1) { 1301 if (rename(oldpath, newpath) == -1) 1302 status = 1303 errno_to_portable(errno); 1304 else 1305 status = SSH2_FX_OK; 1306 } 1307 } else { 1308 status = errno_to_portable(errno); 1309 } 1310 } else if (unlink(oldpath) == -1) { 1311 status = errno_to_portable(errno); 1312 /* clean spare link */ 1313 unlink(newpath); 1314 } else 1315 status = SSH2_FX_OK; 1316 } else if (stat(newpath, &sb) == -1) { 1317 if (rename(oldpath, newpath) == -1) 1318 status = errno_to_portable(errno); 1319 else 1320 status = SSH2_FX_OK; 1321 } 1322 send_status(id, status); 1323 free(oldpath); 1324 free(newpath); 1325 } 1326 1327 static void 1328 process_readlink(u_int32_t id) 1329 { 1330 int r, len; 1331 char buf[PATH_MAX]; 1332 char *path; 1333 1334 if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) 1335 fatal_fr(r, "parse"); 1336 1337 debug3("request %u: readlink", id); 1338 verbose("readlink \"%s\"", path); 1339 if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1) 1340 send_status(id, errno_to_portable(errno)); 1341 else { 1342 Stat s; 1343 1344 buf[len] = '\0'; 1345 attrib_clear(&s.attrib); 1346 s.name = s.long_name = buf; 1347 send_names(id, 1, &s); 1348 } 1349 free(path); 1350 } 1351 1352 static void 1353 process_symlink(u_int32_t id) 1354 { 1355 char *oldpath, *newpath; 1356 int r, status; 1357 1358 if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 || 1359 (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0) 1360 fatal_fr(r, "parse"); 1361 1362 debug3("request %u: symlink", id); 1363 logit("symlink old \"%s\" new \"%s\"", oldpath, newpath); 1364 /* this will fail if 'newpath' exists */ 1365 r = symlink(oldpath, newpath); 1366 status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 1367 send_status(id, status); 1368 free(oldpath); 1369 free(newpath); 1370 } 1371 1372 static void 1373 process_extended_posix_rename(u_int32_t id) 1374 { 1375 char *oldpath, *newpath; 1376 int r, status; 1377 1378 if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 || 1379 (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0) 1380 fatal_fr(r, "parse"); 1381 1382 debug3("request %u: posix-rename", id); 1383 logit("posix-rename old \"%s\" new \"%s\"", oldpath, newpath); 1384 r = rename(oldpath, newpath); 1385 status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 1386 send_status(id, status); 1387 free(oldpath); 1388 free(newpath); 1389 } 1390 1391 static void 1392 process_extended_statvfs(u_int32_t id) 1393 { 1394 char *path; 1395 struct statvfs st; 1396 int r; 1397 1398 if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) 1399 fatal_fr(r, "parse"); 1400 debug3("request %u: statvfs", id); 1401 logit("statvfs \"%s\"", path); 1402 1403 if (statvfs(path, &st) != 0) 1404 send_status(id, errno_to_portable(errno)); 1405 else 1406 send_statvfs(id, &st); 1407 free(path); 1408 } 1409 1410 static void 1411 process_extended_fstatvfs(u_int32_t id) 1412 { 1413 int r, handle, fd; 1414 struct statvfs st; 1415 1416 if ((r = get_handle(iqueue, &handle)) != 0) 1417 fatal_fr(r, "parse"); 1418 debug("request %u: fstatvfs \"%s\" (handle %u)", 1419 id, handle_to_name(handle), handle); 1420 if ((fd = handle_to_fd(handle)) < 0) { 1421 send_status(id, SSH2_FX_FAILURE); 1422 return; 1423 } 1424 if (fstatvfs(fd, &st) != 0) 1425 send_status(id, errno_to_portable(errno)); 1426 else 1427 send_statvfs(id, &st); 1428 } 1429 1430 static void 1431 process_extended_hardlink(u_int32_t id) 1432 { 1433 char *oldpath, *newpath; 1434 int r, status; 1435 1436 if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 || 1437 (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0) 1438 fatal_fr(r, "parse"); 1439 1440 debug3("request %u: hardlink", id); 1441 logit("hardlink old \"%s\" new \"%s\"", oldpath, newpath); 1442 r = link(oldpath, newpath); 1443 status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 1444 send_status(id, status); 1445 free(oldpath); 1446 free(newpath); 1447 } 1448 1449 static void 1450 process_extended_fsync(u_int32_t id) 1451 { 1452 int handle, fd, r, status = SSH2_FX_OP_UNSUPPORTED; 1453 1454 if ((r = get_handle(iqueue, &handle)) != 0) 1455 fatal_fr(r, "parse"); 1456 debug3("request %u: fsync (handle %u)", id, handle); 1457 verbose("fsync \"%s\"", handle_to_name(handle)); 1458 if ((fd = handle_to_fd(handle)) < 0) 1459 status = SSH2_FX_NO_SUCH_FILE; 1460 else if (handle_is_ok(handle, HANDLE_FILE)) { 1461 r = fsync(fd); 1462 status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; 1463 } 1464 send_status(id, status); 1465 } 1466 1467 static void 1468 process_extended_lsetstat(u_int32_t id) 1469 { 1470 Attrib a; 1471 char *name; 1472 int r, status = SSH2_FX_OK; 1473 1474 if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || 1475 (r = decode_attrib(iqueue, &a)) != 0) 1476 fatal_fr(r, "parse"); 1477 1478 debug("request %u: lsetstat name \"%s\"", id, name); 1479 if (a.flags & SSH2_FILEXFER_ATTR_SIZE) { 1480 /* nonsensical for links */ 1481 status = SSH2_FX_BAD_MESSAGE; 1482 goto out; 1483 } 1484 if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { 1485 logit("set \"%s\" mode %04o", name, a.perm); 1486 r = fchmodat(AT_FDCWD, name, 1487 a.perm & 07777, AT_SYMLINK_NOFOLLOW); 1488 if (r == -1) 1489 status = errno_to_portable(errno); 1490 } 1491 if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) { 1492 char buf[64]; 1493 time_t t = a.mtime; 1494 1495 strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S", 1496 localtime(&t)); 1497 logit("set \"%s\" modtime %s", name, buf); 1498 r = utimensat(AT_FDCWD, name, 1499 attrib_to_ts(&a), AT_SYMLINK_NOFOLLOW); 1500 if (r == -1) 1501 status = errno_to_portable(errno); 1502 } 1503 if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) { 1504 logit("set \"%s\" owner %lu group %lu", name, 1505 (u_long)a.uid, (u_long)a.gid); 1506 r = fchownat(AT_FDCWD, name, a.uid, a.gid, 1507 AT_SYMLINK_NOFOLLOW); 1508 if (r == -1) 1509 status = errno_to_portable(errno); 1510 } 1511 out: 1512 send_status(id, status); 1513 free(name); 1514 } 1515 1516 static void 1517 process_extended_limits(u_int32_t id) 1518 { 1519 struct sshbuf *msg; 1520 int r; 1521 uint64_t nfiles = 0; 1522 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE) 1523 struct rlimit rlim; 1524 #endif 1525 1526 debug("request %u: limits", id); 1527 1528 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE) 1529 if (getrlimit(RLIMIT_NOFILE, &rlim) != -1 && rlim.rlim_cur > 5) 1530 nfiles = rlim.rlim_cur - 5; /* stdio(3) + syslog + spare */ 1531 #endif 1532 1533 if ((msg = sshbuf_new()) == NULL) 1534 fatal_f("sshbuf_new failed"); 1535 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED_REPLY)) != 0 || 1536 (r = sshbuf_put_u32(msg, id)) != 0 || 1537 /* max-packet-length */ 1538 (r = sshbuf_put_u64(msg, SFTP_MAX_MSG_LENGTH)) != 0 || 1539 /* max-read-length */ 1540 (r = sshbuf_put_u64(msg, SFTP_MAX_READ_LENGTH)) != 0 || 1541 /* max-write-length */ 1542 (r = sshbuf_put_u64(msg, SFTP_MAX_MSG_LENGTH - 1024)) != 0 || 1543 /* max-open-handles */ 1544 (r = sshbuf_put_u64(msg, nfiles)) != 0) 1545 fatal_fr(r, "compose"); 1546 send_msg(msg); 1547 sshbuf_free(msg); 1548 } 1549 1550 static void 1551 process_extended_expand(u_int32_t id) 1552 { 1553 char cwd[PATH_MAX], resolvedname[PATH_MAX]; 1554 char *path, *npath; 1555 int r; 1556 Stat s; 1557 1558 if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) 1559 fatal_fr(r, "parse"); 1560 if (getcwd(cwd, sizeof(cwd)) == NULL) { 1561 send_status(id, errno_to_portable(errno)); 1562 goto out; 1563 } 1564 1565 debug3("request %u: expand, original \"%s\"", id, path); 1566 if (path[0] == '\0') { 1567 /* empty path */ 1568 free(path); 1569 path = xstrdup("."); 1570 } else if (*path == '~') { 1571 /* ~ expand path */ 1572 /* Special-case for "~" and "~/" to respect homedir flag */ 1573 if (strcmp(path, "~") == 0) { 1574 free(path); 1575 path = xstrdup(cwd); 1576 } else if (strncmp(path, "~/", 2) == 0) { 1577 npath = xstrdup(path + 2); 1578 free(path); 1579 xasprintf(&path, "%s/%s", cwd, npath); 1580 free(npath); 1581 } else { 1582 /* ~user expansions */ 1583 if (tilde_expand(path, pw->pw_uid, &npath) != 0) { 1584 send_status_errmsg(id, 1585 errno_to_portable(ENOENT), "no such user"); 1586 goto out; 1587 } 1588 free(path); 1589 path = npath; 1590 } 1591 } else if (*path != '/') { 1592 /* relative path */ 1593 xasprintf(&npath, "%s/%s", cwd, path); 1594 free(path); 1595 path = npath; 1596 } 1597 verbose("expand \"%s\"", path); 1598 if (sftp_realpath(path, resolvedname) == NULL) { 1599 send_status(id, errno_to_portable(errno)); 1600 goto out; 1601 } 1602 attrib_clear(&s.attrib); 1603 s.name = s.long_name = resolvedname; 1604 send_names(id, 1, &s); 1605 out: 1606 free(path); 1607 } 1608 1609 static void 1610 process_extended_copy_data(u_int32_t id) 1611 { 1612 u_char buf[64*1024]; 1613 int read_handle, read_fd, write_handle, write_fd; 1614 u_int64_t len, read_off, read_len, write_off; 1615 int r, copy_until_eof, status = SSH2_FX_OP_UNSUPPORTED; 1616 size_t ret; 1617 1618 if ((r = get_handle(iqueue, &read_handle)) != 0 || 1619 (r = sshbuf_get_u64(iqueue, &read_off)) != 0 || 1620 (r = sshbuf_get_u64(iqueue, &read_len)) != 0 || 1621 (r = get_handle(iqueue, &write_handle)) != 0 || 1622 (r = sshbuf_get_u64(iqueue, &write_off)) != 0) 1623 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1624 1625 debug("request %u: copy-data from \"%s\" (handle %d) off %llu len %llu " 1626 "to \"%s\" (handle %d) off %llu", 1627 id, handle_to_name(read_handle), read_handle, 1628 (unsigned long long)read_off, (unsigned long long)read_len, 1629 handle_to_name(write_handle), write_handle, 1630 (unsigned long long)write_off); 1631 1632 /* For read length of 0, we read until EOF. */ 1633 if (read_len == 0) { 1634 read_len = (u_int64_t)-1 - read_off; 1635 copy_until_eof = 1; 1636 } else 1637 copy_until_eof = 0; 1638 1639 read_fd = handle_to_fd(read_handle); 1640 write_fd = handle_to_fd(write_handle); 1641 1642 /* Disallow reading & writing to the same handle or same path or dirs */ 1643 if (read_handle == write_handle || read_fd < 0 || write_fd < 0 || 1644 !strcmp(handle_to_name(read_handle), handle_to_name(write_handle))) { 1645 status = SSH2_FX_FAILURE; 1646 goto out; 1647 } 1648 1649 if (lseek(read_fd, read_off, SEEK_SET) < 0) { 1650 status = errno_to_portable(errno); 1651 error("%s: read_seek failed", __func__); 1652 goto out; 1653 } 1654 1655 if ((handle_to_flags(write_handle) & O_APPEND) == 0 && 1656 lseek(write_fd, write_off, SEEK_SET) < 0) { 1657 status = errno_to_portable(errno); 1658 error("%s: write_seek failed", __func__); 1659 goto out; 1660 } 1661 1662 /* Process the request in chunks. */ 1663 while (read_len > 0 || copy_until_eof) { 1664 len = MINIMUM(sizeof(buf), read_len); 1665 read_len -= len; 1666 1667 ret = atomicio(read, read_fd, buf, len); 1668 if (ret == 0 && errno == EPIPE) { 1669 status = copy_until_eof ? SSH2_FX_OK : SSH2_FX_EOF; 1670 break; 1671 } else if (ret == 0) { 1672 status = errno_to_portable(errno); 1673 error("%s: read failed: %s", __func__, strerror(errno)); 1674 break; 1675 } 1676 len = ret; 1677 handle_update_read(read_handle, len); 1678 1679 ret = atomicio(vwrite, write_fd, buf, len); 1680 if (ret != len) { 1681 status = errno_to_portable(errno); 1682 error("%s: write failed: %llu != %llu: %s", __func__, 1683 (unsigned long long)ret, (unsigned long long)len, 1684 strerror(errno)); 1685 break; 1686 } 1687 handle_update_write(write_handle, len); 1688 } 1689 1690 if (read_len == 0) 1691 status = SSH2_FX_OK; 1692 1693 out: 1694 send_status(id, status); 1695 } 1696 1697 static void 1698 process_extended_home_directory(u_int32_t id) 1699 { 1700 char *username; 1701 struct passwd *user_pw; 1702 int r; 1703 Stat s; 1704 1705 if ((r = sshbuf_get_cstring(iqueue, &username, NULL)) != 0) 1706 fatal_fr(r, "parse"); 1707 1708 debug3("request %u: home-directory \"%s\"", id, username); 1709 if ((user_pw = getpwnam(username)) == NULL) { 1710 send_status(id, SSH2_FX_FAILURE); 1711 goto out; 1712 } 1713 1714 verbose("home-directory \"%s\"", pw->pw_dir); 1715 attrib_clear(&s.attrib); 1716 s.name = s.long_name = pw->pw_dir; 1717 send_names(id, 1, &s); 1718 out: 1719 free(username); 1720 } 1721 1722 static void 1723 process_extended_get_users_groups_by_id(u_int32_t id) 1724 { 1725 struct passwd *user_pw; 1726 struct group *gr; 1727 struct sshbuf *uids, *gids, *usernames, *groupnames, *msg; 1728 int r; 1729 u_int n, nusers = 0, ngroups = 0; 1730 const char *name; 1731 1732 if ((usernames = sshbuf_new()) == NULL || 1733 (groupnames = sshbuf_new()) == NULL || 1734 (msg = sshbuf_new()) == NULL) 1735 fatal_f("sshbuf_new failed"); 1736 if ((r = sshbuf_froms(iqueue, &uids)) != 0 || 1737 (r = sshbuf_froms(iqueue, &gids)) != 0) 1738 fatal_fr(r, "parse"); 1739 debug_f("uids len = %zu, gids len = %zu", 1740 sshbuf_len(uids), sshbuf_len(gids)); 1741 while (sshbuf_len(uids) != 0) { 1742 if ((r = sshbuf_get_u32(uids, &n)) != 0) 1743 fatal_fr(r, "parse inner uid"); 1744 user_pw = getpwuid((uid_t)n); 1745 name = user_pw == NULL ? "" : user_pw->pw_name; 1746 debug3_f("uid %u => \"%s\"", n, name); 1747 if ((r = sshbuf_put_cstring(usernames, name)) != 0) 1748 fatal_fr(r, "assemble uid reply"); 1749 nusers++; 1750 } 1751 while (sshbuf_len(gids) != 0) { 1752 if ((r = sshbuf_get_u32(gids, &n)) != 0) 1753 fatal_fr(r, "parse inner gid"); 1754 gr = getgrgid((gid_t)n); 1755 name = gr == NULL ? "" : gr->gr_name; 1756 debug3_f("gid %u => \"%s\"", n, name); 1757 if ((r = sshbuf_put_cstring(groupnames, name)) != 0) 1758 fatal_fr(r, "assemble gid reply"); 1759 nusers++; 1760 } 1761 verbose("users-groups-by-id: %u users, %u groups", nusers, ngroups); 1762 1763 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED_REPLY)) != 0 || 1764 (r = sshbuf_put_u32(msg, id)) != 0 || 1765 (r = sshbuf_put_stringb(msg, usernames)) != 0 || 1766 (r = sshbuf_put_stringb(msg, groupnames)) != 0) 1767 fatal_fr(r, "compose"); 1768 send_msg(msg); 1769 1770 sshbuf_free(uids); 1771 sshbuf_free(gids); 1772 sshbuf_free(usernames); 1773 sshbuf_free(groupnames); 1774 sshbuf_free(msg); 1775 } 1776 1777 static void 1778 process_extended(u_int32_t id) 1779 { 1780 char *request; 1781 int r; 1782 const struct sftp_handler *exthand; 1783 1784 if ((r = sshbuf_get_cstring(iqueue, &request, NULL)) != 0) 1785 fatal_fr(r, "parse"); 1786 if ((exthand = extended_handler_byname(request)) == NULL) { 1787 error("Unknown extended request \"%.100s\"", request); 1788 send_status(id, SSH2_FX_OP_UNSUPPORTED); /* MUST */ 1789 } else { 1790 if (!request_permitted(exthand)) 1791 send_status(id, SSH2_FX_PERMISSION_DENIED); 1792 else 1793 exthand->handler(id); 1794 } 1795 free(request); 1796 } 1797 1798 /* stolen from ssh-agent */ 1799 1800 static void 1801 process(void) 1802 { 1803 u_int msg_len; 1804 u_int buf_len; 1805 u_int consumed; 1806 u_char type; 1807 const u_char *cp; 1808 int i, r; 1809 u_int32_t id; 1810 1811 buf_len = sshbuf_len(iqueue); 1812 if (buf_len < 5) 1813 return; /* Incomplete message. */ 1814 cp = sshbuf_ptr(iqueue); 1815 msg_len = get_u32(cp); 1816 if (msg_len > SFTP_MAX_MSG_LENGTH) { 1817 error("bad message from %s local user %s", 1818 client_addr, pw->pw_name); 1819 sftp_server_cleanup_exit(11); 1820 } 1821 if (buf_len < msg_len + 4) 1822 return; 1823 if ((r = sshbuf_consume(iqueue, 4)) != 0) 1824 fatal_fr(r, "consume"); 1825 buf_len -= 4; 1826 if ((r = sshbuf_get_u8(iqueue, &type)) != 0) 1827 fatal_fr(r, "parse type"); 1828 1829 switch (type) { 1830 case SSH2_FXP_INIT: 1831 process_init(); 1832 init_done = 1; 1833 break; 1834 case SSH2_FXP_EXTENDED: 1835 if (!init_done) 1836 fatal("Received extended request before init"); 1837 if ((r = sshbuf_get_u32(iqueue, &id)) != 0) 1838 fatal_fr(r, "parse extended ID"); 1839 process_extended(id); 1840 break; 1841 default: 1842 if (!init_done) 1843 fatal("Received %u request before init", type); 1844 if ((r = sshbuf_get_u32(iqueue, &id)) != 0) 1845 fatal_fr(r, "parse ID"); 1846 for (i = 0; handlers[i].handler != NULL; i++) { 1847 if (type == handlers[i].type) { 1848 if (!request_permitted(&handlers[i])) { 1849 send_status(id, 1850 SSH2_FX_PERMISSION_DENIED); 1851 } else { 1852 handlers[i].handler(id); 1853 } 1854 break; 1855 } 1856 } 1857 if (handlers[i].handler == NULL) 1858 error("Unknown message %u", type); 1859 } 1860 /* discard the remaining bytes from the current packet */ 1861 if (buf_len < sshbuf_len(iqueue)) { 1862 error("iqueue grew unexpectedly"); 1863 sftp_server_cleanup_exit(255); 1864 } 1865 consumed = buf_len - sshbuf_len(iqueue); 1866 if (msg_len < consumed) { 1867 error("msg_len %u < consumed %u", msg_len, consumed); 1868 sftp_server_cleanup_exit(255); 1869 } 1870 if (msg_len > consumed && 1871 (r = sshbuf_consume(iqueue, msg_len - consumed)) != 0) 1872 fatal_fr(r, "consume"); 1873 } 1874 1875 /* Cleanup handler that logs active handles upon normal exit */ 1876 void 1877 sftp_server_cleanup_exit(int i) 1878 { 1879 if (pw != NULL && client_addr != NULL) { 1880 handle_log_exit(); 1881 logit("session closed for local user %s from [%s]", 1882 pw->pw_name, client_addr); 1883 } 1884 _exit(i); 1885 } 1886 1887 static void 1888 sftp_server_usage(void) 1889 { 1890 extern char *__progname; 1891 1892 fprintf(stderr, 1893 "usage: %s [-ehR] [-d start_directory] [-f log_facility] " 1894 "[-l log_level]\n\t[-P denied_requests] " 1895 "[-p allowed_requests] [-u umask]\n" 1896 " %s -Q protocol_feature\n", 1897 __progname, __progname); 1898 exit(1); 1899 } 1900 1901 int 1902 sftp_server_main(int argc, char **argv, struct passwd *user_pw) 1903 { 1904 int i, r, in, out, ch, skipargs = 0, log_stderr = 0; 1905 ssize_t len, olen; 1906 SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; 1907 char *cp, *homedir = NULL, uidstr[32], buf[4*4096]; 1908 long mask; 1909 1910 extern char *optarg; 1911 extern char *__progname; 1912 1913 __progname = ssh_get_progname(argv[0]); 1914 log_init(__progname, log_level, log_facility, log_stderr); 1915 1916 pw = pwcopy(user_pw); 1917 1918 while (!skipargs && (ch = getopt(argc, argv, 1919 "d:f:l:P:p:Q:u:cehR")) != -1) { 1920 switch (ch) { 1921 case 'Q': 1922 if (strcasecmp(optarg, "requests") != 0) { 1923 fprintf(stderr, "Invalid query type\n"); 1924 exit(1); 1925 } 1926 for (i = 0; handlers[i].handler != NULL; i++) 1927 printf("%s\n", handlers[i].name); 1928 for (i = 0; extended_handlers[i].handler != NULL; i++) 1929 printf("%s\n", extended_handlers[i].name); 1930 exit(0); 1931 break; 1932 case 'R': 1933 readonly = 1; 1934 break; 1935 case 'c': 1936 /* 1937 * Ignore all arguments if we are invoked as a 1938 * shell using "sftp-server -c command" 1939 */ 1940 skipargs = 1; 1941 break; 1942 case 'e': 1943 log_stderr = 1; 1944 break; 1945 case 'l': 1946 log_level = log_level_number(optarg); 1947 if (log_level == SYSLOG_LEVEL_NOT_SET) 1948 error("Invalid log level \"%s\"", optarg); 1949 break; 1950 case 'f': 1951 log_facility = log_facility_number(optarg); 1952 if (log_facility == SYSLOG_FACILITY_NOT_SET) 1953 error("Invalid log facility \"%s\"", optarg); 1954 break; 1955 case 'd': 1956 cp = tilde_expand_filename(optarg, user_pw->pw_uid); 1957 snprintf(uidstr, sizeof(uidstr), "%llu", 1958 (unsigned long long)pw->pw_uid); 1959 homedir = percent_expand(cp, "d", user_pw->pw_dir, 1960 "u", user_pw->pw_name, "U", uidstr, (char *)NULL); 1961 free(cp); 1962 break; 1963 case 'p': 1964 if (request_allowlist != NULL) 1965 fatal("Permitted requests already set"); 1966 request_allowlist = xstrdup(optarg); 1967 break; 1968 case 'P': 1969 if (request_denylist != NULL) 1970 fatal("Refused requests already set"); 1971 request_denylist = xstrdup(optarg); 1972 break; 1973 case 'u': 1974 errno = 0; 1975 mask = strtol(optarg, &cp, 8); 1976 if (mask < 0 || mask > 0777 || *cp != '\0' || 1977 cp == optarg || (mask == 0 && errno != 0)) 1978 fatal("Invalid umask \"%s\"", optarg); 1979 (void)umask((mode_t)mask); 1980 break; 1981 case 'h': 1982 default: 1983 sftp_server_usage(); 1984 } 1985 } 1986 1987 log_init(__progname, log_level, log_facility, log_stderr); 1988 1989 /* 1990 * On platforms where we can, avoid making /proc/self/{mem,maps} 1991 * available to the user so that sftp access doesn't automatically 1992 * imply arbitrary code execution access that will break 1993 * restricted configurations. 1994 */ 1995 platform_disable_tracing(1); /* strict */ 1996 1997 /* Drop any fine-grained privileges we don't need */ 1998 platform_pledge_sftp_server(); 1999 2000 if ((cp = getenv("SSH_CONNECTION")) != NULL) { 2001 client_addr = xstrdup(cp); 2002 if ((cp = strchr(client_addr, ' ')) == NULL) { 2003 error("Malformed SSH_CONNECTION variable: \"%s\"", 2004 getenv("SSH_CONNECTION")); 2005 sftp_server_cleanup_exit(255); 2006 } 2007 *cp = '\0'; 2008 } else 2009 client_addr = xstrdup("UNKNOWN"); 2010 2011 logit("session opened for local user %s from [%s]", 2012 pw->pw_name, client_addr); 2013 2014 in = STDIN_FILENO; 2015 out = STDOUT_FILENO; 2016 2017 #ifdef HAVE_CYGWIN 2018 setmode(in, O_BINARY); 2019 setmode(out, O_BINARY); 2020 #endif 2021 2022 if ((iqueue = sshbuf_new()) == NULL) 2023 fatal_f("sshbuf_new failed"); 2024 if ((oqueue = sshbuf_new()) == NULL) 2025 fatal_f("sshbuf_new failed"); 2026 2027 if (homedir != NULL) { 2028 if (chdir(homedir) != 0) { 2029 error("chdir to \"%s\" failed: %s", homedir, 2030 strerror(errno)); 2031 } 2032 } 2033 2034 for (;;) { 2035 struct pollfd pfd[2]; 2036 2037 memset(pfd, 0, sizeof pfd); 2038 pfd[0].fd = pfd[1].fd = -1; 2039 2040 /* 2041 * Ensure that we can read a full buffer and handle 2042 * the worst-case length packet it can generate, 2043 * otherwise apply backpressure by stopping reads. 2044 */ 2045 if ((r = sshbuf_check_reserve(iqueue, sizeof(buf))) == 0 && 2046 (r = sshbuf_check_reserve(oqueue, 2047 SFTP_MAX_MSG_LENGTH)) == 0) { 2048 pfd[0].fd = in; 2049 pfd[0].events = POLLIN; 2050 } 2051 else if (r != SSH_ERR_NO_BUFFER_SPACE) 2052 fatal_fr(r, "reserve"); 2053 2054 olen = sshbuf_len(oqueue); 2055 if (olen > 0) { 2056 pfd[1].fd = out; 2057 pfd[1].events = POLLOUT; 2058 } 2059 2060 if (poll(pfd, 2, -1) == -1) { 2061 if (errno == EINTR) 2062 continue; 2063 error("poll: %s", strerror(errno)); 2064 sftp_server_cleanup_exit(2); 2065 } 2066 2067 /* copy stdin to iqueue */ 2068 if (pfd[0].revents & (POLLIN|POLLHUP)) { 2069 len = read(in, buf, sizeof buf); 2070 if (len == 0) { 2071 debug("read eof"); 2072 sftp_server_cleanup_exit(0); 2073 } else if (len == -1) { 2074 if (errno != EAGAIN && errno != EINTR) { 2075 error("read: %s", strerror(errno)); 2076 sftp_server_cleanup_exit(1); 2077 } 2078 } else if ((r = sshbuf_put(iqueue, buf, len)) != 0) 2079 fatal_fr(r, "sshbuf_put"); 2080 } 2081 /* send oqueue to stdout */ 2082 if (pfd[1].revents & (POLLOUT|POLLHUP)) { 2083 len = write(out, sshbuf_ptr(oqueue), olen); 2084 if (len == 0 || (len == -1 && errno == EPIPE)) { 2085 debug("write eof"); 2086 sftp_server_cleanup_exit(0); 2087 } else if (len == -1) { 2088 sftp_server_cleanup_exit(1); 2089 if (errno != EAGAIN && errno != EINTR) { 2090 error("write: %s", strerror(errno)); 2091 sftp_server_cleanup_exit(1); 2092 } 2093 } else if ((r = sshbuf_consume(oqueue, len)) != 0) 2094 fatal_fr(r, "consume"); 2095 } 2096 2097 /* 2098 * Process requests from client if we can fit the results 2099 * into the output buffer, otherwise stop processing input 2100 * and let the output queue drain. 2101 */ 2102 r = sshbuf_check_reserve(oqueue, SFTP_MAX_MSG_LENGTH); 2103 if (r == 0) 2104 process(); 2105 else if (r != SSH_ERR_NO_BUFFER_SPACE) 2106 fatal_fr(r, "reserve"); 2107 } 2108 } 2109