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