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