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