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