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