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