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