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