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