1 /* $OpenBSD: misc.c,v 1.154 2020/10/03 09:22:26 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("%s: sshbuf_new failed", __func__); 1080 if (parseerror == NULL) 1081 fatal("%s: null parseerror arg", __func__); 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("%s: NULL replacement for token %s", __func__, keys[num_keys].key); 1093 } 1094 if (num_keys == EXPAND_MAX_KEYS && va_arg(ap, char *) != NULL) 1095 fatal("%s: too many keys", __func__); 1096 if (num_keys == 0) 1097 fatal("%s: percent expansion without token list", 1098 __func__); 1099 } 1100 1101 /* Expand string */ 1102 for (i = 0; *string != '\0'; string++) { 1103 /* Optionally process ${ENVIRONMENT} expansions. */ 1104 if (dollar && string[0] == '$' && string[1] == '{') { 1105 string += 2; /* skip over '${' */ 1106 if ((varend = strchr(string, '}')) == NULL) { 1107 error("%s: environment variable '%s' missing " 1108 "closing '}'", __func__, string); 1109 goto out; 1110 } 1111 len = varend - string; 1112 if (len == 0) { 1113 error("%s: zero-length environment variable", 1114 __func__); 1115 goto out; 1116 } 1117 var = xmalloc(len + 1); 1118 (void)strlcpy(var, string, len + 1); 1119 if ((val = getenv(var)) == NULL) { 1120 error("%s: env var ${%s} has no value", 1121 __func__, var); 1122 missingvar = 1; 1123 } else { 1124 debug3("%s: expand ${%s} -> '%s'", __func__, 1125 var, val); 1126 if ((r = sshbuf_put(buf, val, strlen(val))) !=0) 1127 fatal("%s: sshbuf_put: %s", __func__, 1128 ssh_err(r)); 1129 } 1130 free(var); 1131 string += len; 1132 continue; 1133 } 1134 1135 /* 1136 * Process percent expansions if we have a list of TOKENs. 1137 * If we're not doing percent expansion everything just gets 1138 * appended here. 1139 */ 1140 if (*string != '%' || !percent) { 1141 append: 1142 if ((r = sshbuf_put_u8(buf, *string)) != 0) { 1143 fatal("%s: sshbuf_put_u8: %s", 1144 __func__, ssh_err(r)); 1145 } 1146 continue; 1147 } 1148 string++; 1149 /* %% case */ 1150 if (*string == '%') 1151 goto append; 1152 if (*string == '\0') { 1153 error("%s: invalid format", __func__); 1154 goto out; 1155 } 1156 for (i = 0; i < num_keys; i++) { 1157 if (strchr(keys[i].key, *string) != NULL) { 1158 if ((r = sshbuf_put(buf, keys[i].repl, 1159 strlen(keys[i].repl))) != 0) { 1160 fatal("%s: sshbuf_put: %s", 1161 __func__, ssh_err(r)); 1162 } 1163 break; 1164 } 1165 } 1166 if (i >= num_keys) { 1167 error("%s: unknown key %%%c", __func__, *string); 1168 goto out; 1169 } 1170 } 1171 if (!missingvar && (ret = sshbuf_dup_string(buf)) == NULL) 1172 fatal("%s: sshbuf_dup_string failed", __func__); 1173 *parseerror = 0; 1174 out: 1175 sshbuf_free(buf); 1176 return *parseerror ? NULL : ret; 1177 #undef EXPAND_MAX_KEYS 1178 } 1179 1180 /* 1181 * Expand only environment variables. 1182 * Note that although this function is variadic like the other similar 1183 * functions, any such arguments will be unused. 1184 */ 1185 1186 char * 1187 dollar_expand(int *parseerr, const char *string, ...) 1188 { 1189 char *ret; 1190 int err; 1191 va_list ap; 1192 1193 va_start(ap, string); 1194 ret = vdollar_percent_expand(&err, 1, 0, string, ap); 1195 va_end(ap); 1196 if (parseerr != NULL) 1197 *parseerr = err; 1198 return ret; 1199 } 1200 1201 /* 1202 * Returns expanded string or NULL if a specified environment variable is 1203 * not defined, or calls fatal if the string is invalid. 1204 */ 1205 char * 1206 percent_expand(const char *string, ...) 1207 { 1208 char *ret; 1209 int err; 1210 va_list ap; 1211 1212 va_start(ap, string); 1213 ret = vdollar_percent_expand(&err, 0, 1, string, ap); 1214 va_end(ap); 1215 if (err) 1216 fatal("%s failed", __func__); 1217 return ret; 1218 } 1219 1220 /* 1221 * Returns expanded string or NULL if a specified environment variable is 1222 * not defined, or calls fatal if the string is invalid. 1223 */ 1224 char * 1225 percent_dollar_expand(const char *string, ...) 1226 { 1227 char *ret; 1228 int err; 1229 va_list ap; 1230 1231 va_start(ap, string); 1232 ret = vdollar_percent_expand(&err, 1, 1, string, ap); 1233 va_end(ap); 1234 if (err) 1235 fatal("%s failed", __func__); 1236 return ret; 1237 } 1238 1239 int 1240 tun_open(int tun, int mode, char **ifname) 1241 { 1242 struct ifreq ifr; 1243 char name[100]; 1244 int fd = -1, sock; 1245 const char *tunbase = "tun"; 1246 1247 if (ifname != NULL) 1248 *ifname = NULL; 1249 1250 if (mode == SSH_TUNMODE_ETHERNET) 1251 tunbase = "tap"; 1252 1253 /* Open the tunnel device */ 1254 if (tun <= SSH_TUNID_MAX) { 1255 snprintf(name, sizeof(name), "/dev/%s%d", tunbase, tun); 1256 fd = open(name, O_RDWR); 1257 } else if (tun == SSH_TUNID_ANY) { 1258 for (tun = 100; tun >= 0; tun--) { 1259 snprintf(name, sizeof(name), "/dev/%s%d", 1260 tunbase, tun); 1261 if ((fd = open(name, O_RDWR)) >= 0) 1262 break; 1263 } 1264 } else { 1265 debug("%s: invalid tunnel %u", __func__, tun); 1266 return -1; 1267 } 1268 1269 if (fd == -1) { 1270 debug("%s: %s open: %s", __func__, name, strerror(errno)); 1271 return -1; 1272 } 1273 1274 debug("%s: %s mode %d fd %d", __func__, name, mode, fd); 1275 1276 /* Bring interface up if it is not already */ 1277 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", tunbase, tun); 1278 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) 1279 goto failed; 1280 1281 if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) { 1282 debug("%s: get interface %s flags: %s", __func__, 1283 ifr.ifr_name, strerror(errno)); 1284 goto failed; 1285 } 1286 1287 if (!(ifr.ifr_flags & IFF_UP)) { 1288 ifr.ifr_flags |= IFF_UP; 1289 if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) { 1290 debug("%s: activate interface %s: %s", __func__, 1291 ifr.ifr_name, strerror(errno)); 1292 goto failed; 1293 } 1294 } 1295 1296 if (ifname != NULL) 1297 *ifname = xstrdup(ifr.ifr_name); 1298 1299 close(sock); 1300 return fd; 1301 1302 failed: 1303 if (fd >= 0) 1304 close(fd); 1305 if (sock >= 0) 1306 close(sock); 1307 return -1; 1308 } 1309 1310 void 1311 sanitise_stdfd(void) 1312 { 1313 int nullfd, dupfd; 1314 1315 if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 1316 fprintf(stderr, "Couldn't open /dev/null: %s\n", 1317 strerror(errno)); 1318 exit(1); 1319 } 1320 while (++dupfd <= STDERR_FILENO) { 1321 /* Only populate closed fds. */ 1322 if (fcntl(dupfd, F_GETFL) == -1 && errno == EBADF) { 1323 if (dup2(nullfd, dupfd) == -1) { 1324 fprintf(stderr, "dup2: %s\n", strerror(errno)); 1325 exit(1); 1326 } 1327 } 1328 } 1329 if (nullfd > STDERR_FILENO) 1330 close(nullfd); 1331 } 1332 1333 char * 1334 tohex(const void *vp, size_t l) 1335 { 1336 const u_char *p = (const u_char *)vp; 1337 char b[3], *r; 1338 size_t i, hl; 1339 1340 if (l > 65536) 1341 return xstrdup("tohex: length > 65536"); 1342 1343 hl = l * 2 + 1; 1344 r = xcalloc(1, hl); 1345 for (i = 0; i < l; i++) { 1346 snprintf(b, sizeof(b), "%02x", p[i]); 1347 strlcat(r, b, hl); 1348 } 1349 return (r); 1350 } 1351 1352 /* 1353 * Extend string *sp by the specified format. If *sp is not NULL (or empty), 1354 * then the separator 'sep' will be prepended before the formatted arguments. 1355 * Extended strings are heap allocated. 1356 */ 1357 void 1358 xextendf(char **sp, const char *sep, const char *fmt, ...) 1359 { 1360 va_list ap; 1361 char *tmp1, *tmp2; 1362 1363 va_start(ap, fmt); 1364 xvasprintf(&tmp1, fmt, ap); 1365 va_end(ap); 1366 1367 if (*sp == NULL || **sp == '\0') { 1368 free(*sp); 1369 *sp = tmp1; 1370 return; 1371 } 1372 xasprintf(&tmp2, "%s%s%s", *sp, sep == NULL ? "" : sep, tmp1); 1373 free(tmp1); 1374 free(*sp); 1375 *sp = tmp2; 1376 } 1377 1378 1379 u_int64_t 1380 get_u64(const void *vp) 1381 { 1382 const u_char *p = (const u_char *)vp; 1383 u_int64_t v; 1384 1385 v = (u_int64_t)p[0] << 56; 1386 v |= (u_int64_t)p[1] << 48; 1387 v |= (u_int64_t)p[2] << 40; 1388 v |= (u_int64_t)p[3] << 32; 1389 v |= (u_int64_t)p[4] << 24; 1390 v |= (u_int64_t)p[5] << 16; 1391 v |= (u_int64_t)p[6] << 8; 1392 v |= (u_int64_t)p[7]; 1393 1394 return (v); 1395 } 1396 1397 u_int32_t 1398 get_u32(const void *vp) 1399 { 1400 const u_char *p = (const u_char *)vp; 1401 u_int32_t v; 1402 1403 v = (u_int32_t)p[0] << 24; 1404 v |= (u_int32_t)p[1] << 16; 1405 v |= (u_int32_t)p[2] << 8; 1406 v |= (u_int32_t)p[3]; 1407 1408 return (v); 1409 } 1410 1411 u_int32_t 1412 get_u32_le(const void *vp) 1413 { 1414 const u_char *p = (const u_char *)vp; 1415 u_int32_t v; 1416 1417 v = (u_int32_t)p[0]; 1418 v |= (u_int32_t)p[1] << 8; 1419 v |= (u_int32_t)p[2] << 16; 1420 v |= (u_int32_t)p[3] << 24; 1421 1422 return (v); 1423 } 1424 1425 u_int16_t 1426 get_u16(const void *vp) 1427 { 1428 const u_char *p = (const u_char *)vp; 1429 u_int16_t v; 1430 1431 v = (u_int16_t)p[0] << 8; 1432 v |= (u_int16_t)p[1]; 1433 1434 return (v); 1435 } 1436 1437 void 1438 put_u64(void *vp, u_int64_t v) 1439 { 1440 u_char *p = (u_char *)vp; 1441 1442 p[0] = (u_char)(v >> 56) & 0xff; 1443 p[1] = (u_char)(v >> 48) & 0xff; 1444 p[2] = (u_char)(v >> 40) & 0xff; 1445 p[3] = (u_char)(v >> 32) & 0xff; 1446 p[4] = (u_char)(v >> 24) & 0xff; 1447 p[5] = (u_char)(v >> 16) & 0xff; 1448 p[6] = (u_char)(v >> 8) & 0xff; 1449 p[7] = (u_char)v & 0xff; 1450 } 1451 1452 void 1453 put_u32(void *vp, u_int32_t v) 1454 { 1455 u_char *p = (u_char *)vp; 1456 1457 p[0] = (u_char)(v >> 24) & 0xff; 1458 p[1] = (u_char)(v >> 16) & 0xff; 1459 p[2] = (u_char)(v >> 8) & 0xff; 1460 p[3] = (u_char)v & 0xff; 1461 } 1462 1463 void 1464 put_u32_le(void *vp, u_int32_t v) 1465 { 1466 u_char *p = (u_char *)vp; 1467 1468 p[0] = (u_char)v & 0xff; 1469 p[1] = (u_char)(v >> 8) & 0xff; 1470 p[2] = (u_char)(v >> 16) & 0xff; 1471 p[3] = (u_char)(v >> 24) & 0xff; 1472 } 1473 1474 void 1475 put_u16(void *vp, u_int16_t v) 1476 { 1477 u_char *p = (u_char *)vp; 1478 1479 p[0] = (u_char)(v >> 8) & 0xff; 1480 p[1] = (u_char)v & 0xff; 1481 } 1482 1483 void 1484 ms_subtract_diff(struct timeval *start, int *ms) 1485 { 1486 struct timeval diff, finish; 1487 1488 monotime_tv(&finish); 1489 timersub(&finish, start, &diff); 1490 *ms -= (diff.tv_sec * 1000) + (diff.tv_usec / 1000); 1491 } 1492 1493 void 1494 ms_to_timeval(struct timeval *tv, int ms) 1495 { 1496 if (ms < 0) 1497 ms = 0; 1498 tv->tv_sec = ms / 1000; 1499 tv->tv_usec = (ms % 1000) * 1000; 1500 } 1501 1502 void 1503 monotime_ts(struct timespec *ts) 1504 { 1505 if (clock_gettime(CLOCK_MONOTONIC, ts) != 0) 1506 fatal("clock_gettime: %s", strerror(errno)); 1507 } 1508 1509 void 1510 monotime_tv(struct timeval *tv) 1511 { 1512 struct timespec ts; 1513 1514 monotime_ts(&ts); 1515 tv->tv_sec = ts.tv_sec; 1516 tv->tv_usec = ts.tv_nsec / 1000; 1517 } 1518 1519 time_t 1520 monotime(void) 1521 { 1522 struct timespec ts; 1523 1524 monotime_ts(&ts); 1525 return (ts.tv_sec); 1526 } 1527 1528 double 1529 monotime_double(void) 1530 { 1531 struct timespec ts; 1532 1533 monotime_ts(&ts); 1534 return (double)ts.tv_sec + (double)ts.tv_nsec / 1000000000.0; 1535 } 1536 1537 void 1538 bandwidth_limit_init(struct bwlimit *bw, u_int64_t kbps, size_t buflen) 1539 { 1540 bw->buflen = buflen; 1541 bw->rate = kbps; 1542 bw->thresh = buflen; 1543 bw->lamt = 0; 1544 timerclear(&bw->bwstart); 1545 timerclear(&bw->bwend); 1546 } 1547 1548 /* Callback from read/write loop to insert bandwidth-limiting delays */ 1549 void 1550 bandwidth_limit(struct bwlimit *bw, size_t read_len) 1551 { 1552 u_int64_t waitlen; 1553 struct timespec ts, rm; 1554 1555 bw->lamt += read_len; 1556 if (!timerisset(&bw->bwstart)) { 1557 monotime_tv(&bw->bwstart); 1558 return; 1559 } 1560 if (bw->lamt < bw->thresh) 1561 return; 1562 1563 monotime_tv(&bw->bwend); 1564 timersub(&bw->bwend, &bw->bwstart, &bw->bwend); 1565 if (!timerisset(&bw->bwend)) 1566 return; 1567 1568 bw->lamt *= 8; 1569 waitlen = (double)1000000L * bw->lamt / bw->rate; 1570 1571 bw->bwstart.tv_sec = waitlen / 1000000L; 1572 bw->bwstart.tv_usec = waitlen % 1000000L; 1573 1574 if (timercmp(&bw->bwstart, &bw->bwend, >)) { 1575 timersub(&bw->bwstart, &bw->bwend, &bw->bwend); 1576 1577 /* Adjust the wait time */ 1578 if (bw->bwend.tv_sec) { 1579 bw->thresh /= 2; 1580 if (bw->thresh < bw->buflen / 4) 1581 bw->thresh = bw->buflen / 4; 1582 } else if (bw->bwend.tv_usec < 10000) { 1583 bw->thresh *= 2; 1584 if (bw->thresh > bw->buflen * 8) 1585 bw->thresh = bw->buflen * 8; 1586 } 1587 1588 TIMEVAL_TO_TIMESPEC(&bw->bwend, &ts); 1589 while (nanosleep(&ts, &rm) == -1) { 1590 if (errno != EINTR) 1591 break; 1592 ts = rm; 1593 } 1594 } 1595 1596 bw->lamt = 0; 1597 monotime_tv(&bw->bwstart); 1598 } 1599 1600 /* Make a template filename for mk[sd]temp() */ 1601 void 1602 mktemp_proto(char *s, size_t len) 1603 { 1604 const char *tmpdir; 1605 int r; 1606 1607 if ((tmpdir = getenv("TMPDIR")) != NULL) { 1608 r = snprintf(s, len, "%s/ssh-XXXXXXXXXXXX", tmpdir); 1609 if (r > 0 && (size_t)r < len) 1610 return; 1611 } 1612 r = snprintf(s, len, "/tmp/ssh-XXXXXXXXXXXX"); 1613 if (r < 0 || (size_t)r >= len) 1614 fatal("%s: template string too short", __func__); 1615 } 1616 1617 static const struct { 1618 const char *name; 1619 int value; 1620 } ipqos[] = { 1621 { "none", INT_MAX }, /* can't use 0 here; that's CS0 */ 1622 { "af11", IPTOS_DSCP_AF11 }, 1623 { "af12", IPTOS_DSCP_AF12 }, 1624 { "af13", IPTOS_DSCP_AF13 }, 1625 { "af21", IPTOS_DSCP_AF21 }, 1626 { "af22", IPTOS_DSCP_AF22 }, 1627 { "af23", IPTOS_DSCP_AF23 }, 1628 { "af31", IPTOS_DSCP_AF31 }, 1629 { "af32", IPTOS_DSCP_AF32 }, 1630 { "af33", IPTOS_DSCP_AF33 }, 1631 { "af41", IPTOS_DSCP_AF41 }, 1632 { "af42", IPTOS_DSCP_AF42 }, 1633 { "af43", IPTOS_DSCP_AF43 }, 1634 { "cs0", IPTOS_DSCP_CS0 }, 1635 { "cs1", IPTOS_DSCP_CS1 }, 1636 { "cs2", IPTOS_DSCP_CS2 }, 1637 { "cs3", IPTOS_DSCP_CS3 }, 1638 { "cs4", IPTOS_DSCP_CS4 }, 1639 { "cs5", IPTOS_DSCP_CS5 }, 1640 { "cs6", IPTOS_DSCP_CS6 }, 1641 { "cs7", IPTOS_DSCP_CS7 }, 1642 { "ef", IPTOS_DSCP_EF }, 1643 { "le", IPTOS_DSCP_LE }, 1644 { "lowdelay", IPTOS_LOWDELAY }, 1645 { "throughput", IPTOS_THROUGHPUT }, 1646 { "reliability", IPTOS_RELIABILITY }, 1647 { NULL, -1 } 1648 }; 1649 1650 int 1651 parse_ipqos(const char *cp) 1652 { 1653 u_int i; 1654 char *ep; 1655 long val; 1656 1657 if (cp == NULL) 1658 return -1; 1659 for (i = 0; ipqos[i].name != NULL; i++) { 1660 if (strcasecmp(cp, ipqos[i].name) == 0) 1661 return ipqos[i].value; 1662 } 1663 /* Try parsing as an integer */ 1664 val = strtol(cp, &ep, 0); 1665 if (*cp == '\0' || *ep != '\0' || val < 0 || val > 255) 1666 return -1; 1667 return val; 1668 } 1669 1670 const char * 1671 iptos2str(int iptos) 1672 { 1673 int i; 1674 static char iptos_str[sizeof "0xff"]; 1675 1676 for (i = 0; ipqos[i].name != NULL; i++) { 1677 if (ipqos[i].value == iptos) 1678 return ipqos[i].name; 1679 } 1680 snprintf(iptos_str, sizeof iptos_str, "0x%02x", iptos); 1681 return iptos_str; 1682 } 1683 1684 void 1685 lowercase(char *s) 1686 { 1687 for (; *s; s++) 1688 *s = tolower((u_char)*s); 1689 } 1690 1691 int 1692 unix_listener(const char *path, int backlog, int unlink_first) 1693 { 1694 struct sockaddr_un sunaddr; 1695 int saved_errno, sock; 1696 1697 memset(&sunaddr, 0, sizeof(sunaddr)); 1698 sunaddr.sun_family = AF_UNIX; 1699 if (strlcpy(sunaddr.sun_path, path, 1700 sizeof(sunaddr.sun_path)) >= sizeof(sunaddr.sun_path)) { 1701 error("%s: path \"%s\" too long for Unix domain socket", 1702 __func__, path); 1703 errno = ENAMETOOLONG; 1704 return -1; 1705 } 1706 1707 sock = socket(PF_UNIX, SOCK_STREAM, 0); 1708 if (sock == -1) { 1709 saved_errno = errno; 1710 error("%s: socket: %.100s", __func__, strerror(errno)); 1711 errno = saved_errno; 1712 return -1; 1713 } 1714 if (unlink_first == 1) { 1715 if (unlink(path) != 0 && errno != ENOENT) 1716 error("unlink(%s): %.100s", path, strerror(errno)); 1717 } 1718 if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) { 1719 saved_errno = errno; 1720 error("%s: cannot bind to path %s: %s", 1721 __func__, path, strerror(errno)); 1722 close(sock); 1723 errno = saved_errno; 1724 return -1; 1725 } 1726 if (listen(sock, backlog) == -1) { 1727 saved_errno = errno; 1728 error("%s: cannot listen on path %s: %s", 1729 __func__, path, strerror(errno)); 1730 close(sock); 1731 unlink(path); 1732 errno = saved_errno; 1733 return -1; 1734 } 1735 return sock; 1736 } 1737 1738 /* 1739 * Compares two strings that maybe be NULL. Returns non-zero if strings 1740 * are both NULL or are identical, returns zero otherwise. 1741 */ 1742 static int 1743 strcmp_maybe_null(const char *a, const char *b) 1744 { 1745 if ((a == NULL && b != NULL) || (a != NULL && b == NULL)) 1746 return 0; 1747 if (a != NULL && strcmp(a, b) != 0) 1748 return 0; 1749 return 1; 1750 } 1751 1752 /* 1753 * Compare two forwards, returning non-zero if they are identical or 1754 * zero otherwise. 1755 */ 1756 int 1757 forward_equals(const struct Forward *a, const struct Forward *b) 1758 { 1759 if (strcmp_maybe_null(a->listen_host, b->listen_host) == 0) 1760 return 0; 1761 if (a->listen_port != b->listen_port) 1762 return 0; 1763 if (strcmp_maybe_null(a->listen_path, b->listen_path) == 0) 1764 return 0; 1765 if (strcmp_maybe_null(a->connect_host, b->connect_host) == 0) 1766 return 0; 1767 if (a->connect_port != b->connect_port) 1768 return 0; 1769 if (strcmp_maybe_null(a->connect_path, b->connect_path) == 0) 1770 return 0; 1771 /* allocated_port and handle are not checked */ 1772 return 1; 1773 } 1774 1775 /* returns 1 if process is already daemonized, 0 otherwise */ 1776 int 1777 daemonized(void) 1778 { 1779 int fd; 1780 1781 if ((fd = open(_PATH_TTY, O_RDONLY | O_NOCTTY)) >= 0) { 1782 close(fd); 1783 return 0; /* have controlling terminal */ 1784 } 1785 if (getppid() != 1) 1786 return 0; /* parent is not init */ 1787 if (getsid(0) != getpid()) 1788 return 0; /* not session leader */ 1789 debug3("already daemonized"); 1790 return 1; 1791 } 1792 1793 1794 /* 1795 * Splits 's' into an argument vector. Handles quoted string and basic 1796 * escape characters (\\, \", \'). Caller must free the argument vector 1797 * and its members. 1798 */ 1799 int 1800 argv_split(const char *s, int *argcp, char ***argvp) 1801 { 1802 int r = SSH_ERR_INTERNAL_ERROR; 1803 int argc = 0, quote, i, j; 1804 char *arg, **argv = xcalloc(1, sizeof(*argv)); 1805 1806 *argvp = NULL; 1807 *argcp = 0; 1808 1809 for (i = 0; s[i] != '\0'; i++) { 1810 /* Skip leading whitespace */ 1811 if (s[i] == ' ' || s[i] == '\t') 1812 continue; 1813 1814 /* Start of a token */ 1815 quote = 0; 1816 if (s[i] == '\\' && 1817 (s[i + 1] == '\'' || s[i + 1] == '\"' || s[i + 1] == '\\')) 1818 i++; 1819 else if (s[i] == '\'' || s[i] == '"') 1820 quote = s[i++]; 1821 1822 argv = xreallocarray(argv, (argc + 2), sizeof(*argv)); 1823 arg = argv[argc++] = xcalloc(1, strlen(s + i) + 1); 1824 argv[argc] = NULL; 1825 1826 /* Copy the token in, removing escapes */ 1827 for (j = 0; s[i] != '\0'; i++) { 1828 if (s[i] == '\\') { 1829 if (s[i + 1] == '\'' || 1830 s[i + 1] == '\"' || 1831 s[i + 1] == '\\') { 1832 i++; /* Skip '\' */ 1833 arg[j++] = s[i]; 1834 } else { 1835 /* Unrecognised escape */ 1836 arg[j++] = s[i]; 1837 } 1838 } else if (quote == 0 && (s[i] == ' ' || s[i] == '\t')) 1839 break; /* done */ 1840 else if (quote != 0 && s[i] == quote) 1841 break; /* done */ 1842 else 1843 arg[j++] = s[i]; 1844 } 1845 if (s[i] == '\0') { 1846 if (quote != 0) { 1847 /* Ran out of string looking for close quote */ 1848 r = SSH_ERR_INVALID_FORMAT; 1849 goto out; 1850 } 1851 break; 1852 } 1853 } 1854 /* Success */ 1855 *argcp = argc; 1856 *argvp = argv; 1857 argc = 0; 1858 argv = NULL; 1859 r = 0; 1860 out: 1861 if (argc != 0 && argv != NULL) { 1862 for (i = 0; i < argc; i++) 1863 free(argv[i]); 1864 free(argv); 1865 } 1866 return r; 1867 } 1868 1869 /* 1870 * Reassemble an argument vector into a string, quoting and escaping as 1871 * necessary. Caller must free returned string. 1872 */ 1873 char * 1874 argv_assemble(int argc, char **argv) 1875 { 1876 int i, j, ws, r; 1877 char c, *ret; 1878 struct sshbuf *buf, *arg; 1879 1880 if ((buf = sshbuf_new()) == NULL || (arg = sshbuf_new()) == NULL) 1881 fatal("%s: sshbuf_new failed", __func__); 1882 1883 for (i = 0; i < argc; i++) { 1884 ws = 0; 1885 sshbuf_reset(arg); 1886 for (j = 0; argv[i][j] != '\0'; j++) { 1887 r = 0; 1888 c = argv[i][j]; 1889 switch (c) { 1890 case ' ': 1891 case '\t': 1892 ws = 1; 1893 r = sshbuf_put_u8(arg, c); 1894 break; 1895 case '\\': 1896 case '\'': 1897 case '"': 1898 if ((r = sshbuf_put_u8(arg, '\\')) != 0) 1899 break; 1900 /* FALLTHROUGH */ 1901 default: 1902 r = sshbuf_put_u8(arg, c); 1903 break; 1904 } 1905 if (r != 0) 1906 fatal("%s: sshbuf_put_u8: %s", 1907 __func__, ssh_err(r)); 1908 } 1909 if ((i != 0 && (r = sshbuf_put_u8(buf, ' ')) != 0) || 1910 (ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0) || 1911 (r = sshbuf_putb(buf, arg)) != 0 || 1912 (ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0)) 1913 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1914 } 1915 if ((ret = malloc(sshbuf_len(buf) + 1)) == NULL) 1916 fatal("%s: malloc failed", __func__); 1917 memcpy(ret, sshbuf_ptr(buf), sshbuf_len(buf)); 1918 ret[sshbuf_len(buf)] = '\0'; 1919 sshbuf_free(buf); 1920 sshbuf_free(arg); 1921 return ret; 1922 } 1923 1924 /* Returns 0 if pid exited cleanly, non-zero otherwise */ 1925 int 1926 exited_cleanly(pid_t pid, const char *tag, const char *cmd, int quiet) 1927 { 1928 int status; 1929 1930 while (waitpid(pid, &status, 0) == -1) { 1931 if (errno != EINTR) { 1932 error("%s: waitpid: %s", tag, strerror(errno)); 1933 return -1; 1934 } 1935 } 1936 if (WIFSIGNALED(status)) { 1937 error("%s %s exited on signal %d", tag, cmd, WTERMSIG(status)); 1938 return -1; 1939 } else if (WEXITSTATUS(status) != 0) { 1940 do_log2(quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_INFO, 1941 "%s %s failed, status %d", tag, cmd, WEXITSTATUS(status)); 1942 return -1; 1943 } 1944 return 0; 1945 } 1946 1947 /* 1948 * Check a given path for security. This is defined as all components 1949 * of the path to the file must be owned by either the owner of 1950 * of the file or root and no directories must be group or world writable. 1951 * 1952 * XXX Should any specific check be done for sym links ? 1953 * 1954 * Takes a file name, its stat information (preferably from fstat() to 1955 * avoid races), the uid of the expected owner, their home directory and an 1956 * error buffer plus max size as arguments. 1957 * 1958 * Returns 0 on success and -1 on failure 1959 */ 1960 int 1961 safe_path(const char *name, struct stat *stp, const char *pw_dir, 1962 uid_t uid, char *err, size_t errlen) 1963 { 1964 char buf[PATH_MAX], homedir[PATH_MAX]; 1965 char *cp; 1966 int comparehome = 0; 1967 struct stat st; 1968 1969 if (realpath(name, buf) == NULL) { 1970 snprintf(err, errlen, "realpath %s failed: %s", name, 1971 strerror(errno)); 1972 return -1; 1973 } 1974 if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL) 1975 comparehome = 1; 1976 1977 if (!S_ISREG(stp->st_mode)) { 1978 snprintf(err, errlen, "%s is not a regular file", buf); 1979 return -1; 1980 } 1981 if ((stp->st_uid != 0 && stp->st_uid != uid) || 1982 (stp->st_mode & 022) != 0) { 1983 snprintf(err, errlen, "bad ownership or modes for file %s", 1984 buf); 1985 return -1; 1986 } 1987 1988 /* for each component of the canonical path, walking upwards */ 1989 for (;;) { 1990 if ((cp = dirname(buf)) == NULL) { 1991 snprintf(err, errlen, "dirname() failed"); 1992 return -1; 1993 } 1994 strlcpy(buf, cp, sizeof(buf)); 1995 1996 if (stat(buf, &st) == -1 || 1997 (st.st_uid != 0 && st.st_uid != uid) || 1998 (st.st_mode & 022) != 0) { 1999 snprintf(err, errlen, 2000 "bad ownership or modes for directory %s", buf); 2001 return -1; 2002 } 2003 2004 /* If are past the homedir then we can stop */ 2005 if (comparehome && strcmp(homedir, buf) == 0) 2006 break; 2007 2008 /* 2009 * dirname should always complete with a "/" path, 2010 * but we can be paranoid and check for "." too 2011 */ 2012 if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0)) 2013 break; 2014 } 2015 return 0; 2016 } 2017 2018 /* 2019 * Version of safe_path() that accepts an open file descriptor to 2020 * avoid races. 2021 * 2022 * Returns 0 on success and -1 on failure 2023 */ 2024 int 2025 safe_path_fd(int fd, const char *file, struct passwd *pw, 2026 char *err, size_t errlen) 2027 { 2028 struct stat st; 2029 2030 /* check the open file to avoid races */ 2031 if (fstat(fd, &st) == -1) { 2032 snprintf(err, errlen, "cannot stat file %s: %s", 2033 file, strerror(errno)); 2034 return -1; 2035 } 2036 return safe_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen); 2037 } 2038 2039 /* 2040 * Sets the value of the given variable in the environment. If the variable 2041 * already exists, its value is overridden. 2042 */ 2043 void 2044 child_set_env(char ***envp, u_int *envsizep, const char *name, 2045 const char *value) 2046 { 2047 char **env; 2048 u_int envsize; 2049 u_int i, namelen; 2050 2051 if (strchr(name, '=') != NULL) { 2052 error("Invalid environment variable \"%.100s\"", name); 2053 return; 2054 } 2055 2056 /* 2057 * Find the slot where the value should be stored. If the variable 2058 * already exists, we reuse the slot; otherwise we append a new slot 2059 * at the end of the array, expanding if necessary. 2060 */ 2061 env = *envp; 2062 namelen = strlen(name); 2063 for (i = 0; env[i]; i++) 2064 if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=') 2065 break; 2066 if (env[i]) { 2067 /* Reuse the slot. */ 2068 free(env[i]); 2069 } else { 2070 /* New variable. Expand if necessary. */ 2071 envsize = *envsizep; 2072 if (i >= envsize - 1) { 2073 if (envsize >= 1000) 2074 fatal("child_set_env: too many env vars"); 2075 envsize += 50; 2076 env = (*envp) = xreallocarray(env, envsize, sizeof(char *)); 2077 *envsizep = envsize; 2078 } 2079 /* Need to set the NULL pointer at end of array beyond the new slot. */ 2080 env[i + 1] = NULL; 2081 } 2082 2083 /* Allocate space and format the variable in the appropriate slot. */ 2084 /* XXX xasprintf */ 2085 env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1); 2086 snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value); 2087 } 2088 2089 /* 2090 * Check and optionally lowercase a domain name, also removes trailing '.' 2091 * Returns 1 on success and 0 on failure, storing an error message in errstr. 2092 */ 2093 int 2094 valid_domain(char *name, int makelower, const char **errstr) 2095 { 2096 size_t i, l = strlen(name); 2097 u_char c, last = '\0'; 2098 static char errbuf[256]; 2099 2100 if (l == 0) { 2101 strlcpy(errbuf, "empty domain name", sizeof(errbuf)); 2102 goto bad; 2103 } 2104 if (!isalpha((u_char)name[0]) && !isdigit((u_char)name[0])) { 2105 snprintf(errbuf, sizeof(errbuf), "domain name \"%.100s\" " 2106 "starts with invalid character", name); 2107 goto bad; 2108 } 2109 for (i = 0; i < l; i++) { 2110 c = tolower((u_char)name[i]); 2111 if (makelower) 2112 name[i] = (char)c; 2113 if (last == '.' && c == '.') { 2114 snprintf(errbuf, sizeof(errbuf), "domain name " 2115 "\"%.100s\" contains consecutive separators", name); 2116 goto bad; 2117 } 2118 if (c != '.' && c != '-' && !isalnum(c) && 2119 c != '_') /* technically invalid, but common */ { 2120 snprintf(errbuf, sizeof(errbuf), "domain name " 2121 "\"%.100s\" contains invalid characters", name); 2122 goto bad; 2123 } 2124 last = c; 2125 } 2126 if (name[l - 1] == '.') 2127 name[l - 1] = '\0'; 2128 if (errstr != NULL) 2129 *errstr = NULL; 2130 return 1; 2131 bad: 2132 if (errstr != NULL) 2133 *errstr = errbuf; 2134 return 0; 2135 } 2136 2137 /* 2138 * Verify that a environment variable name (not including initial '$') is 2139 * valid; consisting of one or more alphanumeric or underscore characters only. 2140 * Returns 1 on valid, 0 otherwise. 2141 */ 2142 int 2143 valid_env_name(const char *name) 2144 { 2145 const char *cp; 2146 2147 if (name[0] == '\0') 2148 return 0; 2149 for (cp = name; *cp != '\0'; cp++) { 2150 if (!isalnum((u_char)*cp) && *cp != '_') 2151 return 0; 2152 } 2153 return 1; 2154 } 2155 2156 const char * 2157 atoi_err(const char *nptr, int *val) 2158 { 2159 const char *errstr = NULL; 2160 long long num; 2161 2162 if (nptr == NULL || *nptr == '\0') 2163 return "missing"; 2164 num = strtonum(nptr, 0, INT_MAX, &errstr); 2165 if (errstr == NULL) 2166 *val = (int)num; 2167 return errstr; 2168 } 2169 2170 int 2171 parse_absolute_time(const char *s, uint64_t *tp) 2172 { 2173 struct tm tm; 2174 time_t tt; 2175 char buf[32], *fmt; 2176 2177 *tp = 0; 2178 2179 /* 2180 * POSIX strptime says "The application shall ensure that there 2181 * is white-space or other non-alphanumeric characters between 2182 * any two conversion specifications" so arrange things this way. 2183 */ 2184 switch (strlen(s)) { 2185 case 8: /* YYYYMMDD */ 2186 fmt = "%Y-%m-%d"; 2187 snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2s", s, s + 4, s + 6); 2188 break; 2189 case 12: /* YYYYMMDDHHMM */ 2190 fmt = "%Y-%m-%dT%H:%M"; 2191 snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2sT%.2s:%.2s", 2192 s, s + 4, s + 6, s + 8, s + 10); 2193 break; 2194 case 14: /* YYYYMMDDHHMMSS */ 2195 fmt = "%Y-%m-%dT%H:%M:%S"; 2196 snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2sT%.2s:%.2s:%.2s", 2197 s, s + 4, s + 6, s + 8, s + 10, s + 12); 2198 break; 2199 default: 2200 return SSH_ERR_INVALID_FORMAT; 2201 } 2202 2203 memset(&tm, 0, sizeof(tm)); 2204 if (strptime(buf, fmt, &tm) == NULL) 2205 return SSH_ERR_INVALID_FORMAT; 2206 if ((tt = mktime(&tm)) < 0) 2207 return SSH_ERR_INVALID_FORMAT; 2208 /* success */ 2209 *tp = (uint64_t)tt; 2210 return 0; 2211 } 2212 2213 void 2214 format_absolute_time(uint64_t t, char *buf, size_t len) 2215 { 2216 time_t tt = t > INT_MAX ? INT_MAX : t; /* XXX revisit in 2038 :P */ 2217 struct tm tm; 2218 2219 localtime_r(&tt, &tm); 2220 strftime(buf, len, "%Y-%m-%dT%H:%M:%S", &tm); 2221 } 2222 2223 /* check if path is absolute */ 2224 int 2225 path_absolute(const char *path) 2226 { 2227 return (*path == '/') ? 1 : 0; 2228 } 2229 2230 void 2231 skip_space(char **cpp) 2232 { 2233 char *cp; 2234 2235 for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++) 2236 ; 2237 *cpp = cp; 2238 } 2239 2240 /* authorized_key-style options parsing helpers */ 2241 2242 /* 2243 * Match flag 'opt' in *optsp, and if allow_negate is set then also match 2244 * 'no-opt'. Returns -1 if option not matched, 1 if option matches or 0 2245 * if negated option matches. 2246 * If the option or negated option matches, then *optsp is updated to 2247 * point to the first character after the option. 2248 */ 2249 int 2250 opt_flag(const char *opt, int allow_negate, const char **optsp) 2251 { 2252 size_t opt_len = strlen(opt); 2253 const char *opts = *optsp; 2254 int negate = 0; 2255 2256 if (allow_negate && strncasecmp(opts, "no-", 3) == 0) { 2257 opts += 3; 2258 negate = 1; 2259 } 2260 if (strncasecmp(opts, opt, opt_len) == 0) { 2261 *optsp = opts + opt_len; 2262 return negate ? 0 : 1; 2263 } 2264 return -1; 2265 } 2266 2267 char * 2268 opt_dequote(const char **sp, const char **errstrp) 2269 { 2270 const char *s = *sp; 2271 char *ret; 2272 size_t i; 2273 2274 *errstrp = NULL; 2275 if (*s != '"') { 2276 *errstrp = "missing start quote"; 2277 return NULL; 2278 } 2279 s++; 2280 if ((ret = malloc(strlen((s)) + 1)) == NULL) { 2281 *errstrp = "memory allocation failed"; 2282 return NULL; 2283 } 2284 for (i = 0; *s != '\0' && *s != '"';) { 2285 if (s[0] == '\\' && s[1] == '"') 2286 s++; 2287 ret[i++] = *s++; 2288 } 2289 if (*s == '\0') { 2290 *errstrp = "missing end quote"; 2291 free(ret); 2292 return NULL; 2293 } 2294 ret[i] = '\0'; 2295 s++; 2296 *sp = s; 2297 return ret; 2298 } 2299 2300 int 2301 opt_match(const char **opts, const char *term) 2302 { 2303 if (strncasecmp((*opts), term, strlen(term)) == 0 && 2304 (*opts)[strlen(term)] == '=') { 2305 *opts += strlen(term) + 1; 2306 return 1; 2307 } 2308 return 0; 2309 } 2310 2311 sshsig_t 2312 ssh_signal(int signum, sshsig_t handler) 2313 { 2314 struct sigaction sa, osa; 2315 2316 /* mask all other signals while in handler */ 2317 memset(&sa, 0, sizeof(sa)); 2318 sa.sa_handler = handler; 2319 sigfillset(&sa.sa_mask); 2320 if (signum != SIGALRM) 2321 sa.sa_flags = SA_RESTART; 2322 if (sigaction(signum, &sa, &osa) == -1) { 2323 debug3("sigaction(%s): %s", strsignal(signum), strerror(errno)); 2324 return SIG_ERR; 2325 } 2326 return osa.sa_handler; 2327 } 2328 2329 int 2330 stdfd_devnull(int do_stdin, int do_stdout, int do_stderr) 2331 { 2332 int devnull, ret = 0; 2333 2334 if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) { 2335 error("%s: open %s: %s", __func__, _PATH_DEVNULL, 2336 strerror(errno)); 2337 return -1; 2338 } 2339 if ((do_stdin && dup2(devnull, STDIN_FILENO) == -1) || 2340 (do_stdout && dup2(devnull, STDOUT_FILENO) == -1) || 2341 (do_stderr && dup2(devnull, STDERR_FILENO) == -1)) { 2342 error("%s: dup2: %s", __func__, strerror(errno)); 2343 ret = -1; 2344 } 2345 if (devnull > STDERR_FILENO) 2346 close(devnull); 2347 return ret; 2348 } 2349