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