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