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