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