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