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