1 /* $OpenBSD: misc.c,v 1.157 2020/12/22 00:12:22 djm Exp $ */ 2 /* 3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 4 * Copyright (c) 2005-2020 Damien Miller. All rights reserved. 5 * Copyright (c) 2004 Henning Brauer <henning@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 21 #include <sys/types.h> 22 #include <sys/ioctl.h> 23 #include <sys/socket.h> 24 #include <sys/stat.h> 25 #include <sys/time.h> 26 #include <sys/wait.h> 27 #include <sys/un.h> 28 29 #include <net/if.h> 30 #include <netinet/in.h> 31 #include <netinet/ip.h> 32 #include <netinet/tcp.h> 33 #include <arpa/inet.h> 34 35 #include <ctype.h> 36 #include <errno.h> 37 #include <fcntl.h> 38 #include <netdb.h> 39 #include <paths.h> 40 #include <pwd.h> 41 #include <libgen.h> 42 #include <limits.h> 43 #include <poll.h> 44 #include <signal.h> 45 #include <stdarg.h> 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <string.h> 49 #include <unistd.h> 50 51 #include "xmalloc.h" 52 #include "misc.h" 53 #include "log.h" 54 #include "ssh.h" 55 #include "sshbuf.h" 56 #include "ssherr.h" 57 58 /* remove newline at end of string */ 59 char * 60 chop(char *s) 61 { 62 char *t = s; 63 while (*t) { 64 if (*t == '\n' || *t == '\r') { 65 *t = '\0'; 66 return s; 67 } 68 t++; 69 } 70 return s; 71 72 } 73 74 /* set/unset filedescriptor to non-blocking */ 75 int 76 set_nonblock(int fd) 77 { 78 int val; 79 80 val = fcntl(fd, F_GETFL); 81 if (val == -1) { 82 error("fcntl(%d, F_GETFL): %s", fd, strerror(errno)); 83 return (-1); 84 } 85 if (val & O_NONBLOCK) { 86 debug3("fd %d is O_NONBLOCK", fd); 87 return (0); 88 } 89 debug2("fd %d setting O_NONBLOCK", fd); 90 val |= O_NONBLOCK; 91 if (fcntl(fd, F_SETFL, val) == -1) { 92 debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s", fd, 93 strerror(errno)); 94 return (-1); 95 } 96 return (0); 97 } 98 99 int 100 unset_nonblock(int fd) 101 { 102 int val; 103 104 val = fcntl(fd, F_GETFL); 105 if (val == -1) { 106 error("fcntl(%d, F_GETFL): %s", fd, strerror(errno)); 107 return (-1); 108 } 109 if (!(val & O_NONBLOCK)) { 110 debug3("fd %d is not O_NONBLOCK", fd); 111 return (0); 112 } 113 debug("fd %d clearing O_NONBLOCK", fd); 114 val &= ~O_NONBLOCK; 115 if (fcntl(fd, F_SETFL, val) == -1) { 116 debug("fcntl(%d, F_SETFL, ~O_NONBLOCK): %s", 117 fd, strerror(errno)); 118 return (-1); 119 } 120 return (0); 121 } 122 123 const char * 124 ssh_gai_strerror(int gaierr) 125 { 126 if (gaierr == EAI_SYSTEM && errno != 0) 127 return strerror(errno); 128 return gai_strerror(gaierr); 129 } 130 131 /* disable nagle on socket */ 132 void 133 set_nodelay(int fd) 134 { 135 int opt; 136 socklen_t optlen; 137 138 optlen = sizeof opt; 139 if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) { 140 debug("getsockopt TCP_NODELAY: %.100s", strerror(errno)); 141 return; 142 } 143 if (opt == 1) { 144 debug2("fd %d is TCP_NODELAY", fd); 145 return; 146 } 147 opt = 1; 148 debug2("fd %d setting TCP_NODELAY", fd); 149 if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof opt) == -1) 150 error("setsockopt TCP_NODELAY: %.100s", strerror(errno)); 151 } 152 153 /* Allow local port reuse in TIME_WAIT */ 154 int 155 set_reuseaddr(int fd) 156 { 157 int on = 1; 158 159 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { 160 error("setsockopt SO_REUSEADDR fd %d: %s", fd, strerror(errno)); 161 return -1; 162 } 163 return 0; 164 } 165 166 /* Get/set routing domain */ 167 char * 168 get_rdomain(int fd) 169 { 170 int rtable; 171 char *ret; 172 socklen_t len = sizeof(rtable); 173 174 if (getsockopt(fd, SOL_SOCKET, SO_RTABLE, &rtable, &len) == -1) { 175 error("Failed to get routing domain for fd %d: %s", 176 fd, strerror(errno)); 177 return NULL; 178 } 179 xasprintf(&ret, "%d", rtable); 180 return ret; 181 } 182 183 int 184 set_rdomain(int fd, const char *name) 185 { 186 int rtable; 187 const char *errstr; 188 189 if (name == NULL) 190 return 0; /* default table */ 191 192 rtable = (int)strtonum(name, 0, 255, &errstr); 193 if (errstr != NULL) { 194 /* Shouldn't happen */ 195 error("Invalid routing domain \"%s\": %s", name, errstr); 196 return -1; 197 } 198 if (setsockopt(fd, SOL_SOCKET, SO_RTABLE, 199 &rtable, sizeof(rtable)) == -1) { 200 error("Failed to set routing domain %d on fd %d: %s", 201 rtable, fd, strerror(errno)); 202 return -1; 203 } 204 return 0; 205 } 206 207 int 208 get_sock_af(int fd) 209 { 210 struct sockaddr_storage to; 211 socklen_t tolen = sizeof(to); 212 213 memset(&to, 0, sizeof(to)); 214 if (getsockname(fd, (struct sockaddr *)&to, &tolen) == -1) 215 return -1; 216 return to.ss_family; 217 } 218 219 void 220 set_sock_tos(int fd, int tos) 221 { 222 int af; 223 224 switch ((af = get_sock_af(fd))) { 225 case -1: 226 /* assume not a socket */ 227 break; 228 case AF_INET: 229 debug3_f("set socket %d IP_TOS 0x%02x", fd, tos); 230 if (setsockopt(fd, IPPROTO_IP, IP_TOS, 231 &tos, sizeof(tos)) == -1) { 232 error("setsockopt socket %d IP_TOS %d: %s:", 233 fd, tos, strerror(errno)); 234 } 235 break; 236 case AF_INET6: 237 debug3_f("set socket %d IPV6_TCLASS 0x%02x", fd, tos); 238 if (setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, 239 &tos, sizeof(tos)) == -1) { 240 error("setsockopt socket %d IPV6_TCLASS %d: %.100s:", 241 fd, tos, strerror(errno)); 242 } 243 break; 244 default: 245 debug2_f("unsupported socket family %d", af); 246 break; 247 } 248 } 249 250 /* 251 * Wait up to *timeoutp milliseconds for events on fd. Updates 252 * *timeoutp with time remaining. 253 * Returns 0 if fd ready or -1 on timeout or error (see errno). 254 */ 255 static int 256 waitfd(int fd, int *timeoutp, short events) 257 { 258 struct pollfd pfd; 259 struct timeval t_start; 260 int oerrno, r; 261 262 monotime_tv(&t_start); 263 pfd.fd = fd; 264 pfd.events = events; 265 for (; *timeoutp >= 0;) { 266 r = poll(&pfd, 1, *timeoutp); 267 oerrno = errno; 268 ms_subtract_diff(&t_start, timeoutp); 269 errno = oerrno; 270 if (r > 0) 271 return 0; 272 else if (r == -1 && errno != EAGAIN && errno != EINTR) 273 return -1; 274 else if (r == 0) 275 break; 276 } 277 /* timeout */ 278 errno = ETIMEDOUT; 279 return -1; 280 } 281 282 /* 283 * Wait up to *timeoutp milliseconds for fd to be readable. Updates 284 * *timeoutp with time remaining. 285 * Returns 0 if fd ready or -1 on timeout or error (see errno). 286 */ 287 int 288 waitrfd(int fd, int *timeoutp) { 289 return waitfd(fd, timeoutp, POLLIN); 290 } 291 292 /* 293 * Attempt a non-blocking connect(2) to the specified address, waiting up to 294 * *timeoutp milliseconds for the connection to complete. If the timeout is 295 * <=0, then wait indefinitely. 296 * 297 * Returns 0 on success or -1 on failure. 298 */ 299 int 300 timeout_connect(int sockfd, const struct sockaddr *serv_addr, 301 socklen_t addrlen, int *timeoutp) 302 { 303 int optval = 0; 304 socklen_t optlen = sizeof(optval); 305 306 /* No timeout: just do a blocking connect() */ 307 if (timeoutp == NULL || *timeoutp <= 0) 308 return connect(sockfd, serv_addr, addrlen); 309 310 set_nonblock(sockfd); 311 for (;;) { 312 if (connect(sockfd, serv_addr, addrlen) == 0) { 313 /* Succeeded already? */ 314 unset_nonblock(sockfd); 315 return 0; 316 } else if (errno == EINTR) 317 continue; 318 else if (errno != EINPROGRESS) 319 return -1; 320 break; 321 } 322 323 if (waitfd(sockfd, timeoutp, POLLIN | POLLOUT) == -1) 324 return -1; 325 326 /* Completed or failed */ 327 if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1) { 328 debug("getsockopt: %s", strerror(errno)); 329 return -1; 330 } 331 if (optval != 0) { 332 errno = optval; 333 return -1; 334 } 335 unset_nonblock(sockfd); 336 return 0; 337 } 338 339 /* Characters considered whitespace in strsep calls. */ 340 #define WHITESPACE " \t\r\n" 341 #define QUOTE "\"" 342 343 /* return next token in configuration line */ 344 static char * 345 strdelim_internal(char **s, int split_equals) 346 { 347 char *old; 348 int wspace = 0; 349 350 if (*s == NULL) 351 return NULL; 352 353 old = *s; 354 355 *s = strpbrk(*s, 356 split_equals ? WHITESPACE QUOTE "=" : WHITESPACE QUOTE); 357 if (*s == NULL) 358 return (old); 359 360 if (*s[0] == '\"') { 361 memmove(*s, *s + 1, strlen(*s)); /* move nul too */ 362 /* Find matching quote */ 363 if ((*s = strpbrk(*s, QUOTE)) == NULL) { 364 return (NULL); /* no matching quote */ 365 } else { 366 *s[0] = '\0'; 367 *s += strspn(*s + 1, WHITESPACE) + 1; 368 return (old); 369 } 370 } 371 372 /* Allow only one '=' to be skipped */ 373 if (split_equals && *s[0] == '=') 374 wspace = 1; 375 *s[0] = '\0'; 376 377 /* Skip any extra whitespace after first token */ 378 *s += strspn(*s + 1, WHITESPACE) + 1; 379 if (split_equals && *s[0] == '=' && !wspace) 380 *s += strspn(*s + 1, WHITESPACE) + 1; 381 382 return (old); 383 } 384 385 /* 386 * Return next token in configuration line; splts on whitespace or a 387 * single '=' character. 388 */ 389 char * 390 strdelim(char **s) 391 { 392 return strdelim_internal(s, 1); 393 } 394 395 /* 396 * Return next token in configuration line; splts on whitespace only. 397 */ 398 char * 399 strdelimw(char **s) 400 { 401 return strdelim_internal(s, 0); 402 } 403 404 struct passwd * 405 pwcopy(struct passwd *pw) 406 { 407 struct passwd *copy = xcalloc(1, sizeof(*copy)); 408 409 copy->pw_name = xstrdup(pw->pw_name); 410 copy->pw_passwd = xstrdup(pw->pw_passwd); 411 copy->pw_gecos = xstrdup(pw->pw_gecos); 412 copy->pw_uid = pw->pw_uid; 413 copy->pw_gid = pw->pw_gid; 414 copy->pw_expire = pw->pw_expire; 415 copy->pw_change = pw->pw_change; 416 copy->pw_class = xstrdup(pw->pw_class); 417 copy->pw_dir = xstrdup(pw->pw_dir); 418 copy->pw_shell = xstrdup(pw->pw_shell); 419 return copy; 420 } 421 422 /* 423 * Convert ASCII string to TCP/IP port number. 424 * Port must be >=0 and <=65535. 425 * Return -1 if invalid. 426 */ 427 int 428 a2port(const char *s) 429 { 430 struct servent *se; 431 long long port; 432 const char *errstr; 433 434 port = strtonum(s, 0, 65535, &errstr); 435 if (errstr == NULL) 436 return (int)port; 437 if ((se = getservbyname(s, "tcp")) != NULL) 438 return ntohs(se->s_port); 439 return -1; 440 } 441 442 int 443 a2tun(const char *s, int *remote) 444 { 445 const char *errstr = NULL; 446 char *sp, *ep; 447 int tun; 448 449 if (remote != NULL) { 450 *remote = SSH_TUNID_ANY; 451 sp = xstrdup(s); 452 if ((ep = strchr(sp, ':')) == NULL) { 453 free(sp); 454 return (a2tun(s, NULL)); 455 } 456 ep[0] = '\0'; ep++; 457 *remote = a2tun(ep, NULL); 458 tun = a2tun(sp, NULL); 459 free(sp); 460 return (*remote == SSH_TUNID_ERR ? *remote : tun); 461 } 462 463 if (strcasecmp(s, "any") == 0) 464 return (SSH_TUNID_ANY); 465 466 tun = strtonum(s, 0, SSH_TUNID_MAX, &errstr); 467 if (errstr != NULL) 468 return (SSH_TUNID_ERR); 469 470 return (tun); 471 } 472 473 #define SECONDS 1 474 #define MINUTES (SECONDS * 60) 475 #define HOURS (MINUTES * 60) 476 #define DAYS (HOURS * 24) 477 #define WEEKS (DAYS * 7) 478 479 /* 480 * Convert a time string into seconds; format is 481 * a sequence of: 482 * time[qualifier] 483 * 484 * Valid time qualifiers are: 485 * <none> seconds 486 * s|S seconds 487 * m|M minutes 488 * h|H hours 489 * d|D days 490 * w|W weeks 491 * 492 * Examples: 493 * 90m 90 minutes 494 * 1h30m 90 minutes 495 * 2d 2 days 496 * 1w 1 week 497 * 498 * Return -1 if time string is invalid. 499 */ 500 long 501 convtime(const char *s) 502 { 503 long total, secs, multiplier; 504 const char *p; 505 char *endp; 506 507 errno = 0; 508 total = 0; 509 p = s; 510 511 if (p == NULL || *p == '\0') 512 return -1; 513 514 while (*p) { 515 secs = strtol(p, &endp, 10); 516 if (p == endp || 517 (errno == ERANGE && (secs == LONG_MIN || secs == LONG_MAX)) || 518 secs < 0) 519 return -1; 520 521 multiplier = 1; 522 switch (*endp++) { 523 case '\0': 524 endp--; 525 break; 526 case 's': 527 case 'S': 528 break; 529 case 'm': 530 case 'M': 531 multiplier = MINUTES; 532 break; 533 case 'h': 534 case 'H': 535 multiplier = HOURS; 536 break; 537 case 'd': 538 case 'D': 539 multiplier = DAYS; 540 break; 541 case 'w': 542 case 'W': 543 multiplier = WEEKS; 544 break; 545 default: 546 return -1; 547 } 548 if (secs >= LONG_MAX / multiplier) 549 return -1; 550 secs *= multiplier; 551 if (total >= LONG_MAX - secs) 552 return -1; 553 total += secs; 554 if (total < 0) 555 return -1; 556 p = endp; 557 } 558 559 return total; 560 } 561 562 #define TF_BUFS 8 563 #define TF_LEN 9 564 565 const char * 566 fmt_timeframe(time_t t) 567 { 568 char *buf; 569 static char tfbuf[TF_BUFS][TF_LEN]; /* ring buffer */ 570 static int idx = 0; 571 unsigned int sec, min, hrs, day; 572 unsigned long long week; 573 574 buf = tfbuf[idx++]; 575 if (idx == TF_BUFS) 576 idx = 0; 577 578 week = t; 579 580 sec = week % 60; 581 week /= 60; 582 min = week % 60; 583 week /= 60; 584 hrs = week % 24; 585 week /= 24; 586 day = week % 7; 587 week /= 7; 588 589 if (week > 0) 590 snprintf(buf, TF_LEN, "%02lluw%01ud%02uh", week, day, hrs); 591 else if (day > 0) 592 snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min); 593 else 594 snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec); 595 596 return (buf); 597 } 598 599 /* 600 * Returns a standardized host+port identifier string. 601 * Caller must free returned string. 602 */ 603 char * 604 put_host_port(const char *host, u_short port) 605 { 606 char *hoststr; 607 608 if (port == 0 || port == SSH_DEFAULT_PORT) 609 return(xstrdup(host)); 610 if (asprintf(&hoststr, "[%s]:%d", host, (int)port) == -1) 611 fatal("put_host_port: asprintf: %s", strerror(errno)); 612 debug3("put_host_port: %s", hoststr); 613 return hoststr; 614 } 615 616 /* 617 * Search for next delimiter between hostnames/addresses and ports. 618 * Argument may be modified (for termination). 619 * Returns *cp if parsing succeeds. 620 * *cp is set to the start of the next field, if one was found. 621 * The delimiter char, if present, is stored in delim. 622 * If this is the last field, *cp is set to NULL. 623 */ 624 char * 625 hpdelim2(char **cp, char *delim) 626 { 627 char *s, *old; 628 629 if (cp == NULL || *cp == NULL) 630 return NULL; 631 632 old = s = *cp; 633 if (*s == '[') { 634 if ((s = strchr(s, ']')) == NULL) 635 return NULL; 636 else 637 s++; 638 } else if ((s = strpbrk(s, ":/")) == NULL) 639 s = *cp + strlen(*cp); /* skip to end (see first case below) */ 640 641 switch (*s) { 642 case '\0': 643 *cp = NULL; /* no more fields*/ 644 break; 645 646 case ':': 647 case '/': 648 if (delim != NULL) 649 *delim = *s; 650 *s = '\0'; /* terminate */ 651 *cp = s + 1; 652 break; 653 654 default: 655 return NULL; 656 } 657 658 return old; 659 } 660 661 char * 662 hpdelim(char **cp) 663 { 664 return hpdelim2(cp, NULL); 665 } 666 667 char * 668 cleanhostname(char *host) 669 { 670 if (*host == '[' && host[strlen(host) - 1] == ']') { 671 host[strlen(host) - 1] = '\0'; 672 return (host + 1); 673 } else 674 return host; 675 } 676 677 char * 678 colon(char *cp) 679 { 680 int flag = 0; 681 682 if (*cp == ':') /* Leading colon is part of file name. */ 683 return NULL; 684 if (*cp == '[') 685 flag = 1; 686 687 for (; *cp; ++cp) { 688 if (*cp == '@' && *(cp+1) == '[') 689 flag = 1; 690 if (*cp == ']' && *(cp+1) == ':' && flag) 691 return (cp+1); 692 if (*cp == ':' && !flag) 693 return (cp); 694 if (*cp == '/') 695 return NULL; 696 } 697 return NULL; 698 } 699 700 /* 701 * Parse a [user@]host:[path] string. 702 * Caller must free returned user, host and path. 703 * Any of the pointer return arguments may be NULL (useful for syntax checking). 704 * If user was not specified then *userp will be set to NULL. 705 * If host was not specified then *hostp will be set to NULL. 706 * If path was not specified then *pathp will be set to ".". 707 * Returns 0 on success, -1 on failure. 708 */ 709 int 710 parse_user_host_path(const char *s, char **userp, char **hostp, char **pathp) 711 { 712 char *user = NULL, *host = NULL, *path = NULL; 713 char *sdup, *tmp; 714 int ret = -1; 715 716 if (userp != NULL) 717 *userp = NULL; 718 if (hostp != NULL) 719 *hostp = NULL; 720 if (pathp != NULL) 721 *pathp = NULL; 722 723 sdup = xstrdup(s); 724 725 /* Check for remote syntax: [user@]host:[path] */ 726 if ((tmp = colon(sdup)) == NULL) 727 goto out; 728 729 /* Extract optional path */ 730 *tmp++ = '\0'; 731 if (*tmp == '\0') 732 tmp = "."; 733 path = xstrdup(tmp); 734 735 /* Extract optional user and mandatory host */ 736 tmp = strrchr(sdup, '@'); 737 if (tmp != NULL) { 738 *tmp++ = '\0'; 739 host = xstrdup(cleanhostname(tmp)); 740 if (*sdup != '\0') 741 user = xstrdup(sdup); 742 } else { 743 host = xstrdup(cleanhostname(sdup)); 744 user = NULL; 745 } 746 747 /* Success */ 748 if (userp != NULL) { 749 *userp = user; 750 user = NULL; 751 } 752 if (hostp != NULL) { 753 *hostp = host; 754 host = NULL; 755 } 756 if (pathp != NULL) { 757 *pathp = path; 758 path = NULL; 759 } 760 ret = 0; 761 out: 762 free(sdup); 763 free(user); 764 free(host); 765 free(path); 766 return ret; 767 } 768 769 /* 770 * Parse a [user@]host[:port] string. 771 * Caller must free returned user and host. 772 * Any of the pointer return arguments may be NULL (useful for syntax checking). 773 * If user was not specified then *userp will be set to NULL. 774 * If port was not specified then *portp will be -1. 775 * Returns 0 on success, -1 on failure. 776 */ 777 int 778 parse_user_host_port(const char *s, char **userp, char **hostp, int *portp) 779 { 780 char *sdup, *cp, *tmp; 781 char *user = NULL, *host = NULL; 782 int port = -1, ret = -1; 783 784 if (userp != NULL) 785 *userp = NULL; 786 if (hostp != NULL) 787 *hostp = NULL; 788 if (portp != NULL) 789 *portp = -1; 790 791 if ((sdup = tmp = strdup(s)) == NULL) 792 return -1; 793 /* Extract optional username */ 794 if ((cp = strrchr(tmp, '@')) != NULL) { 795 *cp = '\0'; 796 if (*tmp == '\0') 797 goto out; 798 if ((user = strdup(tmp)) == NULL) 799 goto out; 800 tmp = cp + 1; 801 } 802 /* Extract mandatory hostname */ 803 if ((cp = hpdelim(&tmp)) == NULL || *cp == '\0') 804 goto out; 805 host = xstrdup(cleanhostname(cp)); 806 /* Convert and verify optional port */ 807 if (tmp != NULL && *tmp != '\0') { 808 if ((port = a2port(tmp)) <= 0) 809 goto out; 810 } 811 /* Success */ 812 if (userp != NULL) { 813 *userp = user; 814 user = NULL; 815 } 816 if (hostp != NULL) { 817 *hostp = host; 818 host = NULL; 819 } 820 if (portp != NULL) 821 *portp = port; 822 ret = 0; 823 out: 824 free(sdup); 825 free(user); 826 free(host); 827 return ret; 828 } 829 830 /* 831 * Converts a two-byte hex string to decimal. 832 * Returns the decimal value or -1 for invalid input. 833 */ 834 static int 835 hexchar(const char *s) 836 { 837 unsigned char result[2]; 838 int i; 839 840 for (i = 0; i < 2; i++) { 841 if (s[i] >= '0' && s[i] <= '9') 842 result[i] = (unsigned char)(s[i] - '0'); 843 else if (s[i] >= 'a' && s[i] <= 'f') 844 result[i] = (unsigned char)(s[i] - 'a') + 10; 845 else if (s[i] >= 'A' && s[i] <= 'F') 846 result[i] = (unsigned char)(s[i] - 'A') + 10; 847 else 848 return -1; 849 } 850 return (result[0] << 4) | result[1]; 851 } 852 853 /* 854 * Decode an url-encoded string. 855 * Returns a newly allocated string on success or NULL on failure. 856 */ 857 static char * 858 urldecode(const char *src) 859 { 860 char *ret, *dst; 861 int ch; 862 863 ret = xmalloc(strlen(src) + 1); 864 for (dst = ret; *src != '\0'; src++) { 865 switch (*src) { 866 case '+': 867 *dst++ = ' '; 868 break; 869 case '%': 870 if (!isxdigit((unsigned char)src[1]) || 871 !isxdigit((unsigned char)src[2]) || 872 (ch = hexchar(src + 1)) == -1) { 873 free(ret); 874 return NULL; 875 } 876 *dst++ = ch; 877 src += 2; 878 break; 879 default: 880 *dst++ = *src; 881 break; 882 } 883 } 884 *dst = '\0'; 885 886 return ret; 887 } 888 889 /* 890 * Parse an (scp|ssh|sftp)://[user@]host[:port][/path] URI. 891 * See https://tools.ietf.org/html/draft-ietf-secsh-scp-sftp-ssh-uri-04 892 * Either user or path may be url-encoded (but not host or port). 893 * Caller must free returned user, host and path. 894 * Any of the pointer return arguments may be NULL (useful for syntax checking) 895 * but the scheme must always be specified. 896 * If user was not specified then *userp will be set to NULL. 897 * If port was not specified then *portp will be -1. 898 * If path was not specified then *pathp will be set to NULL. 899 * Returns 0 on success, 1 if non-uri/wrong scheme, -1 on error/invalid uri. 900 */ 901 int 902 parse_uri(const char *scheme, const char *uri, char **userp, char **hostp, 903 int *portp, char **pathp) 904 { 905 char *uridup, *cp, *tmp, ch; 906 char *user = NULL, *host = NULL, *path = NULL; 907 int port = -1, ret = -1; 908 size_t len; 909 910 len = strlen(scheme); 911 if (strncmp(uri, scheme, len) != 0 || strncmp(uri + len, "://", 3) != 0) 912 return 1; 913 uri += len + 3; 914 915 if (userp != NULL) 916 *userp = NULL; 917 if (hostp != NULL) 918 *hostp = NULL; 919 if (portp != NULL) 920 *portp = -1; 921 if (pathp != NULL) 922 *pathp = NULL; 923 924 uridup = tmp = xstrdup(uri); 925 926 /* Extract optional ssh-info (username + connection params) */ 927 if ((cp = strchr(tmp, '@')) != NULL) { 928 char *delim; 929 930 *cp = '\0'; 931 /* Extract username and connection params */ 932 if ((delim = strchr(tmp, ';')) != NULL) { 933 /* Just ignore connection params for now */ 934 *delim = '\0'; 935 } 936 if (*tmp == '\0') { 937 /* Empty username */ 938 goto out; 939 } 940 if ((user = urldecode(tmp)) == NULL) 941 goto out; 942 tmp = cp + 1; 943 } 944 945 /* Extract mandatory hostname */ 946 if ((cp = hpdelim2(&tmp, &ch)) == NULL || *cp == '\0') 947 goto out; 948 host = xstrdup(cleanhostname(cp)); 949 if (!valid_domain(host, 0, NULL)) 950 goto out; 951 952 if (tmp != NULL && *tmp != '\0') { 953 if (ch == ':') { 954 /* Convert and verify port. */ 955 if ((cp = strchr(tmp, '/')) != NULL) 956 *cp = '\0'; 957 if ((port = a2port(tmp)) <= 0) 958 goto out; 959 tmp = cp ? cp + 1 : NULL; 960 } 961 if (tmp != NULL && *tmp != '\0') { 962 /* Extract optional path */ 963 if ((path = urldecode(tmp)) == NULL) 964 goto out; 965 } 966 } 967 968 /* Success */ 969 if (userp != NULL) { 970 *userp = user; 971 user = NULL; 972 } 973 if (hostp != NULL) { 974 *hostp = host; 975 host = NULL; 976 } 977 if (portp != NULL) 978 *portp = port; 979 if (pathp != NULL) { 980 *pathp = path; 981 path = NULL; 982 } 983 ret = 0; 984 out: 985 free(uridup); 986 free(user); 987 free(host); 988 free(path); 989 return ret; 990 } 991 992 /* function to assist building execv() arguments */ 993 void 994 addargs(arglist *args, char *fmt, ...) 995 { 996 va_list ap; 997 char *cp; 998 u_int nalloc; 999 int r; 1000 1001 va_start(ap, fmt); 1002 r = vasprintf(&cp, fmt, ap); 1003 va_end(ap); 1004 if (r == -1) 1005 fatal("addargs: argument too long"); 1006 1007 nalloc = args->nalloc; 1008 if (args->list == NULL) { 1009 nalloc = 32; 1010 args->num = 0; 1011 } else if (args->num+2 >= nalloc) 1012 nalloc *= 2; 1013 1014 args->list = xrecallocarray(args->list, args->nalloc, nalloc, sizeof(char *)); 1015 args->nalloc = nalloc; 1016 args->list[args->num++] = cp; 1017 args->list[args->num] = NULL; 1018 } 1019 1020 void 1021 replacearg(arglist *args, u_int which, char *fmt, ...) 1022 { 1023 va_list ap; 1024 char *cp; 1025 int r; 1026 1027 va_start(ap, fmt); 1028 r = vasprintf(&cp, fmt, ap); 1029 va_end(ap); 1030 if (r == -1) 1031 fatal("replacearg: argument too long"); 1032 1033 if (which >= args->num) 1034 fatal("replacearg: tried to replace invalid arg %d >= %d", 1035 which, args->num); 1036 free(args->list[which]); 1037 args->list[which] = cp; 1038 } 1039 1040 void 1041 freeargs(arglist *args) 1042 { 1043 u_int i; 1044 1045 if (args->list != NULL) { 1046 for (i = 0; i < args->num; i++) 1047 free(args->list[i]); 1048 free(args->list); 1049 args->nalloc = args->num = 0; 1050 args->list = NULL; 1051 } 1052 } 1053 1054 /* 1055 * Expands tildes in the file name. Returns data allocated by xmalloc. 1056 * Warning: this calls getpw*. 1057 */ 1058 char * 1059 tilde_expand_filename(const char *filename, uid_t uid) 1060 { 1061 const char *path, *sep; 1062 char user[128], *ret; 1063 struct passwd *pw; 1064 u_int len, slash; 1065 1066 if (*filename != '~') 1067 return (xstrdup(filename)); 1068 filename++; 1069 1070 path = strchr(filename, '/'); 1071 if (path != NULL && path > filename) { /* ~user/path */ 1072 slash = path - filename; 1073 if (slash > sizeof(user) - 1) 1074 fatal("tilde_expand_filename: ~username too long"); 1075 memcpy(user, filename, slash); 1076 user[slash] = '\0'; 1077 if ((pw = getpwnam(user)) == NULL) 1078 fatal("tilde_expand_filename: No such user %s", user); 1079 } else if ((pw = getpwuid(uid)) == NULL) /* ~/path */ 1080 fatal("tilde_expand_filename: No such uid %ld", (long)uid); 1081 1082 /* Make sure directory has a trailing '/' */ 1083 len = strlen(pw->pw_dir); 1084 if (len == 0 || pw->pw_dir[len - 1] != '/') 1085 sep = "/"; 1086 else 1087 sep = ""; 1088 1089 /* Skip leading '/' from specified path */ 1090 if (path != NULL) 1091 filename = path + 1; 1092 1093 if (xasprintf(&ret, "%s%s%s", pw->pw_dir, sep, filename) >= PATH_MAX) 1094 fatal("tilde_expand_filename: Path too long"); 1095 1096 return (ret); 1097 } 1098 1099 /* 1100 * Expand a string with a set of %[char] escapes and/or ${ENVIRONMENT} 1101 * substitutions. A number of escapes may be specified as 1102 * (char *escape_chars, char *replacement) pairs. The list must be terminated 1103 * by a NULL escape_char. Returns replaced string in memory allocated by 1104 * xmalloc which the caller must free. 1105 */ 1106 static char * 1107 vdollar_percent_expand(int *parseerror, int dollar, int percent, 1108 const char *string, va_list ap) 1109 { 1110 #define EXPAND_MAX_KEYS 16 1111 u_int num_keys = 0, i; 1112 struct { 1113 const char *key; 1114 const char *repl; 1115 } keys[EXPAND_MAX_KEYS]; 1116 struct sshbuf *buf; 1117 int r, missingvar = 0; 1118 char *ret = NULL, *var, *varend, *val; 1119 size_t len; 1120 1121 if ((buf = sshbuf_new()) == NULL) 1122 fatal_f("sshbuf_new failed"); 1123 if (parseerror == NULL) 1124 fatal_f("null parseerror arg"); 1125 *parseerror = 1; 1126 1127 /* Gather keys if we're doing percent expansion. */ 1128 if (percent) { 1129 for (num_keys = 0; num_keys < EXPAND_MAX_KEYS; num_keys++) { 1130 keys[num_keys].key = va_arg(ap, char *); 1131 if (keys[num_keys].key == NULL) 1132 break; 1133 keys[num_keys].repl = va_arg(ap, char *); 1134 if (keys[num_keys].repl == NULL) { 1135 fatal_f("NULL replacement for token %s", 1136 keys[num_keys].key); 1137 } 1138 } 1139 if (num_keys == EXPAND_MAX_KEYS && va_arg(ap, char *) != NULL) 1140 fatal_f("too many keys"); 1141 if (num_keys == 0) 1142 fatal_f("percent expansion without token list"); 1143 } 1144 1145 /* Expand string */ 1146 for (i = 0; *string != '\0'; string++) { 1147 /* Optionally process ${ENVIRONMENT} expansions. */ 1148 if (dollar && string[0] == '$' && string[1] == '{') { 1149 string += 2; /* skip over '${' */ 1150 if ((varend = strchr(string, '}')) == NULL) { 1151 error_f("environment variable '%s' missing " 1152 "closing '}'", string); 1153 goto out; 1154 } 1155 len = varend - string; 1156 if (len == 0) { 1157 error_f("zero-length environment variable"); 1158 goto out; 1159 } 1160 var = xmalloc(len + 1); 1161 (void)strlcpy(var, string, len + 1); 1162 if ((val = getenv(var)) == NULL) { 1163 error_f("env var ${%s} has no value", var); 1164 missingvar = 1; 1165 } else { 1166 debug3_f("expand ${%s} -> '%s'", var, val); 1167 if ((r = sshbuf_put(buf, val, strlen(val))) !=0) 1168 fatal_fr(r, "sshbuf_put ${}"); 1169 } 1170 free(var); 1171 string += len; 1172 continue; 1173 } 1174 1175 /* 1176 * Process percent expansions if we have a list of TOKENs. 1177 * If we're not doing percent expansion everything just gets 1178 * appended here. 1179 */ 1180 if (*string != '%' || !percent) { 1181 append: 1182 if ((r = sshbuf_put_u8(buf, *string)) != 0) 1183 fatal_fr(r, "sshbuf_put_u8 %%"); 1184 continue; 1185 } 1186 string++; 1187 /* %% case */ 1188 if (*string == '%') 1189 goto append; 1190 if (*string == '\0') { 1191 error_f("invalid format"); 1192 goto out; 1193 } 1194 for (i = 0; i < num_keys; i++) { 1195 if (strchr(keys[i].key, *string) != NULL) { 1196 if ((r = sshbuf_put(buf, keys[i].repl, 1197 strlen(keys[i].repl))) != 0) 1198 fatal_fr(r, "sshbuf_put %%-repl"); 1199 break; 1200 } 1201 } 1202 if (i >= num_keys) { 1203 error_f("unknown key %%%c", *string); 1204 goto out; 1205 } 1206 } 1207 if (!missingvar && (ret = sshbuf_dup_string(buf)) == NULL) 1208 fatal_f("sshbuf_dup_string failed"); 1209 *parseerror = 0; 1210 out: 1211 sshbuf_free(buf); 1212 return *parseerror ? NULL : ret; 1213 #undef EXPAND_MAX_KEYS 1214 } 1215 1216 /* 1217 * Expand only environment variables. 1218 * Note that although this function is variadic like the other similar 1219 * functions, any such arguments will be unused. 1220 */ 1221 1222 char * 1223 dollar_expand(int *parseerr, const char *string, ...) 1224 { 1225 char *ret; 1226 int err; 1227 va_list ap; 1228 1229 va_start(ap, string); 1230 ret = vdollar_percent_expand(&err, 1, 0, string, ap); 1231 va_end(ap); 1232 if (parseerr != NULL) 1233 *parseerr = err; 1234 return ret; 1235 } 1236 1237 /* 1238 * Returns expanded string or NULL if a specified environment variable is 1239 * not defined, or calls fatal if the string is invalid. 1240 */ 1241 char * 1242 percent_expand(const char *string, ...) 1243 { 1244 char *ret; 1245 int err; 1246 va_list ap; 1247 1248 va_start(ap, string); 1249 ret = vdollar_percent_expand(&err, 0, 1, string, ap); 1250 va_end(ap); 1251 if (err) 1252 fatal_f("failed"); 1253 return ret; 1254 } 1255 1256 /* 1257 * Returns expanded string or NULL if a specified environment variable is 1258 * not defined, or calls fatal if the string is invalid. 1259 */ 1260 char * 1261 percent_dollar_expand(const char *string, ...) 1262 { 1263 char *ret; 1264 int err; 1265 va_list ap; 1266 1267 va_start(ap, string); 1268 ret = vdollar_percent_expand(&err, 1, 1, string, ap); 1269 va_end(ap); 1270 if (err) 1271 fatal_f("failed"); 1272 return ret; 1273 } 1274 1275 int 1276 tun_open(int tun, int mode, char **ifname) 1277 { 1278 struct ifreq ifr; 1279 char name[100]; 1280 int fd = -1, sock; 1281 const char *tunbase = "tun"; 1282 1283 if (ifname != NULL) 1284 *ifname = NULL; 1285 1286 if (mode == SSH_TUNMODE_ETHERNET) 1287 tunbase = "tap"; 1288 1289 /* Open the tunnel device */ 1290 if (tun <= SSH_TUNID_MAX) { 1291 snprintf(name, sizeof(name), "/dev/%s%d", tunbase, tun); 1292 fd = open(name, O_RDWR); 1293 } else if (tun == SSH_TUNID_ANY) { 1294 for (tun = 100; tun >= 0; tun--) { 1295 snprintf(name, sizeof(name), "/dev/%s%d", 1296 tunbase, tun); 1297 if ((fd = open(name, O_RDWR)) >= 0) 1298 break; 1299 } 1300 } else { 1301 debug_f("invalid tunnel %u", tun); 1302 return -1; 1303 } 1304 1305 if (fd == -1) { 1306 debug_f("%s open: %s", name, strerror(errno)); 1307 return -1; 1308 } 1309 1310 debug_f("%s mode %d fd %d", name, mode, fd); 1311 1312 /* Bring interface up if it is not already */ 1313 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", tunbase, tun); 1314 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) 1315 goto failed; 1316 1317 if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) { 1318 debug_f("get interface %s flags: %s", ifr.ifr_name, 1319 strerror(errno)); 1320 goto failed; 1321 } 1322 1323 if (!(ifr.ifr_flags & IFF_UP)) { 1324 ifr.ifr_flags |= IFF_UP; 1325 if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) { 1326 debug_f("activate interface %s: %s", ifr.ifr_name, 1327 strerror(errno)); 1328 goto failed; 1329 } 1330 } 1331 1332 if (ifname != NULL) 1333 *ifname = xstrdup(ifr.ifr_name); 1334 1335 close(sock); 1336 return fd; 1337 1338 failed: 1339 if (fd >= 0) 1340 close(fd); 1341 if (sock >= 0) 1342 close(sock); 1343 return -1; 1344 } 1345 1346 void 1347 sanitise_stdfd(void) 1348 { 1349 int nullfd, dupfd; 1350 1351 if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 1352 fprintf(stderr, "Couldn't open /dev/null: %s\n", 1353 strerror(errno)); 1354 exit(1); 1355 } 1356 while (++dupfd <= STDERR_FILENO) { 1357 /* Only populate closed fds. */ 1358 if (fcntl(dupfd, F_GETFL) == -1 && errno == EBADF) { 1359 if (dup2(nullfd, dupfd) == -1) { 1360 fprintf(stderr, "dup2: %s\n", strerror(errno)); 1361 exit(1); 1362 } 1363 } 1364 } 1365 if (nullfd > STDERR_FILENO) 1366 close(nullfd); 1367 } 1368 1369 char * 1370 tohex(const void *vp, size_t l) 1371 { 1372 const u_char *p = (const u_char *)vp; 1373 char b[3], *r; 1374 size_t i, hl; 1375 1376 if (l > 65536) 1377 return xstrdup("tohex: length > 65536"); 1378 1379 hl = l * 2 + 1; 1380 r = xcalloc(1, hl); 1381 for (i = 0; i < l; i++) { 1382 snprintf(b, sizeof(b), "%02x", p[i]); 1383 strlcat(r, b, hl); 1384 } 1385 return (r); 1386 } 1387 1388 /* 1389 * Extend string *sp by the specified format. If *sp is not NULL (or empty), 1390 * then the separator 'sep' will be prepended before the formatted arguments. 1391 * Extended strings are heap allocated. 1392 */ 1393 void 1394 xextendf(char **sp, const char *sep, const char *fmt, ...) 1395 { 1396 va_list ap; 1397 char *tmp1, *tmp2; 1398 1399 va_start(ap, fmt); 1400 xvasprintf(&tmp1, fmt, ap); 1401 va_end(ap); 1402 1403 if (*sp == NULL || **sp == '\0') { 1404 free(*sp); 1405 *sp = tmp1; 1406 return; 1407 } 1408 xasprintf(&tmp2, "%s%s%s", *sp, sep == NULL ? "" : sep, tmp1); 1409 free(tmp1); 1410 free(*sp); 1411 *sp = tmp2; 1412 } 1413 1414 1415 u_int64_t 1416 get_u64(const void *vp) 1417 { 1418 const u_char *p = (const u_char *)vp; 1419 u_int64_t v; 1420 1421 v = (u_int64_t)p[0] << 56; 1422 v |= (u_int64_t)p[1] << 48; 1423 v |= (u_int64_t)p[2] << 40; 1424 v |= (u_int64_t)p[3] << 32; 1425 v |= (u_int64_t)p[4] << 24; 1426 v |= (u_int64_t)p[5] << 16; 1427 v |= (u_int64_t)p[6] << 8; 1428 v |= (u_int64_t)p[7]; 1429 1430 return (v); 1431 } 1432 1433 u_int32_t 1434 get_u32(const void *vp) 1435 { 1436 const u_char *p = (const u_char *)vp; 1437 u_int32_t v; 1438 1439 v = (u_int32_t)p[0] << 24; 1440 v |= (u_int32_t)p[1] << 16; 1441 v |= (u_int32_t)p[2] << 8; 1442 v |= (u_int32_t)p[3]; 1443 1444 return (v); 1445 } 1446 1447 u_int32_t 1448 get_u32_le(const void *vp) 1449 { 1450 const u_char *p = (const u_char *)vp; 1451 u_int32_t v; 1452 1453 v = (u_int32_t)p[0]; 1454 v |= (u_int32_t)p[1] << 8; 1455 v |= (u_int32_t)p[2] << 16; 1456 v |= (u_int32_t)p[3] << 24; 1457 1458 return (v); 1459 } 1460 1461 u_int16_t 1462 get_u16(const void *vp) 1463 { 1464 const u_char *p = (const u_char *)vp; 1465 u_int16_t v; 1466 1467 v = (u_int16_t)p[0] << 8; 1468 v |= (u_int16_t)p[1]; 1469 1470 return (v); 1471 } 1472 1473 void 1474 put_u64(void *vp, u_int64_t v) 1475 { 1476 u_char *p = (u_char *)vp; 1477 1478 p[0] = (u_char)(v >> 56) & 0xff; 1479 p[1] = (u_char)(v >> 48) & 0xff; 1480 p[2] = (u_char)(v >> 40) & 0xff; 1481 p[3] = (u_char)(v >> 32) & 0xff; 1482 p[4] = (u_char)(v >> 24) & 0xff; 1483 p[5] = (u_char)(v >> 16) & 0xff; 1484 p[6] = (u_char)(v >> 8) & 0xff; 1485 p[7] = (u_char)v & 0xff; 1486 } 1487 1488 void 1489 put_u32(void *vp, u_int32_t v) 1490 { 1491 u_char *p = (u_char *)vp; 1492 1493 p[0] = (u_char)(v >> 24) & 0xff; 1494 p[1] = (u_char)(v >> 16) & 0xff; 1495 p[2] = (u_char)(v >> 8) & 0xff; 1496 p[3] = (u_char)v & 0xff; 1497 } 1498 1499 void 1500 put_u32_le(void *vp, u_int32_t v) 1501 { 1502 u_char *p = (u_char *)vp; 1503 1504 p[0] = (u_char)v & 0xff; 1505 p[1] = (u_char)(v >> 8) & 0xff; 1506 p[2] = (u_char)(v >> 16) & 0xff; 1507 p[3] = (u_char)(v >> 24) & 0xff; 1508 } 1509 1510 void 1511 put_u16(void *vp, u_int16_t v) 1512 { 1513 u_char *p = (u_char *)vp; 1514 1515 p[0] = (u_char)(v >> 8) & 0xff; 1516 p[1] = (u_char)v & 0xff; 1517 } 1518 1519 void 1520 ms_subtract_diff(struct timeval *start, int *ms) 1521 { 1522 struct timeval diff, finish; 1523 1524 monotime_tv(&finish); 1525 timersub(&finish, start, &diff); 1526 *ms -= (diff.tv_sec * 1000) + (diff.tv_usec / 1000); 1527 } 1528 1529 void 1530 ms_to_timeval(struct timeval *tv, int ms) 1531 { 1532 if (ms < 0) 1533 ms = 0; 1534 tv->tv_sec = ms / 1000; 1535 tv->tv_usec = (ms % 1000) * 1000; 1536 } 1537 1538 void 1539 monotime_ts(struct timespec *ts) 1540 { 1541 if (clock_gettime(CLOCK_MONOTONIC, ts) != 0) 1542 fatal("clock_gettime: %s", strerror(errno)); 1543 } 1544 1545 void 1546 monotime_tv(struct timeval *tv) 1547 { 1548 struct timespec ts; 1549 1550 monotime_ts(&ts); 1551 tv->tv_sec = ts.tv_sec; 1552 tv->tv_usec = ts.tv_nsec / 1000; 1553 } 1554 1555 time_t 1556 monotime(void) 1557 { 1558 struct timespec ts; 1559 1560 monotime_ts(&ts); 1561 return (ts.tv_sec); 1562 } 1563 1564 double 1565 monotime_double(void) 1566 { 1567 struct timespec ts; 1568 1569 monotime_ts(&ts); 1570 return (double)ts.tv_sec + (double)ts.tv_nsec / 1000000000.0; 1571 } 1572 1573 void 1574 bandwidth_limit_init(struct bwlimit *bw, u_int64_t kbps, size_t buflen) 1575 { 1576 bw->buflen = buflen; 1577 bw->rate = kbps; 1578 bw->thresh = buflen; 1579 bw->lamt = 0; 1580 timerclear(&bw->bwstart); 1581 timerclear(&bw->bwend); 1582 } 1583 1584 /* Callback from read/write loop to insert bandwidth-limiting delays */ 1585 void 1586 bandwidth_limit(struct bwlimit *bw, size_t read_len) 1587 { 1588 u_int64_t waitlen; 1589 struct timespec ts, rm; 1590 1591 bw->lamt += read_len; 1592 if (!timerisset(&bw->bwstart)) { 1593 monotime_tv(&bw->bwstart); 1594 return; 1595 } 1596 if (bw->lamt < bw->thresh) 1597 return; 1598 1599 monotime_tv(&bw->bwend); 1600 timersub(&bw->bwend, &bw->bwstart, &bw->bwend); 1601 if (!timerisset(&bw->bwend)) 1602 return; 1603 1604 bw->lamt *= 8; 1605 waitlen = (double)1000000L * bw->lamt / bw->rate; 1606 1607 bw->bwstart.tv_sec = waitlen / 1000000L; 1608 bw->bwstart.tv_usec = waitlen % 1000000L; 1609 1610 if (timercmp(&bw->bwstart, &bw->bwend, >)) { 1611 timersub(&bw->bwstart, &bw->bwend, &bw->bwend); 1612 1613 /* Adjust the wait time */ 1614 if (bw->bwend.tv_sec) { 1615 bw->thresh /= 2; 1616 if (bw->thresh < bw->buflen / 4) 1617 bw->thresh = bw->buflen / 4; 1618 } else if (bw->bwend.tv_usec < 10000) { 1619 bw->thresh *= 2; 1620 if (bw->thresh > bw->buflen * 8) 1621 bw->thresh = bw->buflen * 8; 1622 } 1623 1624 TIMEVAL_TO_TIMESPEC(&bw->bwend, &ts); 1625 while (nanosleep(&ts, &rm) == -1) { 1626 if (errno != EINTR) 1627 break; 1628 ts = rm; 1629 } 1630 } 1631 1632 bw->lamt = 0; 1633 monotime_tv(&bw->bwstart); 1634 } 1635 1636 /* Make a template filename for mk[sd]temp() */ 1637 void 1638 mktemp_proto(char *s, size_t len) 1639 { 1640 const char *tmpdir; 1641 int r; 1642 1643 if ((tmpdir = getenv("TMPDIR")) != NULL) { 1644 r = snprintf(s, len, "%s/ssh-XXXXXXXXXXXX", tmpdir); 1645 if (r > 0 && (size_t)r < len) 1646 return; 1647 } 1648 r = snprintf(s, len, "/tmp/ssh-XXXXXXXXXXXX"); 1649 if (r < 0 || (size_t)r >= len) 1650 fatal_f("template string too short"); 1651 } 1652 1653 static const struct { 1654 const char *name; 1655 int value; 1656 } ipqos[] = { 1657 { "none", INT_MAX }, /* can't use 0 here; that's CS0 */ 1658 { "af11", IPTOS_DSCP_AF11 }, 1659 { "af12", IPTOS_DSCP_AF12 }, 1660 { "af13", IPTOS_DSCP_AF13 }, 1661 { "af21", IPTOS_DSCP_AF21 }, 1662 { "af22", IPTOS_DSCP_AF22 }, 1663 { "af23", IPTOS_DSCP_AF23 }, 1664 { "af31", IPTOS_DSCP_AF31 }, 1665 { "af32", IPTOS_DSCP_AF32 }, 1666 { "af33", IPTOS_DSCP_AF33 }, 1667 { "af41", IPTOS_DSCP_AF41 }, 1668 { "af42", IPTOS_DSCP_AF42 }, 1669 { "af43", IPTOS_DSCP_AF43 }, 1670 { "cs0", IPTOS_DSCP_CS0 }, 1671 { "cs1", IPTOS_DSCP_CS1 }, 1672 { "cs2", IPTOS_DSCP_CS2 }, 1673 { "cs3", IPTOS_DSCP_CS3 }, 1674 { "cs4", IPTOS_DSCP_CS4 }, 1675 { "cs5", IPTOS_DSCP_CS5 }, 1676 { "cs6", IPTOS_DSCP_CS6 }, 1677 { "cs7", IPTOS_DSCP_CS7 }, 1678 { "ef", IPTOS_DSCP_EF }, 1679 { "le", IPTOS_DSCP_LE }, 1680 { "lowdelay", IPTOS_LOWDELAY }, 1681 { "throughput", IPTOS_THROUGHPUT }, 1682 { "reliability", IPTOS_RELIABILITY }, 1683 { NULL, -1 } 1684 }; 1685 1686 int 1687 parse_ipqos(const char *cp) 1688 { 1689 u_int i; 1690 char *ep; 1691 long val; 1692 1693 if (cp == NULL) 1694 return -1; 1695 for (i = 0; ipqos[i].name != NULL; i++) { 1696 if (strcasecmp(cp, ipqos[i].name) == 0) 1697 return ipqos[i].value; 1698 } 1699 /* Try parsing as an integer */ 1700 val = strtol(cp, &ep, 0); 1701 if (*cp == '\0' || *ep != '\0' || val < 0 || val > 255) 1702 return -1; 1703 return val; 1704 } 1705 1706 const char * 1707 iptos2str(int iptos) 1708 { 1709 int i; 1710 static char iptos_str[sizeof "0xff"]; 1711 1712 for (i = 0; ipqos[i].name != NULL; i++) { 1713 if (ipqos[i].value == iptos) 1714 return ipqos[i].name; 1715 } 1716 snprintf(iptos_str, sizeof iptos_str, "0x%02x", iptos); 1717 return iptos_str; 1718 } 1719 1720 void 1721 lowercase(char *s) 1722 { 1723 for (; *s; s++) 1724 *s = tolower((u_char)*s); 1725 } 1726 1727 int 1728 unix_listener(const char *path, int backlog, int unlink_first) 1729 { 1730 struct sockaddr_un sunaddr; 1731 int saved_errno, sock; 1732 1733 memset(&sunaddr, 0, sizeof(sunaddr)); 1734 sunaddr.sun_family = AF_UNIX; 1735 if (strlcpy(sunaddr.sun_path, path, 1736 sizeof(sunaddr.sun_path)) >= sizeof(sunaddr.sun_path)) { 1737 error_f("path \"%s\" too long for Unix domain socket", path); 1738 errno = ENAMETOOLONG; 1739 return -1; 1740 } 1741 1742 sock = socket(PF_UNIX, SOCK_STREAM, 0); 1743 if (sock == -1) { 1744 saved_errno = errno; 1745 error_f("socket: %.100s", strerror(errno)); 1746 errno = saved_errno; 1747 return -1; 1748 } 1749 if (unlink_first == 1) { 1750 if (unlink(path) != 0 && errno != ENOENT) 1751 error("unlink(%s): %.100s", path, strerror(errno)); 1752 } 1753 if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) { 1754 saved_errno = errno; 1755 error_f("cannot bind to path %s: %s", path, strerror(errno)); 1756 close(sock); 1757 errno = saved_errno; 1758 return -1; 1759 } 1760 if (listen(sock, backlog) == -1) { 1761 saved_errno = errno; 1762 error_f("cannot listen on path %s: %s", path, strerror(errno)); 1763 close(sock); 1764 unlink(path); 1765 errno = saved_errno; 1766 return -1; 1767 } 1768 return sock; 1769 } 1770 1771 /* 1772 * Compares two strings that maybe be NULL. Returns non-zero if strings 1773 * are both NULL or are identical, returns zero otherwise. 1774 */ 1775 static int 1776 strcmp_maybe_null(const char *a, const char *b) 1777 { 1778 if ((a == NULL && b != NULL) || (a != NULL && b == NULL)) 1779 return 0; 1780 if (a != NULL && strcmp(a, b) != 0) 1781 return 0; 1782 return 1; 1783 } 1784 1785 /* 1786 * Compare two forwards, returning non-zero if they are identical or 1787 * zero otherwise. 1788 */ 1789 int 1790 forward_equals(const struct Forward *a, const struct Forward *b) 1791 { 1792 if (strcmp_maybe_null(a->listen_host, b->listen_host) == 0) 1793 return 0; 1794 if (a->listen_port != b->listen_port) 1795 return 0; 1796 if (strcmp_maybe_null(a->listen_path, b->listen_path) == 0) 1797 return 0; 1798 if (strcmp_maybe_null(a->connect_host, b->connect_host) == 0) 1799 return 0; 1800 if (a->connect_port != b->connect_port) 1801 return 0; 1802 if (strcmp_maybe_null(a->connect_path, b->connect_path) == 0) 1803 return 0; 1804 /* allocated_port and handle are not checked */ 1805 return 1; 1806 } 1807 1808 /* returns 1 if process is already daemonized, 0 otherwise */ 1809 int 1810 daemonized(void) 1811 { 1812 int fd; 1813 1814 if ((fd = open(_PATH_TTY, O_RDONLY | O_NOCTTY)) >= 0) { 1815 close(fd); 1816 return 0; /* have controlling terminal */ 1817 } 1818 if (getppid() != 1) 1819 return 0; /* parent is not init */ 1820 if (getsid(0) != getpid()) 1821 return 0; /* not session leader */ 1822 debug3("already daemonized"); 1823 return 1; 1824 } 1825 1826 1827 /* 1828 * Splits 's' into an argument vector. Handles quoted string and basic 1829 * escape characters (\\, \", \'). Caller must free the argument vector 1830 * and its members. 1831 */ 1832 int 1833 argv_split(const char *s, int *argcp, char ***argvp) 1834 { 1835 int r = SSH_ERR_INTERNAL_ERROR; 1836 int argc = 0, quote, i, j; 1837 char *arg, **argv = xcalloc(1, sizeof(*argv)); 1838 1839 *argvp = NULL; 1840 *argcp = 0; 1841 1842 for (i = 0; s[i] != '\0'; i++) { 1843 /* Skip leading whitespace */ 1844 if (s[i] == ' ' || s[i] == '\t') 1845 continue; 1846 1847 /* Start of a token */ 1848 quote = 0; 1849 if (s[i] == '\\' && 1850 (s[i + 1] == '\'' || s[i + 1] == '\"' || s[i + 1] == '\\')) 1851 i++; 1852 else if (s[i] == '\'' || s[i] == '"') 1853 quote = s[i++]; 1854 1855 argv = xreallocarray(argv, (argc + 2), sizeof(*argv)); 1856 arg = argv[argc++] = xcalloc(1, strlen(s + i) + 1); 1857 argv[argc] = NULL; 1858 1859 /* Copy the token in, removing escapes */ 1860 for (j = 0; s[i] != '\0'; i++) { 1861 if (s[i] == '\\') { 1862 if (s[i + 1] == '\'' || 1863 s[i + 1] == '\"' || 1864 s[i + 1] == '\\') { 1865 i++; /* Skip '\' */ 1866 arg[j++] = s[i]; 1867 } else { 1868 /* Unrecognised escape */ 1869 arg[j++] = s[i]; 1870 } 1871 } else if (quote == 0 && (s[i] == ' ' || s[i] == '\t')) 1872 break; /* done */ 1873 else if (quote != 0 && s[i] == quote) 1874 break; /* done */ 1875 else 1876 arg[j++] = s[i]; 1877 } 1878 if (s[i] == '\0') { 1879 if (quote != 0) { 1880 /* Ran out of string looking for close quote */ 1881 r = SSH_ERR_INVALID_FORMAT; 1882 goto out; 1883 } 1884 break; 1885 } 1886 } 1887 /* Success */ 1888 *argcp = argc; 1889 *argvp = argv; 1890 argc = 0; 1891 argv = NULL; 1892 r = 0; 1893 out: 1894 if (argc != 0 && argv != NULL) { 1895 for (i = 0; i < argc; i++) 1896 free(argv[i]); 1897 free(argv); 1898 } 1899 return r; 1900 } 1901 1902 /* 1903 * Reassemble an argument vector into a string, quoting and escaping as 1904 * necessary. Caller must free returned string. 1905 */ 1906 char * 1907 argv_assemble(int argc, char **argv) 1908 { 1909 int i, j, ws, r; 1910 char c, *ret; 1911 struct sshbuf *buf, *arg; 1912 1913 if ((buf = sshbuf_new()) == NULL || (arg = sshbuf_new()) == NULL) 1914 fatal_f("sshbuf_new failed"); 1915 1916 for (i = 0; i < argc; i++) { 1917 ws = 0; 1918 sshbuf_reset(arg); 1919 for (j = 0; argv[i][j] != '\0'; j++) { 1920 r = 0; 1921 c = argv[i][j]; 1922 switch (c) { 1923 case ' ': 1924 case '\t': 1925 ws = 1; 1926 r = sshbuf_put_u8(arg, c); 1927 break; 1928 case '\\': 1929 case '\'': 1930 case '"': 1931 if ((r = sshbuf_put_u8(arg, '\\')) != 0) 1932 break; 1933 /* FALLTHROUGH */ 1934 default: 1935 r = sshbuf_put_u8(arg, c); 1936 break; 1937 } 1938 if (r != 0) 1939 fatal_fr(r, "sshbuf_put_u8"); 1940 } 1941 if ((i != 0 && (r = sshbuf_put_u8(buf, ' ')) != 0) || 1942 (ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0) || 1943 (r = sshbuf_putb(buf, arg)) != 0 || 1944 (ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0)) 1945 fatal_fr(r, "assemble"); 1946 } 1947 if ((ret = malloc(sshbuf_len(buf) + 1)) == NULL) 1948 fatal_f("malloc failed"); 1949 memcpy(ret, sshbuf_ptr(buf), sshbuf_len(buf)); 1950 ret[sshbuf_len(buf)] = '\0'; 1951 sshbuf_free(buf); 1952 sshbuf_free(arg); 1953 return ret; 1954 } 1955 1956 /* Returns 0 if pid exited cleanly, non-zero otherwise */ 1957 int 1958 exited_cleanly(pid_t pid, const char *tag, const char *cmd, int quiet) 1959 { 1960 int status; 1961 1962 while (waitpid(pid, &status, 0) == -1) { 1963 if (errno != EINTR) { 1964 error("%s waitpid: %s", tag, strerror(errno)); 1965 return -1; 1966 } 1967 } 1968 if (WIFSIGNALED(status)) { 1969 error("%s %s exited on signal %d", tag, cmd, WTERMSIG(status)); 1970 return -1; 1971 } else if (WEXITSTATUS(status) != 0) { 1972 do_log2(quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_INFO, 1973 "%s %s failed, status %d", tag, cmd, WEXITSTATUS(status)); 1974 return -1; 1975 } 1976 return 0; 1977 } 1978 1979 /* 1980 * Check a given path for security. This is defined as all components 1981 * of the path to the file must be owned by either the owner of 1982 * of the file or root and no directories must be group or world writable. 1983 * 1984 * XXX Should any specific check be done for sym links ? 1985 * 1986 * Takes a file name, its stat information (preferably from fstat() to 1987 * avoid races), the uid of the expected owner, their home directory and an 1988 * error buffer plus max size as arguments. 1989 * 1990 * Returns 0 on success and -1 on failure 1991 */ 1992 int 1993 safe_path(const char *name, struct stat *stp, const char *pw_dir, 1994 uid_t uid, char *err, size_t errlen) 1995 { 1996 char buf[PATH_MAX], homedir[PATH_MAX]; 1997 char *cp; 1998 int comparehome = 0; 1999 struct stat st; 2000 2001 if (realpath(name, buf) == NULL) { 2002 snprintf(err, errlen, "realpath %s failed: %s", name, 2003 strerror(errno)); 2004 return -1; 2005 } 2006 if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL) 2007 comparehome = 1; 2008 2009 if (!S_ISREG(stp->st_mode)) { 2010 snprintf(err, errlen, "%s is not a regular file", buf); 2011 return -1; 2012 } 2013 if ((stp->st_uid != 0 && stp->st_uid != uid) || 2014 (stp->st_mode & 022) != 0) { 2015 snprintf(err, errlen, "bad ownership or modes for file %s", 2016 buf); 2017 return -1; 2018 } 2019 2020 /* for each component of the canonical path, walking upwards */ 2021 for (;;) { 2022 if ((cp = dirname(buf)) == NULL) { 2023 snprintf(err, errlen, "dirname() failed"); 2024 return -1; 2025 } 2026 strlcpy(buf, cp, sizeof(buf)); 2027 2028 if (stat(buf, &st) == -1 || 2029 (st.st_uid != 0 && st.st_uid != uid) || 2030 (st.st_mode & 022) != 0) { 2031 snprintf(err, errlen, 2032 "bad ownership or modes for directory %s", buf); 2033 return -1; 2034 } 2035 2036 /* If are past the homedir then we can stop */ 2037 if (comparehome && strcmp(homedir, buf) == 0) 2038 break; 2039 2040 /* 2041 * dirname should always complete with a "/" path, 2042 * but we can be paranoid and check for "." too 2043 */ 2044 if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0)) 2045 break; 2046 } 2047 return 0; 2048 } 2049 2050 /* 2051 * Version of safe_path() that accepts an open file descriptor to 2052 * avoid races. 2053 * 2054 * Returns 0 on success and -1 on failure 2055 */ 2056 int 2057 safe_path_fd(int fd, const char *file, struct passwd *pw, 2058 char *err, size_t errlen) 2059 { 2060 struct stat st; 2061 2062 /* check the open file to avoid races */ 2063 if (fstat(fd, &st) == -1) { 2064 snprintf(err, errlen, "cannot stat file %s: %s", 2065 file, strerror(errno)); 2066 return -1; 2067 } 2068 return safe_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen); 2069 } 2070 2071 /* 2072 * Sets the value of the given variable in the environment. If the variable 2073 * already exists, its value is overridden. 2074 */ 2075 void 2076 child_set_env(char ***envp, u_int *envsizep, const char *name, 2077 const char *value) 2078 { 2079 char **env; 2080 u_int envsize; 2081 u_int i, namelen; 2082 2083 if (strchr(name, '=') != NULL) { 2084 error("Invalid environment variable \"%.100s\"", name); 2085 return; 2086 } 2087 2088 /* 2089 * Find the slot where the value should be stored. If the variable 2090 * already exists, we reuse the slot; otherwise we append a new slot 2091 * at the end of the array, expanding if necessary. 2092 */ 2093 env = *envp; 2094 namelen = strlen(name); 2095 for (i = 0; env[i]; i++) 2096 if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=') 2097 break; 2098 if (env[i]) { 2099 /* Reuse the slot. */ 2100 free(env[i]); 2101 } else { 2102 /* New variable. Expand if necessary. */ 2103 envsize = *envsizep; 2104 if (i >= envsize - 1) { 2105 if (envsize >= 1000) 2106 fatal("child_set_env: too many env vars"); 2107 envsize += 50; 2108 env = (*envp) = xreallocarray(env, envsize, sizeof(char *)); 2109 *envsizep = envsize; 2110 } 2111 /* Need to set the NULL pointer at end of array beyond the new slot. */ 2112 env[i + 1] = NULL; 2113 } 2114 2115 /* Allocate space and format the variable in the appropriate slot. */ 2116 /* XXX xasprintf */ 2117 env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1); 2118 snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value); 2119 } 2120 2121 /* 2122 * Check and optionally lowercase a domain name, also removes trailing '.' 2123 * Returns 1 on success and 0 on failure, storing an error message in errstr. 2124 */ 2125 int 2126 valid_domain(char *name, int makelower, const char **errstr) 2127 { 2128 size_t i, l = strlen(name); 2129 u_char c, last = '\0'; 2130 static char errbuf[256]; 2131 2132 if (l == 0) { 2133 strlcpy(errbuf, "empty domain name", sizeof(errbuf)); 2134 goto bad; 2135 } 2136 if (!isalpha((u_char)name[0]) && !isdigit((u_char)name[0])) { 2137 snprintf(errbuf, sizeof(errbuf), "domain name \"%.100s\" " 2138 "starts with invalid character", name); 2139 goto bad; 2140 } 2141 for (i = 0; i < l; i++) { 2142 c = tolower((u_char)name[i]); 2143 if (makelower) 2144 name[i] = (char)c; 2145 if (last == '.' && c == '.') { 2146 snprintf(errbuf, sizeof(errbuf), "domain name " 2147 "\"%.100s\" contains consecutive separators", name); 2148 goto bad; 2149 } 2150 if (c != '.' && c != '-' && !isalnum(c) && 2151 c != '_') /* technically invalid, but common */ { 2152 snprintf(errbuf, sizeof(errbuf), "domain name " 2153 "\"%.100s\" contains invalid characters", name); 2154 goto bad; 2155 } 2156 last = c; 2157 } 2158 if (name[l - 1] == '.') 2159 name[l - 1] = '\0'; 2160 if (errstr != NULL) 2161 *errstr = NULL; 2162 return 1; 2163 bad: 2164 if (errstr != NULL) 2165 *errstr = errbuf; 2166 return 0; 2167 } 2168 2169 /* 2170 * Verify that a environment variable name (not including initial '$') is 2171 * valid; consisting of one or more alphanumeric or underscore characters only. 2172 * Returns 1 on valid, 0 otherwise. 2173 */ 2174 int 2175 valid_env_name(const char *name) 2176 { 2177 const char *cp; 2178 2179 if (name[0] == '\0') 2180 return 0; 2181 for (cp = name; *cp != '\0'; cp++) { 2182 if (!isalnum((u_char)*cp) && *cp != '_') 2183 return 0; 2184 } 2185 return 1; 2186 } 2187 2188 const char * 2189 atoi_err(const char *nptr, int *val) 2190 { 2191 const char *errstr = NULL; 2192 long long num; 2193 2194 if (nptr == NULL || *nptr == '\0') 2195 return "missing"; 2196 num = strtonum(nptr, 0, INT_MAX, &errstr); 2197 if (errstr == NULL) 2198 *val = (int)num; 2199 return errstr; 2200 } 2201 2202 int 2203 parse_absolute_time(const char *s, uint64_t *tp) 2204 { 2205 struct tm tm; 2206 time_t tt; 2207 char buf[32], *fmt; 2208 2209 *tp = 0; 2210 2211 /* 2212 * POSIX strptime says "The application shall ensure that there 2213 * is white-space or other non-alphanumeric characters between 2214 * any two conversion specifications" so arrange things this way. 2215 */ 2216 switch (strlen(s)) { 2217 case 8: /* YYYYMMDD */ 2218 fmt = "%Y-%m-%d"; 2219 snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2s", s, s + 4, s + 6); 2220 break; 2221 case 12: /* YYYYMMDDHHMM */ 2222 fmt = "%Y-%m-%dT%H:%M"; 2223 snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2sT%.2s:%.2s", 2224 s, s + 4, s + 6, s + 8, s + 10); 2225 break; 2226 case 14: /* YYYYMMDDHHMMSS */ 2227 fmt = "%Y-%m-%dT%H:%M:%S"; 2228 snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2sT%.2s:%.2s:%.2s", 2229 s, s + 4, s + 6, s + 8, s + 10, s + 12); 2230 break; 2231 default: 2232 return SSH_ERR_INVALID_FORMAT; 2233 } 2234 2235 memset(&tm, 0, sizeof(tm)); 2236 if (strptime(buf, fmt, &tm) == NULL) 2237 return SSH_ERR_INVALID_FORMAT; 2238 if ((tt = mktime(&tm)) < 0) 2239 return SSH_ERR_INVALID_FORMAT; 2240 /* success */ 2241 *tp = (uint64_t)tt; 2242 return 0; 2243 } 2244 2245 void 2246 format_absolute_time(uint64_t t, char *buf, size_t len) 2247 { 2248 time_t tt = t > INT_MAX ? INT_MAX : t; /* XXX revisit in 2038 :P */ 2249 struct tm tm; 2250 2251 localtime_r(&tt, &tm); 2252 strftime(buf, len, "%Y-%m-%dT%H:%M:%S", &tm); 2253 } 2254 2255 /* check if path is absolute */ 2256 int 2257 path_absolute(const char *path) 2258 { 2259 return (*path == '/') ? 1 : 0; 2260 } 2261 2262 void 2263 skip_space(char **cpp) 2264 { 2265 char *cp; 2266 2267 for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++) 2268 ; 2269 *cpp = cp; 2270 } 2271 2272 /* authorized_key-style options parsing helpers */ 2273 2274 /* 2275 * Match flag 'opt' in *optsp, and if allow_negate is set then also match 2276 * 'no-opt'. Returns -1 if option not matched, 1 if option matches or 0 2277 * if negated option matches. 2278 * If the option or negated option matches, then *optsp is updated to 2279 * point to the first character after the option. 2280 */ 2281 int 2282 opt_flag(const char *opt, int allow_negate, const char **optsp) 2283 { 2284 size_t opt_len = strlen(opt); 2285 const char *opts = *optsp; 2286 int negate = 0; 2287 2288 if (allow_negate && strncasecmp(opts, "no-", 3) == 0) { 2289 opts += 3; 2290 negate = 1; 2291 } 2292 if (strncasecmp(opts, opt, opt_len) == 0) { 2293 *optsp = opts + opt_len; 2294 return negate ? 0 : 1; 2295 } 2296 return -1; 2297 } 2298 2299 char * 2300 opt_dequote(const char **sp, const char **errstrp) 2301 { 2302 const char *s = *sp; 2303 char *ret; 2304 size_t i; 2305 2306 *errstrp = NULL; 2307 if (*s != '"') { 2308 *errstrp = "missing start quote"; 2309 return NULL; 2310 } 2311 s++; 2312 if ((ret = malloc(strlen((s)) + 1)) == NULL) { 2313 *errstrp = "memory allocation failed"; 2314 return NULL; 2315 } 2316 for (i = 0; *s != '\0' && *s != '"';) { 2317 if (s[0] == '\\' && s[1] == '"') 2318 s++; 2319 ret[i++] = *s++; 2320 } 2321 if (*s == '\0') { 2322 *errstrp = "missing end quote"; 2323 free(ret); 2324 return NULL; 2325 } 2326 ret[i] = '\0'; 2327 s++; 2328 *sp = s; 2329 return ret; 2330 } 2331 2332 int 2333 opt_match(const char **opts, const char *term) 2334 { 2335 if (strncasecmp((*opts), term, strlen(term)) == 0 && 2336 (*opts)[strlen(term)] == '=') { 2337 *opts += strlen(term) + 1; 2338 return 1; 2339 } 2340 return 0; 2341 } 2342 2343 sshsig_t 2344 ssh_signal(int signum, sshsig_t handler) 2345 { 2346 struct sigaction sa, osa; 2347 2348 /* mask all other signals while in handler */ 2349 memset(&sa, 0, sizeof(sa)); 2350 sa.sa_handler = handler; 2351 sigfillset(&sa.sa_mask); 2352 if (signum != SIGALRM) 2353 sa.sa_flags = SA_RESTART; 2354 if (sigaction(signum, &sa, &osa) == -1) { 2355 debug3("sigaction(%s): %s", strsignal(signum), strerror(errno)); 2356 return SIG_ERR; 2357 } 2358 return osa.sa_handler; 2359 } 2360 2361 int 2362 stdfd_devnull(int do_stdin, int do_stdout, int do_stderr) 2363 { 2364 int devnull, ret = 0; 2365 2366 if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) { 2367 error_f("open %s: %s", _PATH_DEVNULL, 2368 strerror(errno)); 2369 return -1; 2370 } 2371 if ((do_stdin && dup2(devnull, STDIN_FILENO) == -1) || 2372 (do_stdout && dup2(devnull, STDOUT_FILENO) == -1) || 2373 (do_stderr && dup2(devnull, STDERR_FILENO) == -1)) { 2374 error_f("dup2: %s", strerror(errno)); 2375 ret = -1; 2376 } 2377 if (devnull > STDERR_FILENO) 2378 close(devnull); 2379 return ret; 2380 } 2381 2382 /* 2383 * Runs command in a subprocess with a minimal environment. 2384 * Returns pid on success, 0 on failure. 2385 * The child stdout and stderr maybe captured, left attached or sent to 2386 * /dev/null depending on the contents of flags. 2387 * "tag" is prepended to log messages. 2388 * NB. "command" is only used for logging; the actual command executed is 2389 * av[0]. 2390 */ 2391 pid_t 2392 subprocess(const char *tag, const char *command, 2393 int ac, char **av, FILE **child, u_int flags, 2394 struct passwd *pw, privdrop_fn *drop_privs, privrestore_fn *restore_privs) 2395 { 2396 FILE *f = NULL; 2397 struct stat st; 2398 int fd, devnull, p[2], i; 2399 pid_t pid; 2400 char *cp, errmsg[512]; 2401 u_int nenv = 0; 2402 char **env = NULL; 2403 2404 /* If dropping privs, then must specify user and restore function */ 2405 if (drop_privs != NULL && (pw == NULL || restore_privs == NULL)) { 2406 error("%s: inconsistent arguments", tag); /* XXX fatal? */ 2407 return 0; 2408 } 2409 if (pw == NULL && (pw = getpwuid(getuid())) == NULL) { 2410 error("%s: no user for current uid", tag); 2411 return 0; 2412 } 2413 if (child != NULL) 2414 *child = NULL; 2415 2416 debug3_f("%s command \"%s\" running as %s (flags 0x%x)", 2417 tag, command, pw->pw_name, flags); 2418 2419 /* Check consistency */ 2420 if ((flags & SSH_SUBPROCESS_STDOUT_DISCARD) != 0 && 2421 (flags & SSH_SUBPROCESS_STDOUT_CAPTURE) != 0) { 2422 error_f("inconsistent flags"); 2423 return 0; 2424 } 2425 if (((flags & SSH_SUBPROCESS_STDOUT_CAPTURE) == 0) != (child == NULL)) { 2426 error_f("inconsistent flags/output"); 2427 return 0; 2428 } 2429 2430 /* 2431 * If executing an explicit binary, then verify the it exists 2432 * and appears safe-ish to execute 2433 */ 2434 if (!path_absolute(av[0])) { 2435 error("%s path is not absolute", tag); 2436 return 0; 2437 } 2438 if (drop_privs != NULL) 2439 drop_privs(pw); 2440 if (stat(av[0], &st) == -1) { 2441 error("Could not stat %s \"%s\": %s", tag, 2442 av[0], strerror(errno)); 2443 goto restore_return; 2444 } 2445 if ((flags & SSH_SUBPROCESS_UNSAFE_PATH) == 0 && 2446 safe_path(av[0], &st, NULL, 0, errmsg, sizeof(errmsg)) != 0) { 2447 error("Unsafe %s \"%s\": %s", tag, av[0], errmsg); 2448 goto restore_return; 2449 } 2450 /* Prepare to keep the child's stdout if requested */ 2451 if (pipe(p) == -1) { 2452 error("%s: pipe: %s", tag, strerror(errno)); 2453 restore_return: 2454 if (restore_privs != NULL) 2455 restore_privs(); 2456 return 0; 2457 } 2458 if (restore_privs != NULL) 2459 restore_privs(); 2460 2461 switch ((pid = fork())) { 2462 case -1: /* error */ 2463 error("%s: fork: %s", tag, strerror(errno)); 2464 close(p[0]); 2465 close(p[1]); 2466 return 0; 2467 case 0: /* child */ 2468 /* Prepare a minimal environment for the child. */ 2469 if ((flags & SSH_SUBPROCESS_PRESERVE_ENV) == 0) { 2470 nenv = 5; 2471 env = xcalloc(sizeof(*env), nenv); 2472 child_set_env(&env, &nenv, "PATH", _PATH_STDPATH); 2473 child_set_env(&env, &nenv, "USER", pw->pw_name); 2474 child_set_env(&env, &nenv, "LOGNAME", pw->pw_name); 2475 child_set_env(&env, &nenv, "HOME", pw->pw_dir); 2476 if ((cp = getenv("LANG")) != NULL) 2477 child_set_env(&env, &nenv, "LANG", cp); 2478 } 2479 2480 for (i = 0; i < NSIG; i++) 2481 ssh_signal(i, SIG_DFL); 2482 2483 if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) { 2484 error("%s: open %s: %s", tag, _PATH_DEVNULL, 2485 strerror(errno)); 2486 _exit(1); 2487 } 2488 if (dup2(devnull, STDIN_FILENO) == -1) { 2489 error("%s: dup2: %s", tag, strerror(errno)); 2490 _exit(1); 2491 } 2492 2493 /* Set up stdout as requested; leave stderr in place for now. */ 2494 fd = -1; 2495 if ((flags & SSH_SUBPROCESS_STDOUT_CAPTURE) != 0) 2496 fd = p[1]; 2497 else if ((flags & SSH_SUBPROCESS_STDOUT_DISCARD) != 0) 2498 fd = devnull; 2499 if (fd != -1 && dup2(fd, STDOUT_FILENO) == -1) { 2500 error("%s: dup2: %s", tag, strerror(errno)); 2501 _exit(1); 2502 } 2503 closefrom(STDERR_FILENO + 1); 2504 2505 if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1) { 2506 error("%s: setresgid %u: %s", tag, (u_int)pw->pw_gid, 2507 strerror(errno)); 2508 _exit(1); 2509 } 2510 if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1) { 2511 error("%s: setresuid %u: %s", tag, (u_int)pw->pw_uid, 2512 strerror(errno)); 2513 _exit(1); 2514 } 2515 /* stdin is pointed to /dev/null at this point */ 2516 if ((flags & SSH_SUBPROCESS_STDOUT_DISCARD) != 0 && 2517 dup2(STDIN_FILENO, STDERR_FILENO) == -1) { 2518 error("%s: dup2: %s", tag, strerror(errno)); 2519 _exit(1); 2520 } 2521 if (env != NULL) 2522 execve(av[0], av, env); 2523 else 2524 execv(av[0], av); 2525 error("%s %s \"%s\": %s", tag, env == NULL ? "execv" : "execve", 2526 command, strerror(errno)); 2527 _exit(127); 2528 default: /* parent */ 2529 break; 2530 } 2531 2532 close(p[1]); 2533 if ((flags & SSH_SUBPROCESS_STDOUT_CAPTURE) == 0) 2534 close(p[0]); 2535 else if ((f = fdopen(p[0], "r")) == NULL) { 2536 error("%s: fdopen: %s", tag, strerror(errno)); 2537 close(p[0]); 2538 /* Don't leave zombie child */ 2539 kill(pid, SIGTERM); 2540 while (waitpid(pid, NULL, 0) == -1 && errno == EINTR) 2541 ; 2542 return 0; 2543 } 2544 /* Success */ 2545 debug3_f("%s pid %ld", tag, (long)pid); 2546 if (child != NULL) 2547 *child = f; 2548 return pid; 2549 } 2550