1 /* $OpenBSD: misc.c,v 1.113 2017/08/18 05:48:04 djm Exp $ */ 2 /* 3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 4 * Copyright (c) 2005,2006 Damien Miller. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include "includes.h" 28 29 #include <sys/types.h> 30 #include <sys/ioctl.h> 31 #include <sys/socket.h> 32 #include <sys/stat.h> 33 #include <sys/time.h> 34 #include <sys/wait.h> 35 #include <sys/un.h> 36 37 #include <limits.h> 38 #ifdef HAVE_LIBGEN_H 39 # include <libgen.h> 40 #endif 41 #include <signal.h> 42 #include <stdarg.h> 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <time.h> 47 #include <unistd.h> 48 49 #include <netinet/in.h> 50 #include <netinet/in_systm.h> 51 #include <netinet/ip.h> 52 #include <netinet/tcp.h> 53 54 #include <ctype.h> 55 #include <errno.h> 56 #include <fcntl.h> 57 #include <netdb.h> 58 #ifdef HAVE_PATHS_H 59 # include <paths.h> 60 #include <pwd.h> 61 #endif 62 #ifdef SSH_TUN_OPENBSD 63 #include <net/if.h> 64 #endif 65 66 #include "xmalloc.h" 67 #include "misc.h" 68 #include "log.h" 69 #include "ssh.h" 70 #include "sshbuf.h" 71 #include "ssherr.h" 72 #include "uidswap.h" 73 #include "platform.h" 74 75 /* remove newline at end of string */ 76 char * 77 chop(char *s) 78 { 79 char *t = s; 80 while (*t) { 81 if (*t == '\n' || *t == '\r') { 82 *t = '\0'; 83 return s; 84 } 85 t++; 86 } 87 return s; 88 89 } 90 91 /* set/unset filedescriptor to non-blocking */ 92 int 93 set_nonblock(int fd) 94 { 95 int val; 96 97 val = fcntl(fd, F_GETFL); 98 if (val < 0) { 99 error("fcntl(%d, F_GETFL): %s", fd, strerror(errno)); 100 return (-1); 101 } 102 if (val & O_NONBLOCK) { 103 debug3("fd %d is O_NONBLOCK", fd); 104 return (0); 105 } 106 debug2("fd %d setting O_NONBLOCK", fd); 107 val |= O_NONBLOCK; 108 if (fcntl(fd, F_SETFL, val) == -1) { 109 debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s", fd, 110 strerror(errno)); 111 return (-1); 112 } 113 return (0); 114 } 115 116 int 117 unset_nonblock(int fd) 118 { 119 int val; 120 121 val = fcntl(fd, F_GETFL); 122 if (val < 0) { 123 error("fcntl(%d, F_GETFL): %s", fd, strerror(errno)); 124 return (-1); 125 } 126 if (!(val & O_NONBLOCK)) { 127 debug3("fd %d is not O_NONBLOCK", fd); 128 return (0); 129 } 130 debug("fd %d clearing O_NONBLOCK", fd); 131 val &= ~O_NONBLOCK; 132 if (fcntl(fd, F_SETFL, val) == -1) { 133 debug("fcntl(%d, F_SETFL, ~O_NONBLOCK): %s", 134 fd, strerror(errno)); 135 return (-1); 136 } 137 return (0); 138 } 139 140 const char * 141 ssh_gai_strerror(int gaierr) 142 { 143 if (gaierr == EAI_SYSTEM && errno != 0) 144 return strerror(errno); 145 return gai_strerror(gaierr); 146 } 147 148 /* disable nagle on socket */ 149 void 150 set_nodelay(int fd) 151 { 152 int opt; 153 socklen_t optlen; 154 155 optlen = sizeof opt; 156 if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) { 157 debug("getsockopt TCP_NODELAY: %.100s", strerror(errno)); 158 return; 159 } 160 if (opt == 1) { 161 debug2("fd %d is TCP_NODELAY", fd); 162 return; 163 } 164 opt = 1; 165 debug2("fd %d setting TCP_NODELAY", fd); 166 if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof opt) == -1) 167 error("setsockopt TCP_NODELAY: %.100s", strerror(errno)); 168 } 169 170 /* Characters considered whitespace in strsep calls. */ 171 #define WHITESPACE " \t\r\n" 172 #define QUOTE "\"" 173 174 /* return next token in configuration line */ 175 char * 176 strdelim(char **s) 177 { 178 char *old; 179 int wspace = 0; 180 181 if (*s == NULL) 182 return NULL; 183 184 old = *s; 185 186 *s = strpbrk(*s, WHITESPACE QUOTE "="); 187 if (*s == NULL) 188 return (old); 189 190 if (*s[0] == '\"') { 191 memmove(*s, *s + 1, strlen(*s)); /* move nul too */ 192 /* Find matching quote */ 193 if ((*s = strpbrk(*s, QUOTE)) == NULL) { 194 return (NULL); /* no matching quote */ 195 } else { 196 *s[0] = '\0'; 197 *s += strspn(*s + 1, WHITESPACE) + 1; 198 return (old); 199 } 200 } 201 202 /* Allow only one '=' to be skipped */ 203 if (*s[0] == '=') 204 wspace = 1; 205 *s[0] = '\0'; 206 207 /* Skip any extra whitespace after first token */ 208 *s += strspn(*s + 1, WHITESPACE) + 1; 209 if (*s[0] == '=' && !wspace) 210 *s += strspn(*s + 1, WHITESPACE) + 1; 211 212 return (old); 213 } 214 215 struct passwd * 216 pwcopy(struct passwd *pw) 217 { 218 struct passwd *copy = xcalloc(1, sizeof(*copy)); 219 220 copy->pw_name = xstrdup(pw->pw_name); 221 copy->pw_passwd = xstrdup(pw->pw_passwd); 222 #ifdef HAVE_STRUCT_PASSWD_PW_GECOS 223 copy->pw_gecos = xstrdup(pw->pw_gecos); 224 #endif 225 copy->pw_uid = pw->pw_uid; 226 copy->pw_gid = pw->pw_gid; 227 #ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE 228 copy->pw_expire = pw->pw_expire; 229 #endif 230 #ifdef HAVE_STRUCT_PASSWD_PW_CHANGE 231 copy->pw_change = pw->pw_change; 232 #endif 233 #ifdef HAVE_STRUCT_PASSWD_PW_CLASS 234 copy->pw_class = xstrdup(pw->pw_class); 235 #endif 236 copy->pw_dir = xstrdup(pw->pw_dir); 237 copy->pw_shell = xstrdup(pw->pw_shell); 238 return copy; 239 } 240 241 /* 242 * Convert ASCII string to TCP/IP port number. 243 * Port must be >=0 and <=65535. 244 * Return -1 if invalid. 245 */ 246 int 247 a2port(const char *s) 248 { 249 long long port; 250 const char *errstr; 251 252 port = strtonum(s, 0, 65535, &errstr); 253 if (errstr != NULL) 254 return -1; 255 return (int)port; 256 } 257 258 int 259 a2tun(const char *s, int *remote) 260 { 261 const char *errstr = NULL; 262 char *sp, *ep; 263 int tun; 264 265 if (remote != NULL) { 266 *remote = SSH_TUNID_ANY; 267 sp = xstrdup(s); 268 if ((ep = strchr(sp, ':')) == NULL) { 269 free(sp); 270 return (a2tun(s, NULL)); 271 } 272 ep[0] = '\0'; ep++; 273 *remote = a2tun(ep, NULL); 274 tun = a2tun(sp, NULL); 275 free(sp); 276 return (*remote == SSH_TUNID_ERR ? *remote : tun); 277 } 278 279 if (strcasecmp(s, "any") == 0) 280 return (SSH_TUNID_ANY); 281 282 tun = strtonum(s, 0, SSH_TUNID_MAX, &errstr); 283 if (errstr != NULL) 284 return (SSH_TUNID_ERR); 285 286 return (tun); 287 } 288 289 #define SECONDS 1 290 #define MINUTES (SECONDS * 60) 291 #define HOURS (MINUTES * 60) 292 #define DAYS (HOURS * 24) 293 #define WEEKS (DAYS * 7) 294 295 /* 296 * Convert a time string into seconds; format is 297 * a sequence of: 298 * time[qualifier] 299 * 300 * Valid time qualifiers are: 301 * <none> seconds 302 * s|S seconds 303 * m|M minutes 304 * h|H hours 305 * d|D days 306 * w|W weeks 307 * 308 * Examples: 309 * 90m 90 minutes 310 * 1h30m 90 minutes 311 * 2d 2 days 312 * 1w 1 week 313 * 314 * Return -1 if time string is invalid. 315 */ 316 long 317 convtime(const char *s) 318 { 319 long total, secs, multiplier = 1; 320 const char *p; 321 char *endp; 322 323 errno = 0; 324 total = 0; 325 p = s; 326 327 if (p == NULL || *p == '\0') 328 return -1; 329 330 while (*p) { 331 secs = strtol(p, &endp, 10); 332 if (p == endp || 333 (errno == ERANGE && (secs == LONG_MIN || secs == LONG_MAX)) || 334 secs < 0) 335 return -1; 336 337 switch (*endp++) { 338 case '\0': 339 endp--; 340 break; 341 case 's': 342 case 'S': 343 break; 344 case 'm': 345 case 'M': 346 multiplier = MINUTES; 347 break; 348 case 'h': 349 case 'H': 350 multiplier = HOURS; 351 break; 352 case 'd': 353 case 'D': 354 multiplier = DAYS; 355 break; 356 case 'w': 357 case 'W': 358 multiplier = WEEKS; 359 break; 360 default: 361 return -1; 362 } 363 if (secs >= LONG_MAX / multiplier) 364 return -1; 365 secs *= multiplier; 366 if (total >= LONG_MAX - secs) 367 return -1; 368 total += secs; 369 if (total < 0) 370 return -1; 371 p = endp; 372 } 373 374 return total; 375 } 376 377 /* 378 * Returns a standardized host+port identifier string. 379 * Caller must free returned string. 380 */ 381 char * 382 put_host_port(const char *host, u_short port) 383 { 384 char *hoststr; 385 386 if (port == 0 || port == SSH_DEFAULT_PORT) 387 return(xstrdup(host)); 388 if (asprintf(&hoststr, "[%s]:%d", host, (int)port) < 0) 389 fatal("put_host_port: asprintf: %s", strerror(errno)); 390 debug3("put_host_port: %s", hoststr); 391 return hoststr; 392 } 393 394 /* 395 * Search for next delimiter between hostnames/addresses and ports. 396 * Argument may be modified (for termination). 397 * Returns *cp if parsing succeeds. 398 * *cp is set to the start of the next delimiter, if one was found. 399 * If this is the last field, *cp is set to NULL. 400 */ 401 char * 402 hpdelim(char **cp) 403 { 404 char *s, *old; 405 406 if (cp == NULL || *cp == NULL) 407 return NULL; 408 409 old = s = *cp; 410 if (*s == '[') { 411 if ((s = strchr(s, ']')) == NULL) 412 return NULL; 413 else 414 s++; 415 } else if ((s = strpbrk(s, ":/")) == NULL) 416 s = *cp + strlen(*cp); /* skip to end (see first case below) */ 417 418 switch (*s) { 419 case '\0': 420 *cp = NULL; /* no more fields*/ 421 break; 422 423 case ':': 424 case '/': 425 *s = '\0'; /* terminate */ 426 *cp = s + 1; 427 break; 428 429 default: 430 return NULL; 431 } 432 433 return old; 434 } 435 436 char * 437 cleanhostname(char *host) 438 { 439 if (*host == '[' && host[strlen(host) - 1] == ']') { 440 host[strlen(host) - 1] = '\0'; 441 return (host + 1); 442 } else 443 return host; 444 } 445 446 char * 447 colon(char *cp) 448 { 449 int flag = 0; 450 451 if (*cp == ':') /* Leading colon is part of file name. */ 452 return NULL; 453 if (*cp == '[') 454 flag = 1; 455 456 for (; *cp; ++cp) { 457 if (*cp == '@' && *(cp+1) == '[') 458 flag = 1; 459 if (*cp == ']' && *(cp+1) == ':' && flag) 460 return (cp+1); 461 if (*cp == ':' && !flag) 462 return (cp); 463 if (*cp == '/') 464 return NULL; 465 } 466 return NULL; 467 } 468 469 /* 470 * Parse a [user@]host[:port] string. 471 * Caller must free returned user and host. 472 * Any of the pointer return arguments may be NULL (useful for syntax checking). 473 * If user was not specified then *userp will be set to NULL. 474 * If port was not specified then *portp will be -1. 475 * Returns 0 on success, -1 on failure. 476 */ 477 int 478 parse_user_host_port(const char *s, char **userp, char **hostp, int *portp) 479 { 480 char *sdup, *cp, *tmp; 481 char *user = NULL, *host = NULL; 482 int port = -1, ret = -1; 483 484 if (userp != NULL) 485 *userp = NULL; 486 if (hostp != NULL) 487 *hostp = NULL; 488 if (portp != NULL) 489 *portp = -1; 490 491 if ((sdup = tmp = strdup(s)) == NULL) 492 return -1; 493 /* Extract optional username */ 494 if ((cp = strchr(tmp, '@')) != NULL) { 495 *cp = '\0'; 496 if (*tmp == '\0') 497 goto out; 498 if ((user = strdup(tmp)) == NULL) 499 goto out; 500 tmp = cp + 1; 501 } 502 /* Extract mandatory hostname */ 503 if ((cp = hpdelim(&tmp)) == NULL || *cp == '\0') 504 goto out; 505 host = xstrdup(cleanhostname(cp)); 506 /* Convert and verify optional port */ 507 if (tmp != NULL && *tmp != '\0') { 508 if ((port = a2port(tmp)) <= 0) 509 goto out; 510 } 511 /* Success */ 512 if (userp != NULL) { 513 *userp = user; 514 user = NULL; 515 } 516 if (hostp != NULL) { 517 *hostp = host; 518 host = NULL; 519 } 520 if (portp != NULL) 521 *portp = port; 522 ret = 0; 523 out: 524 free(sdup); 525 free(user); 526 free(host); 527 return ret; 528 } 529 530 /* function to assist building execv() arguments */ 531 void 532 addargs(arglist *args, char *fmt, ...) 533 { 534 va_list ap; 535 char *cp; 536 u_int nalloc; 537 int r; 538 539 va_start(ap, fmt); 540 r = vasprintf(&cp, fmt, ap); 541 va_end(ap); 542 if (r == -1) 543 fatal("addargs: argument too long"); 544 545 nalloc = args->nalloc; 546 if (args->list == NULL) { 547 nalloc = 32; 548 args->num = 0; 549 } else if (args->num+2 >= nalloc) 550 nalloc *= 2; 551 552 args->list = xrecallocarray(args->list, args->nalloc, nalloc, sizeof(char *)); 553 args->nalloc = nalloc; 554 args->list[args->num++] = cp; 555 args->list[args->num] = NULL; 556 } 557 558 void 559 replacearg(arglist *args, u_int which, char *fmt, ...) 560 { 561 va_list ap; 562 char *cp; 563 int r; 564 565 va_start(ap, fmt); 566 r = vasprintf(&cp, fmt, ap); 567 va_end(ap); 568 if (r == -1) 569 fatal("replacearg: argument too long"); 570 571 if (which >= args->num) 572 fatal("replacearg: tried to replace invalid arg %d >= %d", 573 which, args->num); 574 free(args->list[which]); 575 args->list[which] = cp; 576 } 577 578 void 579 freeargs(arglist *args) 580 { 581 u_int i; 582 583 if (args->list != NULL) { 584 for (i = 0; i < args->num; i++) 585 free(args->list[i]); 586 free(args->list); 587 args->nalloc = args->num = 0; 588 args->list = NULL; 589 } 590 } 591 592 /* 593 * Expands tildes in the file name. Returns data allocated by xmalloc. 594 * Warning: this calls getpw*. 595 */ 596 char * 597 tilde_expand_filename(const char *filename, uid_t uid) 598 { 599 const char *path, *sep; 600 char user[128], *ret; 601 struct passwd *pw; 602 u_int len, slash; 603 604 if (*filename != '~') 605 return (xstrdup(filename)); 606 filename++; 607 608 path = strchr(filename, '/'); 609 if (path != NULL && path > filename) { /* ~user/path */ 610 slash = path - filename; 611 if (slash > sizeof(user) - 1) 612 fatal("tilde_expand_filename: ~username too long"); 613 memcpy(user, filename, slash); 614 user[slash] = '\0'; 615 if ((pw = getpwnam(user)) == NULL) 616 fatal("tilde_expand_filename: No such user %s", user); 617 } else if ((pw = getpwuid(uid)) == NULL) /* ~/path */ 618 fatal("tilde_expand_filename: No such uid %ld", (long)uid); 619 620 /* Make sure directory has a trailing '/' */ 621 len = strlen(pw->pw_dir); 622 if (len == 0 || pw->pw_dir[len - 1] != '/') 623 sep = "/"; 624 else 625 sep = ""; 626 627 /* Skip leading '/' from specified path */ 628 if (path != NULL) 629 filename = path + 1; 630 631 if (xasprintf(&ret, "%s%s%s", pw->pw_dir, sep, filename) >= PATH_MAX) 632 fatal("tilde_expand_filename: Path too long"); 633 634 return (ret); 635 } 636 637 /* 638 * Expand a string with a set of %[char] escapes. A number of escapes may be 639 * specified as (char *escape_chars, char *replacement) pairs. The list must 640 * be terminated by a NULL escape_char. Returns replaced string in memory 641 * allocated by xmalloc. 642 */ 643 char * 644 percent_expand(const char *string, ...) 645 { 646 #define EXPAND_MAX_KEYS 16 647 u_int num_keys, i, j; 648 struct { 649 const char *key; 650 const char *repl; 651 } keys[EXPAND_MAX_KEYS]; 652 char buf[4096]; 653 va_list ap; 654 655 /* Gather keys */ 656 va_start(ap, string); 657 for (num_keys = 0; num_keys < EXPAND_MAX_KEYS; num_keys++) { 658 keys[num_keys].key = va_arg(ap, char *); 659 if (keys[num_keys].key == NULL) 660 break; 661 keys[num_keys].repl = va_arg(ap, char *); 662 if (keys[num_keys].repl == NULL) 663 fatal("%s: NULL replacement", __func__); 664 } 665 if (num_keys == EXPAND_MAX_KEYS && va_arg(ap, char *) != NULL) 666 fatal("%s: too many keys", __func__); 667 va_end(ap); 668 669 /* Expand string */ 670 *buf = '\0'; 671 for (i = 0; *string != '\0'; string++) { 672 if (*string != '%') { 673 append: 674 buf[i++] = *string; 675 if (i >= sizeof(buf)) 676 fatal("%s: string too long", __func__); 677 buf[i] = '\0'; 678 continue; 679 } 680 string++; 681 /* %% case */ 682 if (*string == '%') 683 goto append; 684 if (*string == '\0') 685 fatal("%s: invalid format", __func__); 686 for (j = 0; j < num_keys; j++) { 687 if (strchr(keys[j].key, *string) != NULL) { 688 i = strlcat(buf, keys[j].repl, sizeof(buf)); 689 if (i >= sizeof(buf)) 690 fatal("%s: string too long", __func__); 691 break; 692 } 693 } 694 if (j >= num_keys) 695 fatal("%s: unknown key %%%c", __func__, *string); 696 } 697 return (xstrdup(buf)); 698 #undef EXPAND_MAX_KEYS 699 } 700 701 /* 702 * Read an entire line from a public key file into a static buffer, discarding 703 * lines that exceed the buffer size. Returns 0 on success, -1 on failure. 704 */ 705 int 706 read_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz, 707 u_long *lineno) 708 { 709 while (fgets(buf, bufsz, f) != NULL) { 710 if (buf[0] == '\0') 711 continue; 712 (*lineno)++; 713 if (buf[strlen(buf) - 1] == '\n' || feof(f)) { 714 return 0; 715 } else { 716 debug("%s: %s line %lu exceeds size limit", __func__, 717 filename, *lineno); 718 /* discard remainder of line */ 719 while (fgetc(f) != '\n' && !feof(f)) 720 ; /* nothing */ 721 } 722 } 723 return -1; 724 } 725 726 int 727 tun_open(int tun, int mode) 728 { 729 #if defined(CUSTOM_SYS_TUN_OPEN) 730 return (sys_tun_open(tun, mode)); 731 #elif defined(SSH_TUN_OPENBSD) 732 struct ifreq ifr; 733 char name[100]; 734 int fd = -1, sock; 735 const char *tunbase = "tun"; 736 737 if (mode == SSH_TUNMODE_ETHERNET) 738 tunbase = "tap"; 739 740 /* Open the tunnel device */ 741 if (tun <= SSH_TUNID_MAX) { 742 snprintf(name, sizeof(name), "/dev/%s%d", tunbase, tun); 743 fd = open(name, O_RDWR); 744 } else if (tun == SSH_TUNID_ANY) { 745 for (tun = 100; tun >= 0; tun--) { 746 snprintf(name, sizeof(name), "/dev/%s%d", 747 tunbase, tun); 748 if ((fd = open(name, O_RDWR)) >= 0) 749 break; 750 } 751 } else { 752 debug("%s: invalid tunnel %u", __func__, tun); 753 return -1; 754 } 755 756 if (fd < 0) { 757 debug("%s: %s open: %s", __func__, name, strerror(errno)); 758 return -1; 759 } 760 761 debug("%s: %s mode %d fd %d", __func__, name, mode, fd); 762 763 /* Bring interface up if it is not already */ 764 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", tunbase, tun); 765 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) 766 goto failed; 767 768 if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) { 769 debug("%s: get interface %s flags: %s", __func__, 770 ifr.ifr_name, strerror(errno)); 771 goto failed; 772 } 773 774 if (!(ifr.ifr_flags & IFF_UP)) { 775 ifr.ifr_flags |= IFF_UP; 776 if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) { 777 debug("%s: activate interface %s: %s", __func__, 778 ifr.ifr_name, strerror(errno)); 779 goto failed; 780 } 781 } 782 783 close(sock); 784 return fd; 785 786 failed: 787 if (fd >= 0) 788 close(fd); 789 if (sock >= 0) 790 close(sock); 791 return -1; 792 #else 793 error("Tunnel interfaces are not supported on this platform"); 794 return (-1); 795 #endif 796 } 797 798 void 799 sanitise_stdfd(void) 800 { 801 int nullfd, dupfd; 802 803 if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 804 fprintf(stderr, "Couldn't open /dev/null: %s\n", 805 strerror(errno)); 806 exit(1); 807 } 808 while (++dupfd <= STDERR_FILENO) { 809 /* Only populate closed fds. */ 810 if (fcntl(dupfd, F_GETFL) == -1 && errno == EBADF) { 811 if (dup2(nullfd, dupfd) == -1) { 812 fprintf(stderr, "dup2: %s\n", strerror(errno)); 813 exit(1); 814 } 815 } 816 } 817 if (nullfd > STDERR_FILENO) 818 close(nullfd); 819 } 820 821 char * 822 tohex(const void *vp, size_t l) 823 { 824 const u_char *p = (const u_char *)vp; 825 char b[3], *r; 826 size_t i, hl; 827 828 if (l > 65536) 829 return xstrdup("tohex: length > 65536"); 830 831 hl = l * 2 + 1; 832 r = xcalloc(1, hl); 833 for (i = 0; i < l; i++) { 834 snprintf(b, sizeof(b), "%02x", p[i]); 835 strlcat(r, b, hl); 836 } 837 return (r); 838 } 839 840 u_int64_t 841 get_u64(const void *vp) 842 { 843 const u_char *p = (const u_char *)vp; 844 u_int64_t v; 845 846 v = (u_int64_t)p[0] << 56; 847 v |= (u_int64_t)p[1] << 48; 848 v |= (u_int64_t)p[2] << 40; 849 v |= (u_int64_t)p[3] << 32; 850 v |= (u_int64_t)p[4] << 24; 851 v |= (u_int64_t)p[5] << 16; 852 v |= (u_int64_t)p[6] << 8; 853 v |= (u_int64_t)p[7]; 854 855 return (v); 856 } 857 858 u_int32_t 859 get_u32(const void *vp) 860 { 861 const u_char *p = (const u_char *)vp; 862 u_int32_t v; 863 864 v = (u_int32_t)p[0] << 24; 865 v |= (u_int32_t)p[1] << 16; 866 v |= (u_int32_t)p[2] << 8; 867 v |= (u_int32_t)p[3]; 868 869 return (v); 870 } 871 872 u_int32_t 873 get_u32_le(const void *vp) 874 { 875 const u_char *p = (const u_char *)vp; 876 u_int32_t v; 877 878 v = (u_int32_t)p[0]; 879 v |= (u_int32_t)p[1] << 8; 880 v |= (u_int32_t)p[2] << 16; 881 v |= (u_int32_t)p[3] << 24; 882 883 return (v); 884 } 885 886 u_int16_t 887 get_u16(const void *vp) 888 { 889 const u_char *p = (const u_char *)vp; 890 u_int16_t v; 891 892 v = (u_int16_t)p[0] << 8; 893 v |= (u_int16_t)p[1]; 894 895 return (v); 896 } 897 898 void 899 put_u64(void *vp, u_int64_t v) 900 { 901 u_char *p = (u_char *)vp; 902 903 p[0] = (u_char)(v >> 56) & 0xff; 904 p[1] = (u_char)(v >> 48) & 0xff; 905 p[2] = (u_char)(v >> 40) & 0xff; 906 p[3] = (u_char)(v >> 32) & 0xff; 907 p[4] = (u_char)(v >> 24) & 0xff; 908 p[5] = (u_char)(v >> 16) & 0xff; 909 p[6] = (u_char)(v >> 8) & 0xff; 910 p[7] = (u_char)v & 0xff; 911 } 912 913 void 914 put_u32(void *vp, u_int32_t v) 915 { 916 u_char *p = (u_char *)vp; 917 918 p[0] = (u_char)(v >> 24) & 0xff; 919 p[1] = (u_char)(v >> 16) & 0xff; 920 p[2] = (u_char)(v >> 8) & 0xff; 921 p[3] = (u_char)v & 0xff; 922 } 923 924 void 925 put_u32_le(void *vp, u_int32_t v) 926 { 927 u_char *p = (u_char *)vp; 928 929 p[0] = (u_char)v & 0xff; 930 p[1] = (u_char)(v >> 8) & 0xff; 931 p[2] = (u_char)(v >> 16) & 0xff; 932 p[3] = (u_char)(v >> 24) & 0xff; 933 } 934 935 void 936 put_u16(void *vp, u_int16_t v) 937 { 938 u_char *p = (u_char *)vp; 939 940 p[0] = (u_char)(v >> 8) & 0xff; 941 p[1] = (u_char)v & 0xff; 942 } 943 944 void 945 ms_subtract_diff(struct timeval *start, int *ms) 946 { 947 struct timeval diff, finish; 948 949 gettimeofday(&finish, NULL); 950 timersub(&finish, start, &diff); 951 *ms -= (diff.tv_sec * 1000) + (diff.tv_usec / 1000); 952 } 953 954 void 955 ms_to_timeval(struct timeval *tv, int ms) 956 { 957 if (ms < 0) 958 ms = 0; 959 tv->tv_sec = ms / 1000; 960 tv->tv_usec = (ms % 1000) * 1000; 961 } 962 963 time_t 964 monotime(void) 965 { 966 #if defined(HAVE_CLOCK_GETTIME) && \ 967 (defined(CLOCK_MONOTONIC) || defined(CLOCK_BOOTTIME)) 968 struct timespec ts; 969 static int gettime_failed = 0; 970 971 if (!gettime_failed) { 972 #if defined(CLOCK_BOOTTIME) 973 if (clock_gettime(CLOCK_BOOTTIME, &ts) == 0) 974 return (ts.tv_sec); 975 #endif 976 #if defined(CLOCK_MONOTONIC) 977 if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) 978 return (ts.tv_sec); 979 #endif 980 debug3("clock_gettime: %s", strerror(errno)); 981 gettime_failed = 1; 982 } 983 #endif /* HAVE_CLOCK_GETTIME && (CLOCK_MONOTONIC || CLOCK_BOOTTIME */ 984 985 return time(NULL); 986 } 987 988 double 989 monotime_double(void) 990 { 991 #if defined(HAVE_CLOCK_GETTIME) && \ 992 (defined(CLOCK_MONOTONIC) || defined(CLOCK_BOOTTIME)) 993 struct timespec ts; 994 static int gettime_failed = 0; 995 996 if (!gettime_failed) { 997 #if defined(CLOCK_BOOTTIME) 998 if (clock_gettime(CLOCK_BOOTTIME, &ts) == 0) 999 return (ts.tv_sec + (double)ts.tv_nsec / 1000000000); 1000 #endif 1001 #if defined(CLOCK_MONOTONIC) 1002 if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) 1003 return (ts.tv_sec + (double)ts.tv_nsec / 1000000000); 1004 #endif 1005 debug3("clock_gettime: %s", strerror(errno)); 1006 gettime_failed = 1; 1007 } 1008 #endif /* HAVE_CLOCK_GETTIME && (CLOCK_MONOTONIC || CLOCK_BOOTTIME */ 1009 1010 return (double)time(NULL); 1011 } 1012 1013 void 1014 bandwidth_limit_init(struct bwlimit *bw, u_int64_t kbps, size_t buflen) 1015 { 1016 bw->buflen = buflen; 1017 bw->rate = kbps; 1018 bw->thresh = bw->rate; 1019 bw->lamt = 0; 1020 timerclear(&bw->bwstart); 1021 timerclear(&bw->bwend); 1022 } 1023 1024 /* Callback from read/write loop to insert bandwidth-limiting delays */ 1025 void 1026 bandwidth_limit(struct bwlimit *bw, size_t read_len) 1027 { 1028 u_int64_t waitlen; 1029 struct timespec ts, rm; 1030 1031 if (!timerisset(&bw->bwstart)) { 1032 gettimeofday(&bw->bwstart, NULL); 1033 return; 1034 } 1035 1036 bw->lamt += read_len; 1037 if (bw->lamt < bw->thresh) 1038 return; 1039 1040 gettimeofday(&bw->bwend, NULL); 1041 timersub(&bw->bwend, &bw->bwstart, &bw->bwend); 1042 if (!timerisset(&bw->bwend)) 1043 return; 1044 1045 bw->lamt *= 8; 1046 waitlen = (double)1000000L * bw->lamt / bw->rate; 1047 1048 bw->bwstart.tv_sec = waitlen / 1000000L; 1049 bw->bwstart.tv_usec = waitlen % 1000000L; 1050 1051 if (timercmp(&bw->bwstart, &bw->bwend, >)) { 1052 timersub(&bw->bwstart, &bw->bwend, &bw->bwend); 1053 1054 /* Adjust the wait time */ 1055 if (bw->bwend.tv_sec) { 1056 bw->thresh /= 2; 1057 if (bw->thresh < bw->buflen / 4) 1058 bw->thresh = bw->buflen / 4; 1059 } else if (bw->bwend.tv_usec < 10000) { 1060 bw->thresh *= 2; 1061 if (bw->thresh > bw->buflen * 8) 1062 bw->thresh = bw->buflen * 8; 1063 } 1064 1065 TIMEVAL_TO_TIMESPEC(&bw->bwend, &ts); 1066 while (nanosleep(&ts, &rm) == -1) { 1067 if (errno != EINTR) 1068 break; 1069 ts = rm; 1070 } 1071 } 1072 1073 bw->lamt = 0; 1074 gettimeofday(&bw->bwstart, NULL); 1075 } 1076 1077 /* Make a template filename for mk[sd]temp() */ 1078 void 1079 mktemp_proto(char *s, size_t len) 1080 { 1081 const char *tmpdir; 1082 int r; 1083 1084 if ((tmpdir = getenv("TMPDIR")) != NULL) { 1085 r = snprintf(s, len, "%s/ssh-XXXXXXXXXXXX", tmpdir); 1086 if (r > 0 && (size_t)r < len) 1087 return; 1088 } 1089 r = snprintf(s, len, "/tmp/ssh-XXXXXXXXXXXX"); 1090 if (r < 0 || (size_t)r >= len) 1091 fatal("%s: template string too short", __func__); 1092 } 1093 1094 static const struct { 1095 const char *name; 1096 int value; 1097 } ipqos[] = { 1098 { "none", INT_MAX }, /* can't use 0 here; that's CS0 */ 1099 { "af11", IPTOS_DSCP_AF11 }, 1100 { "af12", IPTOS_DSCP_AF12 }, 1101 { "af13", IPTOS_DSCP_AF13 }, 1102 { "af21", IPTOS_DSCP_AF21 }, 1103 { "af22", IPTOS_DSCP_AF22 }, 1104 { "af23", IPTOS_DSCP_AF23 }, 1105 { "af31", IPTOS_DSCP_AF31 }, 1106 { "af32", IPTOS_DSCP_AF32 }, 1107 { "af33", IPTOS_DSCP_AF33 }, 1108 { "af41", IPTOS_DSCP_AF41 }, 1109 { "af42", IPTOS_DSCP_AF42 }, 1110 { "af43", IPTOS_DSCP_AF43 }, 1111 { "cs0", IPTOS_DSCP_CS0 }, 1112 { "cs1", IPTOS_DSCP_CS1 }, 1113 { "cs2", IPTOS_DSCP_CS2 }, 1114 { "cs3", IPTOS_DSCP_CS3 }, 1115 { "cs4", IPTOS_DSCP_CS4 }, 1116 { "cs5", IPTOS_DSCP_CS5 }, 1117 { "cs6", IPTOS_DSCP_CS6 }, 1118 { "cs7", IPTOS_DSCP_CS7 }, 1119 { "ef", IPTOS_DSCP_EF }, 1120 { "lowdelay", IPTOS_LOWDELAY }, 1121 { "throughput", IPTOS_THROUGHPUT }, 1122 { "reliability", IPTOS_RELIABILITY }, 1123 { NULL, -1 } 1124 }; 1125 1126 int 1127 parse_ipqos(const char *cp) 1128 { 1129 u_int i; 1130 char *ep; 1131 long val; 1132 1133 if (cp == NULL) 1134 return -1; 1135 for (i = 0; ipqos[i].name != NULL; i++) { 1136 if (strcasecmp(cp, ipqos[i].name) == 0) 1137 return ipqos[i].value; 1138 } 1139 /* Try parsing as an integer */ 1140 val = strtol(cp, &ep, 0); 1141 if (*cp == '\0' || *ep != '\0' || val < 0 || val > 255) 1142 return -1; 1143 return val; 1144 } 1145 1146 const char * 1147 iptos2str(int iptos) 1148 { 1149 int i; 1150 static char iptos_str[sizeof "0xff"]; 1151 1152 for (i = 0; ipqos[i].name != NULL; i++) { 1153 if (ipqos[i].value == iptos) 1154 return ipqos[i].name; 1155 } 1156 snprintf(iptos_str, sizeof iptos_str, "0x%02x", iptos); 1157 return iptos_str; 1158 } 1159 1160 void 1161 lowercase(char *s) 1162 { 1163 for (; *s; s++) 1164 *s = tolower((u_char)*s); 1165 } 1166 1167 int 1168 unix_listener(const char *path, int backlog, int unlink_first) 1169 { 1170 struct sockaddr_un sunaddr; 1171 int saved_errno, sock; 1172 1173 memset(&sunaddr, 0, sizeof(sunaddr)); 1174 sunaddr.sun_family = AF_UNIX; 1175 if (strlcpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path)) >= sizeof(sunaddr.sun_path)) { 1176 error("%s: \"%s\" too long for Unix domain socket", __func__, 1177 path); 1178 errno = ENAMETOOLONG; 1179 return -1; 1180 } 1181 1182 sock = socket(PF_UNIX, SOCK_STREAM, 0); 1183 if (sock < 0) { 1184 saved_errno = errno; 1185 error("socket: %.100s", strerror(errno)); 1186 errno = saved_errno; 1187 return -1; 1188 } 1189 if (unlink_first == 1) { 1190 if (unlink(path) != 0 && errno != ENOENT) 1191 error("unlink(%s): %.100s", path, strerror(errno)); 1192 } 1193 if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) { 1194 saved_errno = errno; 1195 error("bind: %.100s", strerror(errno)); 1196 close(sock); 1197 error("%s: cannot bind to path: %s", __func__, path); 1198 errno = saved_errno; 1199 return -1; 1200 } 1201 if (listen(sock, backlog) < 0) { 1202 saved_errno = errno; 1203 error("listen: %.100s", strerror(errno)); 1204 close(sock); 1205 unlink(path); 1206 error("%s: cannot listen on path: %s", __func__, path); 1207 errno = saved_errno; 1208 return -1; 1209 } 1210 return sock; 1211 } 1212 1213 void 1214 sock_set_v6only(int s) 1215 { 1216 #if defined(IPV6_V6ONLY) && !defined(__OpenBSD__) 1217 int on = 1; 1218 1219 debug3("%s: set socket %d IPV6_V6ONLY", __func__, s); 1220 if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) == -1) 1221 error("setsockopt IPV6_V6ONLY: %s", strerror(errno)); 1222 #endif 1223 } 1224 1225 /* 1226 * Compares two strings that maybe be NULL. Returns non-zero if strings 1227 * are both NULL or are identical, returns zero otherwise. 1228 */ 1229 static int 1230 strcmp_maybe_null(const char *a, const char *b) 1231 { 1232 if ((a == NULL && b != NULL) || (a != NULL && b == NULL)) 1233 return 0; 1234 if (a != NULL && strcmp(a, b) != 0) 1235 return 0; 1236 return 1; 1237 } 1238 1239 /* 1240 * Compare two forwards, returning non-zero if they are identical or 1241 * zero otherwise. 1242 */ 1243 int 1244 forward_equals(const struct Forward *a, const struct Forward *b) 1245 { 1246 if (strcmp_maybe_null(a->listen_host, b->listen_host) == 0) 1247 return 0; 1248 if (a->listen_port != b->listen_port) 1249 return 0; 1250 if (strcmp_maybe_null(a->listen_path, b->listen_path) == 0) 1251 return 0; 1252 if (strcmp_maybe_null(a->connect_host, b->connect_host) == 0) 1253 return 0; 1254 if (a->connect_port != b->connect_port) 1255 return 0; 1256 if (strcmp_maybe_null(a->connect_path, b->connect_path) == 0) 1257 return 0; 1258 /* allocated_port and handle are not checked */ 1259 return 1; 1260 } 1261 1262 /* returns 1 if bind to specified port by specified user is permitted */ 1263 int 1264 bind_permitted(int port, uid_t uid) 1265 { 1266 if (port < IPPORT_RESERVED && uid != 0) 1267 return 0; 1268 return 1; 1269 } 1270 1271 /* returns 1 if process is already daemonized, 0 otherwise */ 1272 int 1273 daemonized(void) 1274 { 1275 int fd; 1276 1277 if ((fd = open(_PATH_TTY, O_RDONLY | O_NOCTTY)) >= 0) { 1278 close(fd); 1279 return 0; /* have controlling terminal */ 1280 } 1281 if (getppid() != 1) 1282 return 0; /* parent is not init */ 1283 if (getsid(0) != getpid()) 1284 return 0; /* not session leader */ 1285 debug3("already daemonized"); 1286 return 1; 1287 } 1288 1289 1290 /* 1291 * Splits 's' into an argument vector. Handles quoted string and basic 1292 * escape characters (\\, \", \'). Caller must free the argument vector 1293 * and its members. 1294 */ 1295 int 1296 argv_split(const char *s, int *argcp, char ***argvp) 1297 { 1298 int r = SSH_ERR_INTERNAL_ERROR; 1299 int argc = 0, quote, i, j; 1300 char *arg, **argv = xcalloc(1, sizeof(*argv)); 1301 1302 *argvp = NULL; 1303 *argcp = 0; 1304 1305 for (i = 0; s[i] != '\0'; i++) { 1306 /* Skip leading whitespace */ 1307 if (s[i] == ' ' || s[i] == '\t') 1308 continue; 1309 1310 /* Start of a token */ 1311 quote = 0; 1312 if (s[i] == '\\' && 1313 (s[i + 1] == '\'' || s[i + 1] == '\"' || s[i + 1] == '\\')) 1314 i++; 1315 else if (s[i] == '\'' || s[i] == '"') 1316 quote = s[i++]; 1317 1318 argv = xreallocarray(argv, (argc + 2), sizeof(*argv)); 1319 arg = argv[argc++] = xcalloc(1, strlen(s + i) + 1); 1320 argv[argc] = NULL; 1321 1322 /* Copy the token in, removing escapes */ 1323 for (j = 0; s[i] != '\0'; i++) { 1324 if (s[i] == '\\') { 1325 if (s[i + 1] == '\'' || 1326 s[i + 1] == '\"' || 1327 s[i + 1] == '\\') { 1328 i++; /* Skip '\' */ 1329 arg[j++] = s[i]; 1330 } else { 1331 /* Unrecognised escape */ 1332 arg[j++] = s[i]; 1333 } 1334 } else if (quote == 0 && (s[i] == ' ' || s[i] == '\t')) 1335 break; /* done */ 1336 else if (quote != 0 && s[i] == quote) 1337 break; /* done */ 1338 else 1339 arg[j++] = s[i]; 1340 } 1341 if (s[i] == '\0') { 1342 if (quote != 0) { 1343 /* Ran out of string looking for close quote */ 1344 r = SSH_ERR_INVALID_FORMAT; 1345 goto out; 1346 } 1347 break; 1348 } 1349 } 1350 /* Success */ 1351 *argcp = argc; 1352 *argvp = argv; 1353 argc = 0; 1354 argv = NULL; 1355 r = 0; 1356 out: 1357 if (argc != 0 && argv != NULL) { 1358 for (i = 0; i < argc; i++) 1359 free(argv[i]); 1360 free(argv); 1361 } 1362 return r; 1363 } 1364 1365 /* 1366 * Reassemble an argument vector into a string, quoting and escaping as 1367 * necessary. Caller must free returned string. 1368 */ 1369 char * 1370 argv_assemble(int argc, char **argv) 1371 { 1372 int i, j, ws, r; 1373 char c, *ret; 1374 struct sshbuf *buf, *arg; 1375 1376 if ((buf = sshbuf_new()) == NULL || (arg = sshbuf_new()) == NULL) 1377 fatal("%s: sshbuf_new failed", __func__); 1378 1379 for (i = 0; i < argc; i++) { 1380 ws = 0; 1381 sshbuf_reset(arg); 1382 for (j = 0; argv[i][j] != '\0'; j++) { 1383 r = 0; 1384 c = argv[i][j]; 1385 switch (c) { 1386 case ' ': 1387 case '\t': 1388 ws = 1; 1389 r = sshbuf_put_u8(arg, c); 1390 break; 1391 case '\\': 1392 case '\'': 1393 case '"': 1394 if ((r = sshbuf_put_u8(arg, '\\')) != 0) 1395 break; 1396 /* FALLTHROUGH */ 1397 default: 1398 r = sshbuf_put_u8(arg, c); 1399 break; 1400 } 1401 if (r != 0) 1402 fatal("%s: sshbuf_put_u8: %s", 1403 __func__, ssh_err(r)); 1404 } 1405 if ((i != 0 && (r = sshbuf_put_u8(buf, ' ')) != 0) || 1406 (ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0) || 1407 (r = sshbuf_putb(buf, arg)) != 0 || 1408 (ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0)) 1409 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1410 } 1411 if ((ret = malloc(sshbuf_len(buf) + 1)) == NULL) 1412 fatal("%s: malloc failed", __func__); 1413 memcpy(ret, sshbuf_ptr(buf), sshbuf_len(buf)); 1414 ret[sshbuf_len(buf)] = '\0'; 1415 sshbuf_free(buf); 1416 sshbuf_free(arg); 1417 return ret; 1418 } 1419 1420 /* 1421 * Runs command in a subprocess wuth a minimal environment. 1422 * Returns pid on success, 0 on failure. 1423 * The child stdout and stderr maybe captured, left attached or sent to 1424 * /dev/null depending on the contents of flags. 1425 * "tag" is prepended to log messages. 1426 * NB. "command" is only used for logging; the actual command executed is 1427 * av[0]. 1428 */ 1429 pid_t 1430 subprocess(const char *tag, struct passwd *pw, const char *command, 1431 int ac, char **av, FILE **child, u_int flags) 1432 { 1433 FILE *f = NULL; 1434 struct stat st; 1435 int fd, devnull, p[2], i; 1436 pid_t pid; 1437 char *cp, errmsg[512]; 1438 u_int envsize; 1439 char **child_env; 1440 1441 if (child != NULL) 1442 *child = NULL; 1443 1444 debug3("%s: %s command \"%s\" running as %s (flags 0x%x)", __func__, 1445 tag, command, pw->pw_name, flags); 1446 1447 /* Check consistency */ 1448 if ((flags & SSH_SUBPROCESS_STDOUT_DISCARD) != 0 && 1449 (flags & SSH_SUBPROCESS_STDOUT_CAPTURE) != 0) { 1450 error("%s: inconsistent flags", __func__); 1451 return 0; 1452 } 1453 if (((flags & SSH_SUBPROCESS_STDOUT_CAPTURE) == 0) != (child == NULL)) { 1454 error("%s: inconsistent flags/output", __func__); 1455 return 0; 1456 } 1457 1458 /* 1459 * If executing an explicit binary, then verify the it exists 1460 * and appears safe-ish to execute 1461 */ 1462 if (*av[0] != '/') { 1463 error("%s path is not absolute", tag); 1464 return 0; 1465 } 1466 temporarily_use_uid(pw); 1467 if (stat(av[0], &st) < 0) { 1468 error("Could not stat %s \"%s\": %s", tag, 1469 av[0], strerror(errno)); 1470 restore_uid(); 1471 return 0; 1472 } 1473 if (safe_path(av[0], &st, NULL, 0, errmsg, sizeof(errmsg)) != 0) { 1474 error("Unsafe %s \"%s\": %s", tag, av[0], errmsg); 1475 restore_uid(); 1476 return 0; 1477 } 1478 /* Prepare to keep the child's stdout if requested */ 1479 if (pipe(p) != 0) { 1480 error("%s: pipe: %s", tag, strerror(errno)); 1481 restore_uid(); 1482 return 0; 1483 } 1484 restore_uid(); 1485 1486 switch ((pid = fork())) { 1487 case -1: /* error */ 1488 error("%s: fork: %s", tag, strerror(errno)); 1489 close(p[0]); 1490 close(p[1]); 1491 return 0; 1492 case 0: /* child */ 1493 /* Prepare a minimal environment for the child. */ 1494 envsize = 5; 1495 child_env = xcalloc(sizeof(*child_env), envsize); 1496 child_set_env(&child_env, &envsize, "PATH", _PATH_STDPATH); 1497 child_set_env(&child_env, &envsize, "USER", pw->pw_name); 1498 child_set_env(&child_env, &envsize, "LOGNAME", pw->pw_name); 1499 child_set_env(&child_env, &envsize, "HOME", pw->pw_dir); 1500 if ((cp = getenv("LANG")) != NULL) 1501 child_set_env(&child_env, &envsize, "LANG", cp); 1502 1503 for (i = 0; i < NSIG; i++) 1504 signal(i, SIG_DFL); 1505 1506 if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) { 1507 error("%s: open %s: %s", tag, _PATH_DEVNULL, 1508 strerror(errno)); 1509 _exit(1); 1510 } 1511 if (dup2(devnull, STDIN_FILENO) == -1) { 1512 error("%s: dup2: %s", tag, strerror(errno)); 1513 _exit(1); 1514 } 1515 1516 /* Set up stdout as requested; leave stderr in place for now. */ 1517 fd = -1; 1518 if ((flags & SSH_SUBPROCESS_STDOUT_CAPTURE) != 0) 1519 fd = p[1]; 1520 else if ((flags & SSH_SUBPROCESS_STDOUT_DISCARD) != 0) 1521 fd = devnull; 1522 if (fd != -1 && dup2(fd, STDOUT_FILENO) == -1) { 1523 error("%s: dup2: %s", tag, strerror(errno)); 1524 _exit(1); 1525 } 1526 closefrom(STDERR_FILENO + 1); 1527 1528 /* Don't use permanently_set_uid() here to avoid fatal() */ 1529 if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) { 1530 error("%s: setresgid %u: %s", tag, (u_int)pw->pw_gid, 1531 strerror(errno)); 1532 _exit(1); 1533 } 1534 if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) { 1535 error("%s: setresuid %u: %s", tag, (u_int)pw->pw_uid, 1536 strerror(errno)); 1537 _exit(1); 1538 } 1539 /* stdin is pointed to /dev/null at this point */ 1540 if ((flags & SSH_SUBPROCESS_STDOUT_DISCARD) != 0 && 1541 dup2(STDIN_FILENO, STDERR_FILENO) == -1) { 1542 error("%s: dup2: %s", tag, strerror(errno)); 1543 _exit(1); 1544 } 1545 1546 execve(av[0], av, child_env); 1547 error("%s exec \"%s\": %s", tag, command, strerror(errno)); 1548 _exit(127); 1549 default: /* parent */ 1550 break; 1551 } 1552 1553 close(p[1]); 1554 if ((flags & SSH_SUBPROCESS_STDOUT_CAPTURE) == 0) 1555 close(p[0]); 1556 else if ((f = fdopen(p[0], "r")) == NULL) { 1557 error("%s: fdopen: %s", tag, strerror(errno)); 1558 close(p[0]); 1559 /* Don't leave zombie child */ 1560 kill(pid, SIGTERM); 1561 while (waitpid(pid, NULL, 0) == -1 && errno == EINTR) 1562 ; 1563 return 0; 1564 } 1565 /* Success */ 1566 debug3("%s: %s pid %ld", __func__, tag, (long)pid); 1567 if (child != NULL) 1568 *child = f; 1569 return pid; 1570 } 1571 1572 /* Returns 0 if pid exited cleanly, non-zero otherwise */ 1573 int 1574 exited_cleanly(pid_t pid, const char *tag, const char *cmd, int quiet) 1575 { 1576 int status; 1577 1578 while (waitpid(pid, &status, 0) == -1) { 1579 if (errno != EINTR) { 1580 error("%s: waitpid: %s", tag, strerror(errno)); 1581 return -1; 1582 } 1583 } 1584 if (WIFSIGNALED(status)) { 1585 error("%s %s exited on signal %d", tag, cmd, WTERMSIG(status)); 1586 return -1; 1587 } else if (WEXITSTATUS(status) != 0) { 1588 do_log2(quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_INFO, 1589 "%s %s failed, status %d", tag, cmd, WEXITSTATUS(status)); 1590 return -1; 1591 } 1592 return 0; 1593 } 1594 1595 /* 1596 * Check a given path for security. This is defined as all components 1597 * of the path to the file must be owned by either the owner of 1598 * of the file or root and no directories must be group or world writable. 1599 * 1600 * XXX Should any specific check be done for sym links ? 1601 * 1602 * Takes a file name, its stat information (preferably from fstat() to 1603 * avoid races), the uid of the expected owner, their home directory and an 1604 * error buffer plus max size as arguments. 1605 * 1606 * Returns 0 on success and -1 on failure 1607 */ 1608 int 1609 safe_path(const char *name, struct stat *stp, const char *pw_dir, 1610 uid_t uid, char *err, size_t errlen) 1611 { 1612 char buf[PATH_MAX], homedir[PATH_MAX]; 1613 char *cp; 1614 int comparehome = 0; 1615 struct stat st; 1616 1617 if (realpath(name, buf) == NULL) { 1618 snprintf(err, errlen, "realpath %s failed: %s", name, 1619 strerror(errno)); 1620 return -1; 1621 } 1622 if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL) 1623 comparehome = 1; 1624 1625 if (!S_ISREG(stp->st_mode)) { 1626 snprintf(err, errlen, "%s is not a regular file", buf); 1627 return -1; 1628 } 1629 if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) || 1630 (stp->st_mode & 022) != 0) { 1631 snprintf(err, errlen, "bad ownership or modes for file %s", 1632 buf); 1633 return -1; 1634 } 1635 1636 /* for each component of the canonical path, walking upwards */ 1637 for (;;) { 1638 if ((cp = dirname(buf)) == NULL) { 1639 snprintf(err, errlen, "dirname() failed"); 1640 return -1; 1641 } 1642 strlcpy(buf, cp, sizeof(buf)); 1643 1644 if (stat(buf, &st) < 0 || 1645 (!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) || 1646 (st.st_mode & 022) != 0) { 1647 snprintf(err, errlen, 1648 "bad ownership or modes for directory %s", buf); 1649 return -1; 1650 } 1651 1652 /* If are past the homedir then we can stop */ 1653 if (comparehome && strcmp(homedir, buf) == 0) 1654 break; 1655 1656 /* 1657 * dirname should always complete with a "/" path, 1658 * but we can be paranoid and check for "." too 1659 */ 1660 if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0)) 1661 break; 1662 } 1663 return 0; 1664 } 1665 1666 /* 1667 * Version of safe_path() that accepts an open file descriptor to 1668 * avoid races. 1669 * 1670 * Returns 0 on success and -1 on failure 1671 */ 1672 int 1673 safe_path_fd(int fd, const char *file, struct passwd *pw, 1674 char *err, size_t errlen) 1675 { 1676 struct stat st; 1677 1678 /* check the open file to avoid races */ 1679 if (fstat(fd, &st) < 0) { 1680 snprintf(err, errlen, "cannot stat file %s: %s", 1681 file, strerror(errno)); 1682 return -1; 1683 } 1684 return safe_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen); 1685 } 1686 1687 /* 1688 * Sets the value of the given variable in the environment. If the variable 1689 * already exists, its value is overridden. 1690 */ 1691 void 1692 child_set_env(char ***envp, u_int *envsizep, const char *name, 1693 const char *value) 1694 { 1695 char **env; 1696 u_int envsize; 1697 u_int i, namelen; 1698 1699 if (strchr(name, '=') != NULL) { 1700 error("Invalid environment variable \"%.100s\"", name); 1701 return; 1702 } 1703 1704 /* 1705 * If we're passed an uninitialized list, allocate a single null 1706 * entry before continuing. 1707 */ 1708 if (*envp == NULL && *envsizep == 0) { 1709 *envp = xmalloc(sizeof(char *)); 1710 *envp[0] = NULL; 1711 *envsizep = 1; 1712 } 1713 1714 /* 1715 * Find the slot where the value should be stored. If the variable 1716 * already exists, we reuse the slot; otherwise we append a new slot 1717 * at the end of the array, expanding if necessary. 1718 */ 1719 env = *envp; 1720 namelen = strlen(name); 1721 for (i = 0; env[i]; i++) 1722 if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=') 1723 break; 1724 if (env[i]) { 1725 /* Reuse the slot. */ 1726 free(env[i]); 1727 } else { 1728 /* New variable. Expand if necessary. */ 1729 envsize = *envsizep; 1730 if (i >= envsize - 1) { 1731 if (envsize >= 1000) 1732 fatal("child_set_env: too many env vars"); 1733 envsize += 50; 1734 env = (*envp) = xreallocarray(env, envsize, sizeof(char *)); 1735 *envsizep = envsize; 1736 } 1737 /* Need to set the NULL pointer at end of array beyond the new slot. */ 1738 env[i + 1] = NULL; 1739 } 1740 1741 /* Allocate space and format the variable in the appropriate slot. */ 1742 env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1); 1743 snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value); 1744 } 1745 1746