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