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