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