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