1 /* $OpenBSD: ssh.c,v 1.612 2025/04/09 01:24:40 djm Exp $ */ 2 /* 3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 5 * All rights reserved 6 * Ssh client program. This program can be used to log into a remote machine. 7 * The software supports strong authentication, encryption, and forwarding 8 * of X11, TCP/IP, and authentication connections. 9 * 10 * As far as I am concerned, the code I have written for this software 11 * can be used freely for any purpose. Any derived versions of this 12 * software must be clearly marked as such, and if the derived work is 13 * incompatible with the protocol description in the RFC file, it must be 14 * called by a name other than "ssh" or "Secure Shell". 15 * 16 * Copyright (c) 1999 Niels Provos. All rights reserved. 17 * Copyright (c) 2000, 2001, 2002, 2003 Markus Friedl. All rights reserved. 18 * 19 * Modified to work with SSLeay by Niels Provos <provos@citi.umich.edu> 20 * in Canada (German citizen). 21 * 22 * Redistribution and use in source and binary forms, with or without 23 * modification, are permitted provided that the following conditions 24 * are met: 25 * 1. Redistributions of source code must retain the above copyright 26 * notice, this list of conditions and the following disclaimer. 27 * 2. Redistributions in binary form must reproduce the above copyright 28 * notice, this list of conditions and the following disclaimer in the 29 * documentation and/or other materials provided with the distribution. 30 * 31 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 32 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 33 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 34 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 35 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 37 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 38 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 40 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 41 */ 42 43 #include "includes.h" 44 45 #include <sys/types.h> 46 #ifdef HAVE_SYS_STAT_H 47 # include <sys/stat.h> 48 #endif 49 #include <sys/resource.h> 50 #include <sys/ioctl.h> 51 #include <sys/socket.h> 52 #include <sys/wait.h> 53 #include <sys/utsname.h> 54 55 #include <ctype.h> 56 #include <errno.h> 57 #include <fcntl.h> 58 #include <netdb.h> 59 #ifdef HAVE_PATHS_H 60 #include <paths.h> 61 #endif 62 #include <pwd.h> 63 #include <signal.h> 64 #include <stdarg.h> 65 #include <stddef.h> 66 #include <stdio.h> 67 #include <stdlib.h> 68 #include <string.h> 69 #include <stdarg.h> 70 #include <unistd.h> 71 #include <limits.h> 72 #include <locale.h> 73 74 #include <netinet/in.h> 75 #include <arpa/inet.h> 76 77 #ifdef WITH_OPENSSL 78 #include <openssl/evp.h> 79 #include <openssl/err.h> 80 #endif 81 #include "openbsd-compat/openssl-compat.h" 82 #include "openbsd-compat/sys-queue.h" 83 84 #include "xmalloc.h" 85 #include "ssh.h" 86 #include "ssh2.h" 87 #include "canohost.h" 88 #include "compat.h" 89 #include "cipher.h" 90 #include "packet.h" 91 #include "sshbuf.h" 92 #include "channels.h" 93 #include "sshkey.h" 94 #include "authfd.h" 95 #include "authfile.h" 96 #include "pathnames.h" 97 #include "dispatch.h" 98 #include "clientloop.h" 99 #include "log.h" 100 #include "misc.h" 101 #include "readconf.h" 102 #include "sshconnect.h" 103 #include "kex.h" 104 #include "mac.h" 105 #include "sshpty.h" 106 #include "match.h" 107 #include "msg.h" 108 #include "version.h" 109 #include "ssherr.h" 110 #include "myproposal.h" 111 #include "utf8.h" 112 113 #ifdef ENABLE_PKCS11 114 #include "ssh-pkcs11.h" 115 #endif 116 117 extern char *__progname; 118 119 /* Saves a copy of argv for setproctitle emulation */ 120 #ifndef HAVE_SETPROCTITLE 121 static char **saved_av; 122 #endif 123 124 /* Flag indicating whether debug mode is on. May be set on the command line. */ 125 int debug_flag = 0; 126 127 /* Flag indicating whether a tty should be requested */ 128 int tty_flag = 0; 129 130 /* 131 * Flag indicating that the current process should be backgrounded and 132 * a new mux-client launched in the foreground for ControlPersist. 133 */ 134 static int need_controlpersist_detach = 0; 135 136 /* Copies of flags for ControlPersist foreground mux-client */ 137 static int ostdin_null_flag, osession_type, otty_flag, orequest_tty; 138 static int ofork_after_authentication; 139 140 /* 141 * General data structure for command line options and options configurable 142 * in configuration files. See readconf.h. 143 */ 144 Options options; 145 146 /* optional user configfile */ 147 char *config = NULL; 148 149 /* 150 * Name of the host we are connecting to. This is the name given on the 151 * command line, or the Hostname specified for the user-supplied name in a 152 * configuration file. 153 */ 154 char *host; 155 156 /* 157 * A config can specify a path to forward, overriding SSH_AUTH_SOCK. If this is 158 * not NULL, forward the socket at this path instead. 159 */ 160 char *forward_agent_sock_path = NULL; 161 162 /* socket address the host resolves to */ 163 struct sockaddr_storage hostaddr; 164 165 /* Private host keys. */ 166 Sensitive sensitive_data; 167 168 /* command to be executed */ 169 struct sshbuf *command; 170 171 /* # of replies received for global requests */ 172 static int forward_confirms_pending = -1; 173 174 /* mux.c */ 175 extern int muxserver_sock; 176 extern u_int muxclient_command; 177 178 /* Prints a help message to the user. This function never returns. */ 179 180 static void 181 usage(void) 182 { 183 fprintf(stderr, 184 "usage: ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-B bind_interface] [-b bind_address]\n" 185 " [-c cipher_spec] [-D [bind_address:]port] [-E log_file]\n" 186 " [-e escape_char] [-F configfile] [-I pkcs11] [-i identity_file]\n" 187 " [-J destination] [-L address] [-l login_name] [-m mac_spec]\n" 188 " [-O ctl_cmd] [-o option] [-P tag] [-p port] [-R address]\n" 189 " [-S ctl_path] [-W host:port] [-w local_tun[:remote_tun]]\n" 190 " destination [command [argument ...]]\n" 191 " ssh [-Q query_option]\n" 192 ); 193 exit(255); 194 } 195 196 static int ssh_session2(struct ssh *, const struct ssh_conn_info *); 197 static void load_public_identity_files(const struct ssh_conn_info *); 198 static void main_sigchld_handler(int); 199 200 /* ~/ expand a list of paths. NB. assumes path[n] is heap-allocated. */ 201 static void 202 tilde_expand_paths(char **paths, u_int num_paths) 203 { 204 u_int i; 205 char *cp; 206 207 for (i = 0; i < num_paths; i++) { 208 cp = tilde_expand_filename(paths[i], getuid()); 209 free(paths[i]); 210 paths[i] = cp; 211 } 212 } 213 214 /* 215 * Expands the set of percent_expand options used by the majority of keywords 216 * in the client that support percent expansion. 217 * Caller must free returned string. 218 */ 219 static char * 220 default_client_percent_expand(const char *str, 221 const struct ssh_conn_info *cinfo) 222 { 223 return percent_expand(str, 224 DEFAULT_CLIENT_PERCENT_EXPAND_ARGS(cinfo), 225 (char *)NULL); 226 } 227 228 /* 229 * Expands the set of percent_expand options used by the majority of keywords 230 * AND perform environment variable substitution. 231 * Caller must free returned string. 232 */ 233 static char * 234 default_client_percent_dollar_expand(const char *str, 235 const struct ssh_conn_info *cinfo) 236 { 237 char *ret; 238 239 ret = percent_dollar_expand(str, 240 DEFAULT_CLIENT_PERCENT_EXPAND_ARGS(cinfo), 241 (char *)NULL); 242 if (ret == NULL) 243 fatal("invalid environment variable expansion"); 244 return ret; 245 } 246 247 /* 248 * Attempt to resolve a host name / port to a set of addresses and 249 * optionally return any CNAMEs encountered along the way. 250 * Returns NULL on failure. 251 * NB. this function must operate with a options having undefined members. 252 */ 253 static struct addrinfo * 254 resolve_host(const char *name, int port, int logerr, char *cname, size_t clen) 255 { 256 char strport[NI_MAXSERV]; 257 const char *errstr = NULL; 258 struct addrinfo hints, *res; 259 int gaierr; 260 LogLevel loglevel = SYSLOG_LEVEL_DEBUG1; 261 262 if (port <= 0) 263 port = default_ssh_port(); 264 if (cname != NULL) 265 *cname = '\0'; 266 debug3_f("lookup %s:%d", name, port); 267 268 snprintf(strport, sizeof strport, "%d", port); 269 memset(&hints, 0, sizeof(hints)); 270 hints.ai_family = options.address_family == -1 ? 271 AF_UNSPEC : options.address_family; 272 hints.ai_socktype = SOCK_STREAM; 273 if (cname != NULL) 274 hints.ai_flags = AI_CANONNAME; 275 if ((gaierr = getaddrinfo(name, strport, &hints, &res)) != 0) { 276 if (logerr || (gaierr != EAI_NONAME && gaierr != EAI_NODATA)) 277 loglevel = SYSLOG_LEVEL_ERROR; 278 do_log2(loglevel, "%s: Could not resolve hostname %.100s: %s", 279 __progname, name, ssh_gai_strerror(gaierr)); 280 return NULL; 281 } 282 if (cname != NULL && res->ai_canonname != NULL) { 283 if (!valid_domain(res->ai_canonname, 0, &errstr)) { 284 error("ignoring bad CNAME \"%s\" for host \"%s\": %s", 285 res->ai_canonname, name, errstr); 286 } else if (strlcpy(cname, res->ai_canonname, clen) >= clen) { 287 error_f("host \"%s\" cname \"%s\" too long (max %lu)", 288 name, res->ai_canonname, (u_long)clen); 289 if (clen > 0) 290 *cname = '\0'; 291 } 292 } 293 return res; 294 } 295 296 /* Returns non-zero if name can only be an address and not a hostname */ 297 static int 298 is_addr_fast(const char *name) 299 { 300 return (strchr(name, '%') != NULL || strchr(name, ':') != NULL || 301 strspn(name, "0123456789.") == strlen(name)); 302 } 303 304 /* Returns non-zero if name represents a valid, single address */ 305 static int 306 is_addr(const char *name) 307 { 308 char strport[NI_MAXSERV]; 309 struct addrinfo hints, *res; 310 311 if (is_addr_fast(name)) 312 return 1; 313 314 snprintf(strport, sizeof strport, "%u", default_ssh_port()); 315 memset(&hints, 0, sizeof(hints)); 316 hints.ai_family = options.address_family == -1 ? 317 AF_UNSPEC : options.address_family; 318 hints.ai_socktype = SOCK_STREAM; 319 hints.ai_flags = AI_NUMERICHOST|AI_NUMERICSERV; 320 if (getaddrinfo(name, strport, &hints, &res) != 0) 321 return 0; 322 if (res == NULL || res->ai_next != NULL) { 323 freeaddrinfo(res); 324 return 0; 325 } 326 freeaddrinfo(res); 327 return 1; 328 } 329 330 /* 331 * Attempt to resolve a numeric host address / port to a single address. 332 * Returns a canonical address string. 333 * Returns NULL on failure. 334 * NB. this function must operate with a options having undefined members. 335 */ 336 static struct addrinfo * 337 resolve_addr(const char *name, int port, char *caddr, size_t clen) 338 { 339 char addr[NI_MAXHOST], strport[NI_MAXSERV]; 340 struct addrinfo hints, *res; 341 int gaierr; 342 343 if (port <= 0) 344 port = default_ssh_port(); 345 snprintf(strport, sizeof strport, "%u", port); 346 memset(&hints, 0, sizeof(hints)); 347 hints.ai_family = options.address_family == -1 ? 348 AF_UNSPEC : options.address_family; 349 hints.ai_socktype = SOCK_STREAM; 350 hints.ai_flags = AI_NUMERICHOST|AI_NUMERICSERV; 351 if ((gaierr = getaddrinfo(name, strport, &hints, &res)) != 0) { 352 debug2_f("could not resolve name %.100s as address: %s", 353 name, ssh_gai_strerror(gaierr)); 354 return NULL; 355 } 356 if (res == NULL) { 357 debug_f("getaddrinfo %.100s returned no addresses", name); 358 return NULL; 359 } 360 if (res->ai_next != NULL) { 361 debug_f("getaddrinfo %.100s returned multiple addresses", name); 362 goto fail; 363 } 364 if ((gaierr = getnameinfo(res->ai_addr, res->ai_addrlen, 365 addr, sizeof(addr), NULL, 0, NI_NUMERICHOST)) != 0) { 366 debug_f("Could not format address for name %.100s: %s", 367 name, ssh_gai_strerror(gaierr)); 368 goto fail; 369 } 370 if (strlcpy(caddr, addr, clen) >= clen) { 371 error_f("host \"%s\" addr \"%s\" too long (max %lu)", 372 name, addr, (u_long)clen); 373 if (clen > 0) 374 *caddr = '\0'; 375 fail: 376 freeaddrinfo(res); 377 return NULL; 378 } 379 return res; 380 } 381 382 /* 383 * Check whether the cname is a permitted replacement for the hostname 384 * and perform the replacement if it is. 385 * NB. this function must operate with a options having undefined members. 386 */ 387 static int 388 check_follow_cname(int direct, char **namep, const char *cname) 389 { 390 int i; 391 struct allowed_cname *rule; 392 393 if (*cname == '\0' || !config_has_permitted_cnames(&options) || 394 strcmp(*namep, cname) == 0) 395 return 0; 396 if (options.canonicalize_hostname == SSH_CANONICALISE_NO) 397 return 0; 398 /* 399 * Don't attempt to canonicalize names that will be interpreted by 400 * a proxy or jump host unless the user specifically requests so. 401 */ 402 if (!direct && 403 options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS) 404 return 0; 405 debug3_f("check \"%s\" CNAME \"%s\"", *namep, cname); 406 for (i = 0; i < options.num_permitted_cnames; i++) { 407 rule = options.permitted_cnames + i; 408 if (match_pattern_list(*namep, rule->source_list, 1) != 1 || 409 match_pattern_list(cname, rule->target_list, 1) != 1) 410 continue; 411 verbose("Canonicalized DNS aliased hostname " 412 "\"%s\" => \"%s\"", *namep, cname); 413 free(*namep); 414 *namep = xstrdup(cname); 415 return 1; 416 } 417 return 0; 418 } 419 420 /* 421 * Attempt to resolve the supplied hostname after applying the user's 422 * canonicalization rules. Returns the address list for the host or NULL 423 * if no name was found after canonicalization. 424 * NB. this function must operate with a options having undefined members. 425 */ 426 static struct addrinfo * 427 resolve_canonicalize(char **hostp, int port) 428 { 429 int i, direct, ndots; 430 char *cp, *fullhost, newname[NI_MAXHOST]; 431 struct addrinfo *addrs; 432 433 /* 434 * Attempt to canonicalise addresses, regardless of 435 * whether hostname canonicalisation was requested 436 */ 437 if ((addrs = resolve_addr(*hostp, port, 438 newname, sizeof(newname))) != NULL) { 439 debug2_f("hostname %.100s is address", *hostp); 440 if (strcasecmp(*hostp, newname) != 0) { 441 debug2_f("canonicalised address \"%s\" => \"%s\"", 442 *hostp, newname); 443 free(*hostp); 444 *hostp = xstrdup(newname); 445 } 446 return addrs; 447 } 448 449 /* 450 * If this looks like an address but didn't parse as one, it might 451 * be an address with an invalid interface scope. Skip further 452 * attempts at canonicalisation. 453 */ 454 if (is_addr_fast(*hostp)) { 455 debug_f("hostname %.100s is an unrecognised address", *hostp); 456 return NULL; 457 } 458 459 if (options.canonicalize_hostname == SSH_CANONICALISE_NO) 460 return NULL; 461 462 /* 463 * Don't attempt to canonicalize names that will be interpreted by 464 * a proxy unless the user specifically requests so. 465 */ 466 direct = option_clear_or_none(options.proxy_command) && 467 option_clear_or_none(options.jump_host); 468 if (!direct && 469 options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS) 470 return NULL; 471 472 /* If domain name is anchored, then resolve it now */ 473 if ((*hostp)[strlen(*hostp) - 1] == '.') { 474 debug3_f("name is fully qualified"); 475 fullhost = xstrdup(*hostp); 476 if ((addrs = resolve_host(fullhost, port, 0, 477 newname, sizeof(newname))) != NULL) 478 goto found; 479 free(fullhost); 480 goto notfound; 481 } 482 483 /* Don't apply canonicalization to sufficiently-qualified hostnames */ 484 ndots = 0; 485 for (cp = *hostp; *cp != '\0'; cp++) { 486 if (*cp == '.') 487 ndots++; 488 } 489 if (ndots > options.canonicalize_max_dots) { 490 debug3_f("not canonicalizing hostname \"%s\" (max dots %d)", 491 *hostp, options.canonicalize_max_dots); 492 return NULL; 493 } 494 /* Attempt each supplied suffix */ 495 for (i = 0; i < options.num_canonical_domains; i++) { 496 if (strcasecmp(options.canonical_domains[i], "none") == 0) 497 break; 498 xasprintf(&fullhost, "%s.%s.", *hostp, 499 options.canonical_domains[i]); 500 debug3_f("attempting \"%s\" => \"%s\"", *hostp, fullhost); 501 if ((addrs = resolve_host(fullhost, port, 0, 502 newname, sizeof(newname))) == NULL) { 503 free(fullhost); 504 continue; 505 } 506 found: 507 /* Remove trailing '.' */ 508 fullhost[strlen(fullhost) - 1] = '\0'; 509 /* Follow CNAME if requested */ 510 if (!check_follow_cname(direct, &fullhost, newname)) { 511 debug("Canonicalized hostname \"%s\" => \"%s\"", 512 *hostp, fullhost); 513 } 514 free(*hostp); 515 *hostp = fullhost; 516 return addrs; 517 } 518 notfound: 519 if (!options.canonicalize_fallback_local) 520 fatal("%s: Could not resolve host \"%s\"", __progname, *hostp); 521 debug2_f("host %s not found in any suffix", *hostp); 522 return NULL; 523 } 524 525 /* 526 * Check the result of hostkey loading, ignoring some errors and either 527 * discarding the key or fatal()ing for others. 528 */ 529 static void 530 check_load(int r, struct sshkey **k, const char *path, const char *message) 531 { 532 switch (r) { 533 case 0: 534 /* Check RSA keys size and discard if undersized */ 535 if (k != NULL && *k != NULL && 536 (r = sshkey_check_rsa_length(*k, 537 options.required_rsa_size)) != 0) { 538 error_r(r, "load %s \"%s\"", message, path); 539 free(*k); 540 *k = NULL; 541 } 542 break; 543 case SSH_ERR_INTERNAL_ERROR: 544 case SSH_ERR_ALLOC_FAIL: 545 fatal_r(r, "load %s \"%s\"", message, path); 546 case SSH_ERR_SYSTEM_ERROR: 547 /* Ignore missing files */ 548 if (errno == ENOENT) 549 break; 550 /* FALLTHROUGH */ 551 default: 552 error_r(r, "load %s \"%s\"", message, path); 553 break; 554 } 555 } 556 557 /* 558 * Read per-user configuration file. Ignore the system wide config 559 * file if the user specifies a config file on the command line. 560 */ 561 static void 562 process_config_files(const char *host_name, struct passwd *pw, 563 int final_pass, int *want_final_pass) 564 { 565 char *cmd, buf[PATH_MAX]; 566 int r; 567 568 if ((cmd = sshbuf_dup_string(command)) == NULL) 569 fatal_f("sshbuf_dup_string failed"); 570 if (config != NULL) { 571 if (strcasecmp(config, "none") != 0 && 572 !read_config_file(config, pw, host, host_name, cmd, 573 &options, 574 SSHCONF_USERCONF | (final_pass ? SSHCONF_FINAL : 0), 575 want_final_pass)) 576 fatal("Can't open user config file %.100s: " 577 "%.100s", config, strerror(errno)); 578 } else { 579 r = snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, 580 _PATH_SSH_USER_CONFFILE); 581 if (r > 0 && (size_t)r < sizeof(buf)) 582 (void)read_config_file(buf, pw, host, host_name, cmd, 583 &options, SSHCONF_CHECKPERM | SSHCONF_USERCONF | 584 (final_pass ? SSHCONF_FINAL : 0), want_final_pass); 585 586 /* Read systemwide configuration file after user config. */ 587 (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, 588 host, host_name, cmd, &options, 589 final_pass ? SSHCONF_FINAL : 0, want_final_pass); 590 } 591 free(cmd); 592 } 593 594 /* Rewrite the port number in an addrinfo list of addresses */ 595 static void 596 set_addrinfo_port(struct addrinfo *addrs, int port) 597 { 598 struct addrinfo *addr; 599 600 for (addr = addrs; addr != NULL; addr = addr->ai_next) { 601 switch (addr->ai_family) { 602 case AF_INET: 603 ((struct sockaddr_in *)addr->ai_addr)-> 604 sin_port = htons(port); 605 break; 606 case AF_INET6: 607 ((struct sockaddr_in6 *)addr->ai_addr)-> 608 sin6_port = htons(port); 609 break; 610 } 611 } 612 } 613 614 static void 615 ssh_conn_info_free(struct ssh_conn_info *cinfo) 616 { 617 if (cinfo == NULL) 618 return; 619 free(cinfo->conn_hash_hex); 620 free(cinfo->shorthost); 621 free(cinfo->uidstr); 622 free(cinfo->keyalias); 623 free(cinfo->thishost); 624 free(cinfo->host_arg); 625 free(cinfo->portstr); 626 free(cinfo->remhost); 627 free(cinfo->remuser); 628 free(cinfo->homedir); 629 free(cinfo->locuser); 630 free(cinfo->jmphost); 631 free(cinfo); 632 } 633 634 static int 635 valid_hostname(const char *s) 636 { 637 size_t i; 638 639 if (*s == '-') 640 return 0; 641 for (i = 0; s[i] != 0; i++) { 642 if (strchr("'`\"$\\;&<>|(){},", s[i]) != NULL || 643 isspace((u_char)s[i]) || iscntrl((u_char)s[i])) 644 return 0; 645 } 646 return 1; 647 } 648 649 static int 650 valid_ruser(const char *s) 651 { 652 size_t i; 653 654 if (*s == '-') 655 return 0; 656 for (i = 0; s[i] != 0; i++) { 657 if (strchr("'`\";&<>|(){}", s[i]) != NULL) 658 return 0; 659 /* Disallow '-' after whitespace */ 660 if (isspace((u_char)s[i]) && s[i + 1] == '-') 661 return 0; 662 /* Disallow \ in last position */ 663 if (s[i] == '\\' && s[i + 1] == '\0') 664 return 0; 665 } 666 return 1; 667 } 668 669 /* 670 * Main program for the ssh client. 671 */ 672 int 673 main(int ac, char **av) 674 { 675 struct ssh *ssh = NULL; 676 int i, r, opt, exit_status, use_syslog, direct, timeout_ms; 677 int was_addr, config_test = 0, opt_terminated = 0, want_final_pass = 0; 678 char *p, *cp, *line, *argv0, *logfile, *args; 679 char cname[NI_MAXHOST], thishost[NI_MAXHOST]; 680 struct stat st; 681 struct passwd *pw; 682 extern int optind, optreset; 683 extern char *optarg; 684 struct Forward fwd; 685 struct addrinfo *addrs = NULL; 686 size_t n, len; 687 u_int j; 688 struct utsname utsname; 689 struct ssh_conn_info *cinfo = NULL; 690 691 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ 692 sanitise_stdfd(); 693 694 /* 695 * Discard other fds that are hanging around. These can cause problem 696 * with backgrounded ssh processes started by ControlPersist. 697 */ 698 closefrom(STDERR_FILENO + 1); 699 700 __progname = ssh_get_progname(av[0]); 701 702 #ifndef HAVE_SETPROCTITLE 703 /* Prepare for later setproctitle emulation */ 704 /* Save argv so it isn't clobbered by setproctitle() emulation */ 705 saved_av = xcalloc(ac + 1, sizeof(*saved_av)); 706 for (i = 0; i < ac; i++) 707 saved_av[i] = xstrdup(av[i]); 708 saved_av[i] = NULL; 709 compat_init_setproctitle(ac, av); 710 av = saved_av; 711 #endif 712 713 seed_rng(); 714 715 /* Get user data. */ 716 pw = getpwuid(getuid()); 717 if (!pw) { 718 logit("No user exists for uid %lu", (u_long)getuid()); 719 exit(255); 720 } 721 /* Take a copy of the returned structure. */ 722 pw = pwcopy(pw); 723 724 /* 725 * Set our umask to something reasonable, as some files are created 726 * with the default umask. This will make them world-readable but 727 * writable only by the owner, which is ok for all files for which we 728 * don't set the modes explicitly. 729 */ 730 umask(022 | umask(077)); 731 732 msetlocale(); 733 734 /* 735 * Initialize option structure to indicate that no values have been 736 * set. 737 */ 738 initialize_options(&options); 739 740 /* 741 * Prepare main ssh transport/connection structures 742 */ 743 if ((ssh = ssh_alloc_session_state()) == NULL) 744 fatal("Couldn't allocate session state"); 745 channel_init_channels(ssh); 746 747 748 /* Parse command-line arguments. */ 749 args = argv_assemble(ac, av); /* logged later */ 750 host = NULL; 751 use_syslog = 0; 752 logfile = NULL; 753 argv0 = av[0]; 754 755 again: 756 while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx" 757 "AB:CD:E:F:GI:J:KL:MNO:P:Q:R:S:TVw:W:XYy")) != -1) { /* HUZdhjruz */ 758 switch (opt) { 759 case '1': 760 fatal("SSH protocol v.1 is no longer supported"); 761 break; 762 case '2': 763 /* Ignored */ 764 break; 765 case '4': 766 options.address_family = AF_INET; 767 break; 768 case '6': 769 options.address_family = AF_INET6; 770 break; 771 case 'n': 772 options.stdin_null = 1; 773 break; 774 case 'f': 775 options.fork_after_authentication = 1; 776 options.stdin_null = 1; 777 break; 778 case 'x': 779 options.forward_x11 = 0; 780 break; 781 case 'X': 782 options.forward_x11 = 1; 783 break; 784 case 'y': 785 use_syslog = 1; 786 break; 787 case 'E': 788 logfile = optarg; 789 break; 790 case 'G': 791 config_test = 1; 792 break; 793 case 'Y': 794 options.forward_x11 = 1; 795 options.forward_x11_trusted = 1; 796 break; 797 case 'g': 798 options.fwd_opts.gateway_ports = 1; 799 break; 800 case 'O': 801 if (options.stdio_forward_host != NULL) 802 fatal("Cannot specify multiplexing " 803 "command with -W"); 804 else if (muxclient_command != 0) 805 fatal("Multiplexing command already specified"); 806 if (strcmp(optarg, "check") == 0) 807 muxclient_command = SSHMUX_COMMAND_ALIVE_CHECK; 808 else if (strcmp(optarg, "forward") == 0) 809 muxclient_command = SSHMUX_COMMAND_FORWARD; 810 else if (strcmp(optarg, "exit") == 0) 811 muxclient_command = SSHMUX_COMMAND_TERMINATE; 812 else if (strcmp(optarg, "stop") == 0) 813 muxclient_command = SSHMUX_COMMAND_STOP; 814 else if (strcmp(optarg, "cancel") == 0) 815 muxclient_command = SSHMUX_COMMAND_CANCEL_FWD; 816 else if (strcmp(optarg, "proxy") == 0) 817 muxclient_command = SSHMUX_COMMAND_PROXY; 818 else 819 fatal("Invalid multiplex command."); 820 break; 821 case 'P': 822 if (options.tag == NULL) 823 options.tag = xstrdup(optarg); 824 break; 825 case 'Q': 826 cp = NULL; 827 if (strcmp(optarg, "cipher") == 0 || 828 strcasecmp(optarg, "Ciphers") == 0) 829 cp = cipher_alg_list('\n', 0); 830 else if (strcmp(optarg, "cipher-auth") == 0) 831 cp = cipher_alg_list('\n', 1); 832 else if (strcmp(optarg, "mac") == 0 || 833 strcasecmp(optarg, "MACs") == 0) 834 cp = mac_alg_list('\n'); 835 else if (strcmp(optarg, "kex") == 0 || 836 strcasecmp(optarg, "KexAlgorithms") == 0) 837 cp = kex_alg_list('\n'); 838 else if (strcmp(optarg, "key") == 0) 839 cp = sshkey_alg_list(0, 0, 0, '\n'); 840 else if (strcmp(optarg, "key-cert") == 0) 841 cp = sshkey_alg_list(1, 0, 0, '\n'); 842 else if (strcmp(optarg, "key-plain") == 0) 843 cp = sshkey_alg_list(0, 1, 0, '\n'); 844 else if (strcmp(optarg, "key-ca-sign") == 0 || 845 strcasecmp(optarg, "CASignatureAlgorithms") == 0) 846 cp = sshkey_alg_list(0, 1, 1, '\n'); 847 else if (strcmp(optarg, "key-sig") == 0 || 848 strcasecmp(optarg, "PubkeyAcceptedKeyTypes") == 0 || /* deprecated name */ 849 strcasecmp(optarg, "PubkeyAcceptedAlgorithms") == 0 || 850 strcasecmp(optarg, "HostKeyAlgorithms") == 0 || 851 strcasecmp(optarg, "HostbasedKeyTypes") == 0 || /* deprecated name */ 852 strcasecmp(optarg, "HostbasedAcceptedKeyTypes") == 0 || /* deprecated name */ 853 strcasecmp(optarg, "HostbasedAcceptedAlgorithms") == 0) 854 cp = sshkey_alg_list(0, 0, 1, '\n'); 855 else if (strcmp(optarg, "sig") == 0) 856 cp = sshkey_alg_list(0, 1, 1, '\n'); 857 else if (strcmp(optarg, "protocol-version") == 0) 858 cp = xstrdup("2"); 859 else if (strcmp(optarg, "compression") == 0) { 860 cp = xstrdup(compression_alg_list(0)); 861 len = strlen(cp); 862 for (n = 0; n < len; n++) 863 if (cp[n] == ',') 864 cp[n] = '\n'; 865 } else if (strcmp(optarg, "help") == 0) { 866 cp = xstrdup( 867 "cipher\ncipher-auth\ncompression\nkex\n" 868 "key\nkey-cert\nkey-plain\nkey-sig\nmac\n" 869 "protocol-version\nsig"); 870 } 871 if (cp == NULL) 872 fatal("Unsupported query \"%s\"", optarg); 873 printf("%s\n", cp); 874 free(cp); 875 exit(0); 876 break; 877 case 'a': 878 options.forward_agent = 0; 879 break; 880 case 'A': 881 options.forward_agent = 1; 882 break; 883 case 'k': 884 options.gss_deleg_creds = 0; 885 break; 886 case 'K': 887 options.gss_authentication = 1; 888 options.gss_deleg_creds = 1; 889 break; 890 case 'i': 891 p = tilde_expand_filename(optarg, getuid()); 892 if (stat(p, &st) == -1) 893 fprintf(stderr, "Warning: Identity file %s " 894 "not accessible: %s.\n", p, 895 strerror(errno)); 896 else 897 add_identity_file(&options, NULL, p, 1); 898 free(p); 899 break; 900 case 'I': 901 #ifdef ENABLE_PKCS11 902 free(options.pkcs11_provider); 903 options.pkcs11_provider = xstrdup(optarg); 904 #else 905 fprintf(stderr, "no support for PKCS#11.\n"); 906 #endif 907 break; 908 case 'J': 909 if (options.jump_host != NULL) { 910 fatal("Only a single -J option is permitted " 911 "(use commas to separate multiple " 912 "jump hops)"); 913 } 914 if (options.proxy_command != NULL) 915 fatal("Cannot specify -J with ProxyCommand"); 916 if (parse_jump(optarg, &options, 1) == -1) 917 fatal("Invalid -J argument"); 918 options.proxy_command = xstrdup("none"); 919 break; 920 case 't': 921 if (options.request_tty == REQUEST_TTY_YES) 922 options.request_tty = REQUEST_TTY_FORCE; 923 else 924 options.request_tty = REQUEST_TTY_YES; 925 break; 926 case 'v': 927 if (debug_flag == 0) { 928 debug_flag = 1; 929 options.log_level = SYSLOG_LEVEL_DEBUG1; 930 } else { 931 if (options.log_level < SYSLOG_LEVEL_DEBUG3) { 932 debug_flag++; 933 options.log_level++; 934 } 935 } 936 break; 937 case 'V': 938 fprintf(stderr, "%s, %s\n", 939 SSH_RELEASE, SSH_OPENSSL_VERSION); 940 exit(0); 941 break; 942 case 'w': 943 if (options.tun_open == -1) 944 options.tun_open = SSH_TUNMODE_DEFAULT; 945 options.tun_local = a2tun(optarg, &options.tun_remote); 946 if (options.tun_local == SSH_TUNID_ERR) { 947 fprintf(stderr, 948 "Bad tun device '%s'\n", optarg); 949 exit(255); 950 } 951 break; 952 case 'W': 953 if (options.stdio_forward_host != NULL) 954 fatal("stdio forward already specified"); 955 if (muxclient_command != 0) 956 fatal("Cannot specify stdio forward with -O"); 957 if (parse_forward(&fwd, optarg, 1, 0)) { 958 options.stdio_forward_host = 959 fwd.listen_port == PORT_STREAMLOCAL ? 960 fwd.listen_path : fwd.listen_host; 961 options.stdio_forward_port = fwd.listen_port; 962 free(fwd.connect_host); 963 } else { 964 fprintf(stderr, 965 "Bad stdio forwarding specification '%s'\n", 966 optarg); 967 exit(255); 968 } 969 options.request_tty = REQUEST_TTY_NO; 970 options.session_type = SESSION_TYPE_NONE; 971 break; 972 case 'q': 973 options.log_level = SYSLOG_LEVEL_QUIET; 974 break; 975 case 'e': 976 if (strlen(optarg) == 2 && optarg[0] == '^' && 977 (u_char) optarg[1] >= 64 && 978 (u_char) optarg[1] < 128) 979 options.escape_char = (u_char) optarg[1] & 31; 980 else if (strlen(optarg) == 1) 981 options.escape_char = (u_char) optarg[0]; 982 else if (strcmp(optarg, "none") == 0) 983 options.escape_char = SSH_ESCAPECHAR_NONE; 984 else { 985 fprintf(stderr, "Bad escape character '%s'.\n", 986 optarg); 987 exit(255); 988 } 989 break; 990 case 'c': 991 if (!ciphers_valid(*optarg == '+' || *optarg == '^' ? 992 optarg + 1 : optarg)) { 993 fprintf(stderr, "Unknown cipher type '%s'\n", 994 optarg); 995 exit(255); 996 } 997 free(options.ciphers); 998 options.ciphers = xstrdup(optarg); 999 break; 1000 case 'm': 1001 if (mac_valid(optarg)) { 1002 free(options.macs); 1003 options.macs = xstrdup(optarg); 1004 } else { 1005 fprintf(stderr, "Unknown mac type '%s'\n", 1006 optarg); 1007 exit(255); 1008 } 1009 break; 1010 case 'M': 1011 if (options.control_master == SSHCTL_MASTER_YES) 1012 options.control_master = SSHCTL_MASTER_ASK; 1013 else 1014 options.control_master = SSHCTL_MASTER_YES; 1015 break; 1016 case 'p': 1017 if (options.port == -1) { 1018 options.port = a2port(optarg); 1019 if (options.port <= 0) { 1020 fprintf(stderr, "Bad port '%s'\n", 1021 optarg); 1022 exit(255); 1023 } 1024 } 1025 break; 1026 case 'l': 1027 if (options.user == NULL) 1028 options.user = xstrdup(optarg); 1029 break; 1030 1031 case 'L': 1032 if (parse_forward(&fwd, optarg, 0, 0)) 1033 add_local_forward(&options, &fwd); 1034 else { 1035 fprintf(stderr, 1036 "Bad local forwarding specification '%s'\n", 1037 optarg); 1038 exit(255); 1039 } 1040 break; 1041 1042 case 'R': 1043 if (parse_forward(&fwd, optarg, 0, 1) || 1044 parse_forward(&fwd, optarg, 1, 1)) { 1045 add_remote_forward(&options, &fwd); 1046 } else { 1047 fprintf(stderr, 1048 "Bad remote forwarding specification " 1049 "'%s'\n", optarg); 1050 exit(255); 1051 } 1052 break; 1053 1054 case 'D': 1055 if (parse_forward(&fwd, optarg, 1, 0)) { 1056 add_local_forward(&options, &fwd); 1057 } else { 1058 fprintf(stderr, 1059 "Bad dynamic forwarding specification " 1060 "'%s'\n", optarg); 1061 exit(255); 1062 } 1063 break; 1064 1065 case 'C': 1066 #ifdef WITH_ZLIB 1067 options.compression = 1; 1068 #else 1069 error("Compression not supported, disabling."); 1070 #endif 1071 break; 1072 case 'N': 1073 if (options.session_type != -1 && 1074 options.session_type != SESSION_TYPE_NONE) 1075 fatal("Cannot specify -N with -s/SessionType"); 1076 options.session_type = SESSION_TYPE_NONE; 1077 options.request_tty = REQUEST_TTY_NO; 1078 break; 1079 case 'T': 1080 options.request_tty = REQUEST_TTY_NO; 1081 break; 1082 case 'o': 1083 line = xstrdup(optarg); 1084 if (process_config_line(&options, pw, 1085 host ? host : "", host ? host : "", "", line, 1086 "command-line", 0, NULL, SSHCONF_USERCONF) != 0) 1087 exit(255); 1088 free(line); 1089 break; 1090 case 's': 1091 if (options.session_type != -1 && 1092 options.session_type != SESSION_TYPE_SUBSYSTEM) 1093 fatal("Cannot specify -s with -N/SessionType"); 1094 options.session_type = SESSION_TYPE_SUBSYSTEM; 1095 break; 1096 case 'S': 1097 free(options.control_path); 1098 options.control_path = xstrdup(optarg); 1099 break; 1100 case 'b': 1101 options.bind_address = optarg; 1102 break; 1103 case 'B': 1104 options.bind_interface = optarg; 1105 break; 1106 case 'F': 1107 config = optarg; 1108 break; 1109 default: 1110 usage(); 1111 } 1112 } 1113 1114 if (optind > 1 && strcmp(av[optind - 1], "--") == 0) 1115 opt_terminated = 1; 1116 1117 ac -= optind; 1118 av += optind; 1119 1120 if (ac > 0 && !host) { 1121 int tport; 1122 char *tuser; 1123 switch (parse_ssh_uri(*av, &tuser, &host, &tport)) { 1124 case -1: 1125 usage(); 1126 break; 1127 case 0: 1128 if (options.user == NULL) { 1129 options.user = tuser; 1130 tuser = NULL; 1131 } 1132 free(tuser); 1133 if (options.port == -1 && tport != -1) 1134 options.port = tport; 1135 break; 1136 default: 1137 p = xstrdup(*av); 1138 cp = strrchr(p, '@'); 1139 if (cp != NULL) { 1140 if (cp == p) 1141 usage(); 1142 if (options.user == NULL) { 1143 options.user = p; 1144 p = NULL; 1145 } 1146 *cp++ = '\0'; 1147 host = xstrdup(cp); 1148 free(p); 1149 } else 1150 host = p; 1151 break; 1152 } 1153 if (ac > 1 && !opt_terminated) { 1154 optind = optreset = 1; 1155 goto again; 1156 } 1157 ac--, av++; 1158 } 1159 1160 /* Check that we got a host name. */ 1161 if (!host) 1162 usage(); 1163 1164 if (!valid_hostname(host)) 1165 fatal("hostname contains invalid characters"); 1166 options.host_arg = xstrdup(host); 1167 1168 /* Initialize the command to execute on remote host. */ 1169 if ((command = sshbuf_new()) == NULL) 1170 fatal("sshbuf_new failed"); 1171 1172 /* 1173 * Save the command to execute on the remote host in a buffer. There 1174 * is no limit on the length of the command, except by the maximum 1175 * packet size. Also sets the tty flag if there is no command. 1176 */ 1177 if (!ac) { 1178 /* No command specified - execute shell on a tty. */ 1179 if (options.session_type == SESSION_TYPE_SUBSYSTEM) { 1180 fprintf(stderr, 1181 "You must specify a subsystem to invoke.\n"); 1182 usage(); 1183 } 1184 } else { 1185 /* A command has been specified. Store it into the buffer. */ 1186 for (i = 0; i < ac; i++) { 1187 if ((r = sshbuf_putf(command, "%s%s", 1188 i ? " " : "", av[i])) != 0) 1189 fatal_fr(r, "buffer error"); 1190 } 1191 } 1192 1193 ssh_signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */ 1194 1195 /* 1196 * Initialize "log" output. Since we are the client all output 1197 * goes to stderr unless otherwise specified by -y or -E. 1198 */ 1199 if (use_syslog && logfile != NULL) 1200 fatal("Can't specify both -y and -E"); 1201 if (logfile != NULL) 1202 log_redirect_stderr_to(logfile); 1203 log_init(argv0, 1204 options.log_level == SYSLOG_LEVEL_NOT_SET ? 1205 SYSLOG_LEVEL_INFO : options.log_level, 1206 options.log_facility == SYSLOG_FACILITY_NOT_SET ? 1207 SYSLOG_FACILITY_USER : options.log_facility, 1208 !use_syslog); 1209 1210 debug("%s, %s", SSH_RELEASE, SSH_OPENSSL_VERSION); 1211 if (uname(&utsname) != 0) { 1212 memset(&utsname, 0, sizeof(utsname)); 1213 strlcpy(utsname.sysname, "UNKNOWN", sizeof(utsname.sysname)); 1214 } 1215 debug3("Running on %s %s %s %s", utsname.sysname, utsname.release, 1216 utsname.version, utsname.machine); 1217 debug3("Started with: %s", args); 1218 free(args); 1219 1220 /* Parse the configuration files */ 1221 process_config_files(options.host_arg, pw, 0, &want_final_pass); 1222 if (want_final_pass) 1223 debug("configuration requests final Match pass"); 1224 1225 /* Hostname canonicalisation needs a few options filled. */ 1226 fill_default_options_for_canonicalization(&options); 1227 1228 /* If the user has replaced the hostname then take it into use now */ 1229 if (options.hostname != NULL) { 1230 /* NB. Please keep in sync with readconf.c:match_cfg_line() */ 1231 cp = percent_expand(options.hostname, 1232 "h", host, (char *)NULL); 1233 free(host); 1234 host = cp; 1235 free(options.hostname); 1236 options.hostname = xstrdup(host); 1237 } 1238 1239 /* Don't lowercase addresses, they will be explicitly canonicalised */ 1240 if ((was_addr = is_addr(host)) == 0) 1241 lowercase(host); 1242 1243 /* 1244 * Try to canonicalize if requested by configuration or the 1245 * hostname is an address. 1246 */ 1247 if (options.canonicalize_hostname != SSH_CANONICALISE_NO || was_addr) 1248 addrs = resolve_canonicalize(&host, options.port); 1249 1250 /* 1251 * If CanonicalizePermittedCNAMEs have been specified but 1252 * other canonicalization did not happen (by not being requested 1253 * or by failing with fallback) then the hostname may still be changed 1254 * as a result of CNAME following. 1255 * 1256 * Try to resolve the bare hostname name using the system resolver's 1257 * usual search rules and then apply the CNAME follow rules. 1258 * 1259 * Skip the lookup if a ProxyCommand is being used unless the user 1260 * has specifically requested canonicalisation for this case via 1261 * CanonicalizeHostname=always 1262 */ 1263 direct = option_clear_or_none(options.proxy_command) && 1264 option_clear_or_none(options.jump_host); 1265 if (addrs == NULL && config_has_permitted_cnames(&options) && (direct || 1266 options.canonicalize_hostname == SSH_CANONICALISE_ALWAYS)) { 1267 if ((addrs = resolve_host(host, options.port, 1268 direct, cname, sizeof(cname))) == NULL) { 1269 /* Don't fatal proxied host names not in the DNS */ 1270 if (direct) 1271 cleanup_exit(255); /* logged in resolve_host */ 1272 } else 1273 check_follow_cname(direct, &host, cname); 1274 } 1275 1276 /* 1277 * If canonicalisation is enabled then re-parse the configuration 1278 * files as new stanzas may match. 1279 */ 1280 if (options.canonicalize_hostname != 0 && !want_final_pass) { 1281 debug("hostname canonicalisation enabled, " 1282 "will re-parse configuration"); 1283 want_final_pass = 1; 1284 } 1285 1286 if (want_final_pass) { 1287 debug("re-parsing configuration"); 1288 free(options.hostname); 1289 options.hostname = xstrdup(host); 1290 process_config_files(options.host_arg, pw, 1, NULL); 1291 /* 1292 * Address resolution happens early with canonicalisation 1293 * enabled and the port number may have changed since, so 1294 * reset it in address list 1295 */ 1296 if (addrs != NULL && options.port > 0) 1297 set_addrinfo_port(addrs, options.port); 1298 } 1299 1300 /* Fill configuration defaults. */ 1301 if (fill_default_options(&options) != 0) 1302 cleanup_exit(255); 1303 1304 if (options.user == NULL) 1305 options.user = xstrdup(pw->pw_name); 1306 1307 /* 1308 * If ProxyJump option specified, then construct a ProxyCommand now. 1309 */ 1310 if (options.jump_host != NULL) { 1311 char port_s[8]; 1312 const char *jumpuser = options.jump_user, *sshbin = argv0; 1313 int port = options.port, jumpport = options.jump_port; 1314 1315 if (port <= 0) 1316 port = default_ssh_port(); 1317 if (jumpport <= 0) 1318 jumpport = default_ssh_port(); 1319 if (jumpuser == NULL) 1320 jumpuser = options.user; 1321 if (strcmp(options.jump_host, host) == 0 && port == jumpport && 1322 strcmp(options.user, jumpuser) == 0) 1323 fatal("jumphost loop via %s", options.jump_host); 1324 1325 /* 1326 * Try to use SSH indicated by argv[0], but fall back to 1327 * "ssh" if it appears unavailable. 1328 */ 1329 if (strchr(argv0, '/') != NULL && access(argv0, X_OK) != 0) 1330 sshbin = "ssh"; 1331 1332 /* Consistency check */ 1333 if (options.proxy_command != NULL) 1334 fatal("inconsistent options: ProxyCommand+ProxyJump"); 1335 /* Never use FD passing for ProxyJump */ 1336 options.proxy_use_fdpass = 0; 1337 snprintf(port_s, sizeof(port_s), "%d", options.jump_port); 1338 xasprintf(&options.proxy_command, 1339 "%s%s%s%s%s%s%s%s%s%s%.*s -W '[%%h]:%%p' %s", 1340 sshbin, 1341 /* Optional "-l user" argument if jump_user set */ 1342 options.jump_user == NULL ? "" : " -l ", 1343 options.jump_user == NULL ? "" : options.jump_user, 1344 /* Optional "-p port" argument if jump_port set */ 1345 options.jump_port <= 0 ? "" : " -p ", 1346 options.jump_port <= 0 ? "" : port_s, 1347 /* Optional additional jump hosts ",..." */ 1348 options.jump_extra == NULL ? "" : " -J ", 1349 options.jump_extra == NULL ? "" : options.jump_extra, 1350 /* Optional "-F" argument if -F specified */ 1351 config == NULL ? "" : " -F ", 1352 config == NULL ? "" : config, 1353 /* Optional "-v" arguments if -v set */ 1354 debug_flag ? " -" : "", 1355 debug_flag, "vvv", 1356 /* Mandatory hostname */ 1357 options.jump_host); 1358 debug("Setting implicit ProxyCommand from ProxyJump: %s", 1359 options.proxy_command); 1360 } 1361 1362 if (options.port == 0) 1363 options.port = default_ssh_port(); 1364 channel_set_af(ssh, options.address_family); 1365 1366 /* Tidy and check options */ 1367 if (options.host_key_alias != NULL) 1368 lowercase(options.host_key_alias); 1369 if (options.proxy_command != NULL && 1370 strcmp(options.proxy_command, "-") == 0 && 1371 options.proxy_use_fdpass) 1372 fatal("ProxyCommand=- and ProxyUseFDPass are incompatible"); 1373 if (options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK) { 1374 if (options.control_persist && options.control_path != NULL) { 1375 debug("UpdateHostKeys=ask is incompatible with " 1376 "ControlPersist; disabling"); 1377 options.update_hostkeys = 0; 1378 } else if (sshbuf_len(command) != 0 || 1379 options.remote_command != NULL || 1380 options.request_tty == REQUEST_TTY_NO) { 1381 debug("UpdateHostKeys=ask is incompatible with " 1382 "remote command execution; disabling"); 1383 options.update_hostkeys = 0; 1384 } else if (options.log_level < SYSLOG_LEVEL_INFO) { 1385 /* no point logging anything; user won't see it */ 1386 options.update_hostkeys = 0; 1387 } 1388 } 1389 if (options.connection_attempts <= 0) 1390 fatal("Invalid number of ConnectionAttempts"); 1391 1392 if (sshbuf_len(command) != 0 && options.remote_command != NULL) 1393 fatal("Cannot execute command-line and remote command."); 1394 1395 /* Cannot fork to background if no command. */ 1396 if (options.fork_after_authentication && sshbuf_len(command) == 0 && 1397 options.remote_command == NULL && 1398 options.session_type != SESSION_TYPE_NONE) 1399 fatal("Cannot fork into background without a command " 1400 "to execute."); 1401 1402 /* reinit */ 1403 log_init(argv0, options.log_level, options.log_facility, !use_syslog); 1404 for (j = 0; j < options.num_log_verbose; j++) { 1405 if (strcasecmp(options.log_verbose[j], "none") == 0) 1406 break; 1407 log_verbose_add(options.log_verbose[j]); 1408 } 1409 1410 if (options.request_tty == REQUEST_TTY_YES || 1411 options.request_tty == REQUEST_TTY_FORCE) 1412 tty_flag = 1; 1413 1414 /* Allocate a tty by default if no command specified. */ 1415 if (sshbuf_len(command) == 0 && options.remote_command == NULL) 1416 tty_flag = options.request_tty != REQUEST_TTY_NO; 1417 1418 /* Force no tty */ 1419 if (options.request_tty == REQUEST_TTY_NO || 1420 (muxclient_command && muxclient_command != SSHMUX_COMMAND_PROXY) || 1421 options.session_type == SESSION_TYPE_NONE) 1422 tty_flag = 0; 1423 /* Do not allocate a tty if stdin is not a tty. */ 1424 if ((!isatty(fileno(stdin)) || options.stdin_null) && 1425 options.request_tty != REQUEST_TTY_FORCE) { 1426 if (tty_flag) 1427 logit("Pseudo-terminal will not be allocated because " 1428 "stdin is not a terminal."); 1429 tty_flag = 0; 1430 } 1431 1432 /* Set up strings used to percent_expand() arguments */ 1433 cinfo = xcalloc(1, sizeof(*cinfo)); 1434 if (gethostname(thishost, sizeof(thishost)) == -1) 1435 fatal("gethostname: %s", strerror(errno)); 1436 cinfo->thishost = xstrdup(thishost); 1437 thishost[strcspn(thishost, ".")] = '\0'; 1438 cinfo->shorthost = xstrdup(thishost); 1439 xasprintf(&cinfo->portstr, "%d", options.port); 1440 xasprintf(&cinfo->uidstr, "%llu", 1441 (unsigned long long)pw->pw_uid); 1442 cinfo->keyalias = xstrdup(options.host_key_alias ? 1443 options.host_key_alias : options.host_arg); 1444 cinfo->host_arg = xstrdup(options.host_arg); 1445 cinfo->remhost = xstrdup(host); 1446 cinfo->homedir = xstrdup(pw->pw_dir); 1447 cinfo->locuser = xstrdup(pw->pw_name); 1448 cinfo->jmphost = xstrdup(options.jump_host == NULL ? 1449 "" : options.jump_host); 1450 1451 /* 1452 * Expand User. It cannot contain %r (itself) or %C since User is 1453 * a component of the hash. 1454 */ 1455 if (options.user != NULL) { 1456 if ((p = percent_dollar_expand(options.user, 1457 DEFAULT_CLIENT_PERCENT_EXPAND_ARGS_NOUSER(cinfo), 1458 (char *)NULL)) == NULL) 1459 fatal("invalid environment variable expansion"); 1460 free(options.user); 1461 options.user = p; 1462 if (!valid_ruser(options.user)) 1463 fatal("remote username contains invalid characters"); 1464 } 1465 1466 /* Now User is expanded, store it and calculate hash. */ 1467 cinfo->remuser = xstrdup(options.user); 1468 cinfo->conn_hash_hex = ssh_connection_hash(cinfo->thishost, 1469 cinfo->remhost, cinfo->portstr, cinfo->remuser, cinfo->jmphost); 1470 1471 /* Find canonic host name. */ 1472 if (strchr(host, '.') == NULL) { 1473 struct addrinfo hints; 1474 struct addrinfo *ai = NULL; 1475 int errgai; 1476 1477 memset(&hints, 0, sizeof(hints)); 1478 hints.ai_family = options.address_family; 1479 hints.ai_flags = AI_CANONNAME; 1480 hints.ai_socktype = SOCK_STREAM; 1481 errgai = getaddrinfo(host, NULL, &hints, &ai); 1482 if (errgai == 0) { 1483 if (ai->ai_canonname != NULL) { 1484 free(host); 1485 host = xstrdup(ai->ai_canonname); 1486 } 1487 freeaddrinfo(ai); 1488 } 1489 } 1490 1491 /* 1492 * Expand tokens in arguments. NB. LocalCommand is expanded later, 1493 * after port-forwarding is set up, so it may pick up any local 1494 * tunnel interface name allocated. 1495 */ 1496 if (options.remote_command != NULL) { 1497 debug3("expanding RemoteCommand: %s", options.remote_command); 1498 cp = options.remote_command; 1499 options.remote_command = default_client_percent_expand(cp, 1500 cinfo); 1501 debug3("expanded RemoteCommand: %s", options.remote_command); 1502 free(cp); 1503 if ((r = sshbuf_put(command, options.remote_command, 1504 strlen(options.remote_command))) != 0) 1505 fatal_fr(r, "buffer error"); 1506 } 1507 1508 if (options.control_path != NULL) { 1509 cp = tilde_expand_filename(options.control_path, getuid()); 1510 free(options.control_path); 1511 options.control_path = default_client_percent_dollar_expand(cp, 1512 cinfo); 1513 free(cp); 1514 } 1515 1516 if (options.identity_agent != NULL) { 1517 p = tilde_expand_filename(options.identity_agent, getuid()); 1518 cp = default_client_percent_dollar_expand(p, cinfo); 1519 free(p); 1520 free(options.identity_agent); 1521 options.identity_agent = cp; 1522 } 1523 1524 if (options.revoked_host_keys != NULL) { 1525 p = tilde_expand_filename(options.revoked_host_keys, getuid()); 1526 cp = default_client_percent_dollar_expand(p, cinfo); 1527 free(p); 1528 free(options.revoked_host_keys); 1529 options.revoked_host_keys = cp; 1530 } 1531 1532 if (options.forward_agent_sock_path != NULL) { 1533 p = tilde_expand_filename(options.forward_agent_sock_path, 1534 getuid()); 1535 cp = default_client_percent_dollar_expand(p, cinfo); 1536 free(p); 1537 free(options.forward_agent_sock_path); 1538 options.forward_agent_sock_path = cp; 1539 if (stat(options.forward_agent_sock_path, &st) != 0) { 1540 error("Cannot forward agent socket path \"%s\": %s", 1541 options.forward_agent_sock_path, strerror(errno)); 1542 if (options.exit_on_forward_failure) 1543 cleanup_exit(255); 1544 } 1545 } 1546 1547 if (options.version_addendum != NULL) { 1548 cp = default_client_percent_dollar_expand( 1549 options.version_addendum, cinfo); 1550 free(options.version_addendum); 1551 options.version_addendum = cp; 1552 } 1553 1554 if (options.num_system_hostfiles > 0 && 1555 strcasecmp(options.system_hostfiles[0], "none") == 0) { 1556 if (options.num_system_hostfiles > 1) 1557 fatal("Invalid GlobalKnownHostsFiles: \"none\" " 1558 "appears with other entries"); 1559 free(options.system_hostfiles[0]); 1560 options.system_hostfiles[0] = NULL; 1561 options.num_system_hostfiles = 0; 1562 } 1563 1564 if (options.num_user_hostfiles > 0 && 1565 strcasecmp(options.user_hostfiles[0], "none") == 0) { 1566 if (options.num_user_hostfiles > 1) 1567 fatal("Invalid UserKnownHostsFiles: \"none\" " 1568 "appears with other entries"); 1569 free(options.user_hostfiles[0]); 1570 options.user_hostfiles[0] = NULL; 1571 options.num_user_hostfiles = 0; 1572 } 1573 for (j = 0; j < options.num_user_hostfiles; j++) { 1574 if (options.user_hostfiles[j] == NULL) 1575 continue; 1576 cp = tilde_expand_filename(options.user_hostfiles[j], getuid()); 1577 p = default_client_percent_dollar_expand(cp, cinfo); 1578 if (strcmp(options.user_hostfiles[j], p) != 0) 1579 debug3("expanded UserKnownHostsFile '%s' -> " 1580 "'%s'", options.user_hostfiles[j], p); 1581 free(options.user_hostfiles[j]); 1582 free(cp); 1583 options.user_hostfiles[j] = p; 1584 } 1585 1586 for (j = 0; j < options.num_setenv; j++) { 1587 char *name = options.setenv[j], *value; 1588 1589 if (name == NULL) 1590 continue; 1591 /* Expand only the value portion, not the variable name. */ 1592 if ((value = strchr(name, '=')) == NULL) { 1593 /* shouldn't happen; vars are checked in readconf.c */ 1594 fatal("Invalid config SetEnv: %s", name); 1595 } 1596 *value++ = '\0'; 1597 cp = default_client_percent_dollar_expand(value, cinfo); 1598 xasprintf(&p, "%s=%s", name, cp); 1599 if (strcmp(value, p) != 0) { 1600 debug3("expanded SetEnv '%s' '%s' -> '%s'", 1601 name, value, cp); 1602 } 1603 free(options.setenv[j]); 1604 free(cp); 1605 options.setenv[j] = p; 1606 } 1607 1608 for (i = 0; i < options.num_local_forwards; i++) { 1609 if (options.local_forwards[i].listen_path != NULL) { 1610 cp = options.local_forwards[i].listen_path; 1611 p = options.local_forwards[i].listen_path = 1612 default_client_percent_expand(cp, cinfo); 1613 if (strcmp(cp, p) != 0) 1614 debug3("expanded LocalForward listen path " 1615 "'%s' -> '%s'", cp, p); 1616 free(cp); 1617 } 1618 if (options.local_forwards[i].connect_path != NULL) { 1619 cp = options.local_forwards[i].connect_path; 1620 p = options.local_forwards[i].connect_path = 1621 default_client_percent_expand(cp, cinfo); 1622 if (strcmp(cp, p) != 0) 1623 debug3("expanded LocalForward connect path " 1624 "'%s' -> '%s'", cp, p); 1625 free(cp); 1626 } 1627 } 1628 1629 for (i = 0; i < options.num_remote_forwards; i++) { 1630 if (options.remote_forwards[i].listen_path != NULL) { 1631 cp = options.remote_forwards[i].listen_path; 1632 p = options.remote_forwards[i].listen_path = 1633 default_client_percent_expand(cp, cinfo); 1634 if (strcmp(cp, p) != 0) 1635 debug3("expanded RemoteForward listen path " 1636 "'%s' -> '%s'", cp, p); 1637 free(cp); 1638 } 1639 if (options.remote_forwards[i].connect_path != NULL) { 1640 cp = options.remote_forwards[i].connect_path; 1641 p = options.remote_forwards[i].connect_path = 1642 default_client_percent_expand(cp, cinfo); 1643 if (strcmp(cp, p) != 0) 1644 debug3("expanded RemoteForward connect path " 1645 "'%s' -> '%s'", cp, p); 1646 free(cp); 1647 } 1648 } 1649 1650 if (config_test) { 1651 dump_client_config(&options, host); 1652 exit(0); 1653 } 1654 1655 /* Expand SecurityKeyProvider if it refers to an environment variable */ 1656 if (options.sk_provider != NULL && *options.sk_provider == '$' && 1657 strlen(options.sk_provider) > 1) { 1658 if ((cp = getenv(options.sk_provider + 1)) == NULL) { 1659 debug("Authenticator provider %s did not resolve; " 1660 "disabling", options.sk_provider); 1661 free(options.sk_provider); 1662 options.sk_provider = NULL; 1663 } else { 1664 debug2("resolved SecurityKeyProvider %s => %s", 1665 options.sk_provider, cp); 1666 free(options.sk_provider); 1667 options.sk_provider = xstrdup(cp); 1668 } 1669 } 1670 1671 if (muxclient_command != 0 && options.control_path == NULL) 1672 fatal("No ControlPath specified for \"-O\" command"); 1673 if (options.control_path != NULL) { 1674 int sock; 1675 if ((sock = muxclient(options.control_path)) >= 0) { 1676 ssh_packet_set_connection(ssh, sock, sock); 1677 ssh_packet_set_mux(ssh); 1678 goto skip_connect; 1679 } 1680 } 1681 1682 /* 1683 * If hostname canonicalisation was not enabled, then we may not 1684 * have yet resolved the hostname. Do so now. 1685 */ 1686 if (addrs == NULL && options.proxy_command == NULL) { 1687 debug2("resolving \"%s\" port %d", host, options.port); 1688 if ((addrs = resolve_host(host, options.port, 1, 1689 cname, sizeof(cname))) == NULL) 1690 cleanup_exit(255); /* resolve_host logs the error */ 1691 } 1692 1693 if (options.connection_timeout >= INT_MAX/1000) 1694 timeout_ms = INT_MAX; 1695 else 1696 timeout_ms = options.connection_timeout * 1000; 1697 1698 /* Apply channels timeouts, if set */ 1699 channel_clear_timeouts(ssh); 1700 for (j = 0; j < options.num_channel_timeouts; j++) { 1701 debug3("applying channel timeout %s", 1702 options.channel_timeouts[j]); 1703 if (parse_pattern_interval(options.channel_timeouts[j], 1704 &cp, &i) != 0) { 1705 fatal_f("internal error: bad timeout %s", 1706 options.channel_timeouts[j]); 1707 } 1708 channel_add_timeout(ssh, cp, i); 1709 free(cp); 1710 } 1711 1712 /* Open a connection to the remote host. */ 1713 if (ssh_connect(ssh, host, options.host_arg, addrs, &hostaddr, 1714 options.port, options.connection_attempts, 1715 &timeout_ms, options.tcp_keep_alive) != 0) 1716 exit(255); 1717 1718 if (addrs != NULL) 1719 freeaddrinfo(addrs); 1720 1721 ssh_packet_set_timeout(ssh, options.server_alive_interval, 1722 options.server_alive_count_max); 1723 1724 if (timeout_ms > 0) 1725 debug3("timeout: %d ms remain after connect", timeout_ms); 1726 1727 /* 1728 * If we successfully made the connection and we have hostbased auth 1729 * enabled, load the public keys so we can later use the ssh-keysign 1730 * helper to sign challenges. 1731 */ 1732 sensitive_data.nkeys = 0; 1733 sensitive_data.keys = NULL; 1734 if (options.hostbased_authentication) { 1735 int loaded = 0; 1736 1737 sensitive_data.nkeys = 10; 1738 sensitive_data.keys = xcalloc(sensitive_data.nkeys, 1739 sizeof(*sensitive_data.keys)); 1740 1741 /* XXX check errors? */ 1742 #define L_PUBKEY(p,o) do { \ 1743 if ((o) >= sensitive_data.nkeys) \ 1744 fatal_f("pubkey out of array bounds"); \ 1745 check_load(sshkey_load_public(p, &(sensitive_data.keys[o]), NULL), \ 1746 &(sensitive_data.keys[o]), p, "pubkey"); \ 1747 if (sensitive_data.keys[o] != NULL) { \ 1748 debug2("hostbased key %d: %s key from \"%s\"", o, \ 1749 sshkey_ssh_name(sensitive_data.keys[o]), p); \ 1750 loaded++; \ 1751 } \ 1752 } while (0) 1753 #define L_CERT(p,o) do { \ 1754 if ((o) >= sensitive_data.nkeys) \ 1755 fatal_f("cert out of array bounds"); \ 1756 check_load(sshkey_load_cert(p, &(sensitive_data.keys[o])), \ 1757 &(sensitive_data.keys[o]), p, "cert"); \ 1758 if (sensitive_data.keys[o] != NULL) { \ 1759 debug2("hostbased key %d: %s cert from \"%s\"", o, \ 1760 sshkey_ssh_name(sensitive_data.keys[o]), p); \ 1761 loaded++; \ 1762 } \ 1763 } while (0) 1764 1765 if (options.hostbased_authentication == 1) { 1766 L_CERT(_PATH_HOST_ECDSA_KEY_FILE, 0); 1767 L_CERT(_PATH_HOST_ED25519_KEY_FILE, 1); 1768 L_CERT(_PATH_HOST_RSA_KEY_FILE, 2); 1769 #ifdef WITH_DSA 1770 L_CERT(_PATH_HOST_DSA_KEY_FILE, 3); 1771 #endif 1772 L_PUBKEY(_PATH_HOST_ECDSA_KEY_FILE, 4); 1773 L_PUBKEY(_PATH_HOST_ED25519_KEY_FILE, 5); 1774 L_PUBKEY(_PATH_HOST_RSA_KEY_FILE, 6); 1775 #ifdef WITH_DSA 1776 L_PUBKEY(_PATH_HOST_DSA_KEY_FILE, 7); 1777 #endif 1778 L_CERT(_PATH_HOST_XMSS_KEY_FILE, 8); 1779 L_PUBKEY(_PATH_HOST_XMSS_KEY_FILE, 9); 1780 if (loaded == 0) 1781 debug("HostbasedAuthentication enabled but no " 1782 "local public host keys could be loaded."); 1783 } 1784 } 1785 1786 /* load options.identity_files */ 1787 load_public_identity_files(cinfo); 1788 1789 /* optionally set the SSH_AUTHSOCKET_ENV_NAME variable */ 1790 if (options.identity_agent && 1791 strcmp(options.identity_agent, SSH_AUTHSOCKET_ENV_NAME) != 0) { 1792 if (strcmp(options.identity_agent, "none") == 0) { 1793 unsetenv(SSH_AUTHSOCKET_ENV_NAME); 1794 } else { 1795 cp = options.identity_agent; 1796 /* legacy (limited) format */ 1797 if (cp[0] == '$' && cp[1] != '{') { 1798 if (!valid_env_name(cp + 1)) { 1799 fatal("Invalid IdentityAgent " 1800 "environment variable name %s", cp); 1801 } 1802 if ((p = getenv(cp + 1)) == NULL) 1803 unsetenv(SSH_AUTHSOCKET_ENV_NAME); 1804 else 1805 setenv(SSH_AUTHSOCKET_ENV_NAME, p, 1); 1806 } else { 1807 /* identity_agent specifies a path directly */ 1808 setenv(SSH_AUTHSOCKET_ENV_NAME, cp, 1); 1809 } 1810 } 1811 } 1812 1813 if (options.forward_agent && options.forward_agent_sock_path != NULL) { 1814 cp = options.forward_agent_sock_path; 1815 if (cp[0] == '$') { 1816 if (!valid_env_name(cp + 1)) { 1817 fatal("Invalid ForwardAgent environment variable name %s", cp); 1818 } 1819 if ((p = getenv(cp + 1)) != NULL) 1820 forward_agent_sock_path = xstrdup(p); 1821 else 1822 options.forward_agent = 0; 1823 free(cp); 1824 } else { 1825 forward_agent_sock_path = cp; 1826 } 1827 } 1828 1829 /* Expand ~ in known host file names. */ 1830 tilde_expand_paths(options.system_hostfiles, 1831 options.num_system_hostfiles); 1832 tilde_expand_paths(options.user_hostfiles, options.num_user_hostfiles); 1833 1834 ssh_signal(SIGCHLD, main_sigchld_handler); 1835 1836 /* Log into the remote system. Never returns if the login fails. */ 1837 ssh_login(ssh, &sensitive_data, host, (struct sockaddr *)&hostaddr, 1838 options.port, pw, timeout_ms, cinfo); 1839 1840 /* We no longer need the private host keys. Clear them now. */ 1841 if (sensitive_data.nkeys != 0) { 1842 for (i = 0; i < sensitive_data.nkeys; i++) { 1843 if (sensitive_data.keys[i] != NULL) { 1844 /* Destroys contents safely */ 1845 debug3("clear hostkey %d", i); 1846 sshkey_free(sensitive_data.keys[i]); 1847 sensitive_data.keys[i] = NULL; 1848 } 1849 } 1850 free(sensitive_data.keys); 1851 } 1852 for (i = 0; i < options.num_identity_files; i++) { 1853 free(options.identity_files[i]); 1854 options.identity_files[i] = NULL; 1855 if (options.identity_keys[i]) { 1856 sshkey_free(options.identity_keys[i]); 1857 options.identity_keys[i] = NULL; 1858 } 1859 } 1860 for (i = 0; i < options.num_certificate_files; i++) { 1861 free(options.certificate_files[i]); 1862 options.certificate_files[i] = NULL; 1863 } 1864 1865 #ifdef ENABLE_PKCS11 1866 (void)pkcs11_del_provider(options.pkcs11_provider); 1867 #endif 1868 1869 skip_connect: 1870 exit_status = ssh_session2(ssh, cinfo); 1871 ssh_conn_info_free(cinfo); 1872 ssh_packet_close(ssh); 1873 1874 if (options.control_path != NULL && muxserver_sock != -1) 1875 unlink(options.control_path); 1876 1877 /* Kill ProxyCommand if it is running. */ 1878 ssh_kill_proxy_command(); 1879 1880 return exit_status; 1881 } 1882 1883 static void 1884 control_persist_detach(void) 1885 { 1886 pid_t pid; 1887 1888 debug_f("backgrounding master process"); 1889 1890 /* 1891 * master (current process) into the background, and make the 1892 * foreground process a client of the backgrounded master. 1893 */ 1894 switch ((pid = fork())) { 1895 case -1: 1896 fatal_f("fork: %s", strerror(errno)); 1897 case 0: 1898 /* Child: master process continues mainloop */ 1899 break; 1900 default: 1901 /* 1902 * Parent: set up mux client to connect to backgrounded 1903 * master. 1904 */ 1905 debug2_f("background process is %ld", (long)pid); 1906 options.stdin_null = ostdin_null_flag; 1907 options.request_tty = orequest_tty; 1908 tty_flag = otty_flag; 1909 options.fork_after_authentication = ofork_after_authentication; 1910 options.session_type = osession_type; 1911 close(muxserver_sock); 1912 muxserver_sock = -1; 1913 options.control_master = SSHCTL_MASTER_NO; 1914 (void)muxclient(options.control_path); 1915 /* muxclient() doesn't return on success. */ 1916 fatal("Failed to connect to new control master"); 1917 } 1918 if (stdfd_devnull(1, 1, !(log_is_on_stderr() && debug_flag)) == -1) 1919 error_f("stdfd_devnull failed"); 1920 daemon(1, 1); 1921 setproctitle("%s [mux]", options.control_path); 1922 } 1923 1924 /* Do fork() after authentication. Used by "ssh -f" */ 1925 static void 1926 fork_postauth(void) 1927 { 1928 if (need_controlpersist_detach) 1929 control_persist_detach(); 1930 debug("forking to background"); 1931 options.fork_after_authentication = 0; 1932 if (daemon(1, 1) == -1) 1933 fatal("daemon() failed: %.200s", strerror(errno)); 1934 if (stdfd_devnull(1, 1, !(log_is_on_stderr() && debug_flag)) == -1) 1935 error_f("stdfd_devnull failed"); 1936 } 1937 1938 static void 1939 forwarding_success(void) 1940 { 1941 if (forward_confirms_pending == -1) 1942 return; 1943 if (--forward_confirms_pending == 0) { 1944 debug_f("all expected forwarding replies received"); 1945 if (options.fork_after_authentication) 1946 fork_postauth(); 1947 } else { 1948 debug2_f("%d expected forwarding replies remaining", 1949 forward_confirms_pending); 1950 } 1951 } 1952 1953 /* Callback for remote forward global requests */ 1954 static void 1955 ssh_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt) 1956 { 1957 struct Forward *rfwd = (struct Forward *)ctxt; 1958 u_int port; 1959 int r; 1960 1961 /* XXX verbose() on failure? */ 1962 debug("remote forward %s for: listen %s%s%d, connect %s:%d", 1963 type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", 1964 rfwd->listen_path ? rfwd->listen_path : 1965 rfwd->listen_host ? rfwd->listen_host : "", 1966 (rfwd->listen_path || rfwd->listen_host) ? ":" : "", 1967 rfwd->listen_port, rfwd->connect_path ? rfwd->connect_path : 1968 rfwd->connect_host, rfwd->connect_port); 1969 if (rfwd->listen_path == NULL && rfwd->listen_port == 0) { 1970 if (type == SSH2_MSG_REQUEST_SUCCESS) { 1971 if ((r = sshpkt_get_u32(ssh, &port)) != 0) 1972 fatal_fr(r, "parse packet"); 1973 if (port > 65535) { 1974 error("Invalid allocated port %u for remote " 1975 "forward to %s:%d", port, 1976 rfwd->connect_host, rfwd->connect_port); 1977 /* Ensure failure processing runs below */ 1978 type = SSH2_MSG_REQUEST_FAILURE; 1979 channel_update_permission(ssh, 1980 rfwd->handle, -1); 1981 } else { 1982 rfwd->allocated_port = (int)port; 1983 logit("Allocated port %u for remote " 1984 "forward to %s:%d", 1985 rfwd->allocated_port, rfwd->connect_path ? 1986 rfwd->connect_path : rfwd->connect_host, 1987 rfwd->connect_port); 1988 channel_update_permission(ssh, 1989 rfwd->handle, rfwd->allocated_port); 1990 } 1991 } else { 1992 channel_update_permission(ssh, rfwd->handle, -1); 1993 } 1994 } 1995 1996 if (type == SSH2_MSG_REQUEST_FAILURE) { 1997 if (options.exit_on_forward_failure) { 1998 if (rfwd->listen_path != NULL) 1999 fatal("Error: remote port forwarding failed " 2000 "for listen path %s", rfwd->listen_path); 2001 else 2002 fatal("Error: remote port forwarding failed " 2003 "for listen port %d", rfwd->listen_port); 2004 } else { 2005 if (rfwd->listen_path != NULL) 2006 logit("Warning: remote port forwarding failed " 2007 "for listen path %s", rfwd->listen_path); 2008 else 2009 logit("Warning: remote port forwarding failed " 2010 "for listen port %d", rfwd->listen_port); 2011 } 2012 } 2013 forwarding_success(); 2014 } 2015 2016 static void 2017 client_cleanup_stdio_fwd(struct ssh *ssh, int id, int force, void *arg) 2018 { 2019 debug("stdio forwarding: done"); 2020 cleanup_exit(0); 2021 } 2022 2023 static void 2024 ssh_stdio_confirm(struct ssh *ssh, int id, int success, void *arg) 2025 { 2026 if (!success) 2027 fatal("stdio forwarding failed"); 2028 } 2029 2030 static void 2031 ssh_tun_confirm(struct ssh *ssh, int id, int success, void *arg) 2032 { 2033 if (!success) { 2034 error("Tunnel forwarding failed"); 2035 if (options.exit_on_forward_failure) 2036 cleanup_exit(255); 2037 } 2038 2039 debug_f("tunnel forward established, id=%d", id); 2040 forwarding_success(); 2041 } 2042 2043 static void 2044 ssh_init_stdio_forwarding(struct ssh *ssh) 2045 { 2046 Channel *c; 2047 int in, out; 2048 2049 if (options.stdio_forward_host == NULL) 2050 return; 2051 2052 debug3_f("%s:%d", options.stdio_forward_host, 2053 options.stdio_forward_port); 2054 2055 if ((in = dup(STDIN_FILENO)) == -1 || 2056 (out = dup(STDOUT_FILENO)) == -1) 2057 fatal_f("dup() in/out failed"); 2058 if ((c = channel_connect_stdio_fwd(ssh, options.stdio_forward_host, 2059 options.stdio_forward_port, in, out, 2060 CHANNEL_NONBLOCK_STDIO)) == NULL) 2061 fatal_f("channel_connect_stdio_fwd failed"); 2062 channel_register_cleanup(ssh, c->self, client_cleanup_stdio_fwd, 0); 2063 channel_register_open_confirm(ssh, c->self, ssh_stdio_confirm, NULL); 2064 } 2065 2066 static void 2067 ssh_init_forward_permissions(struct ssh *ssh, const char *what, char **opens, 2068 u_int num_opens) 2069 { 2070 u_int i; 2071 int port; 2072 char *addr, *arg, *oarg; 2073 int where = FORWARD_LOCAL; 2074 2075 channel_clear_permission(ssh, FORWARD_ADM, where); 2076 if (num_opens == 0) 2077 return; /* permit any */ 2078 2079 /* handle keywords: "any" / "none" */ 2080 if (num_opens == 1 && strcmp(opens[0], "any") == 0) 2081 return; 2082 if (num_opens == 1 && strcmp(opens[0], "none") == 0) { 2083 channel_disable_admin(ssh, where); 2084 return; 2085 } 2086 /* Otherwise treat it as a list of permitted host:port */ 2087 for (i = 0; i < num_opens; i++) { 2088 oarg = arg = xstrdup(opens[i]); 2089 addr = hpdelim(&arg); 2090 if (addr == NULL) 2091 fatal_f("missing host in %s", what); 2092 addr = cleanhostname(addr); 2093 if (arg == NULL || ((port = permitopen_port(arg)) < 0)) 2094 fatal_f("bad port number in %s", what); 2095 /* Send it to channels layer */ 2096 channel_add_permission(ssh, FORWARD_ADM, 2097 where, addr, port); 2098 free(oarg); 2099 } 2100 } 2101 2102 static void 2103 ssh_init_forwarding(struct ssh *ssh, char **ifname) 2104 { 2105 int success = 0; 2106 int i; 2107 2108 ssh_init_forward_permissions(ssh, "permitremoteopen", 2109 options.permitted_remote_opens, 2110 options.num_permitted_remote_opens); 2111 2112 if (options.exit_on_forward_failure) 2113 forward_confirms_pending = 0; /* track pending requests */ 2114 /* Initiate local TCP/IP port forwardings. */ 2115 for (i = 0; i < options.num_local_forwards; i++) { 2116 debug("Local connections to %.200s:%d forwarded to remote " 2117 "address %.200s:%d", 2118 (options.local_forwards[i].listen_path != NULL) ? 2119 options.local_forwards[i].listen_path : 2120 (options.local_forwards[i].listen_host == NULL) ? 2121 (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") : 2122 options.local_forwards[i].listen_host, 2123 options.local_forwards[i].listen_port, 2124 (options.local_forwards[i].connect_path != NULL) ? 2125 options.local_forwards[i].connect_path : 2126 options.local_forwards[i].connect_host, 2127 options.local_forwards[i].connect_port); 2128 success += channel_setup_local_fwd_listener(ssh, 2129 &options.local_forwards[i], &options.fwd_opts); 2130 } 2131 if (i > 0 && success != i && options.exit_on_forward_failure) 2132 fatal("Could not request local forwarding."); 2133 if (i > 0 && success == 0) 2134 error("Could not request local forwarding."); 2135 2136 /* Initiate remote TCP/IP port forwardings. */ 2137 for (i = 0; i < options.num_remote_forwards; i++) { 2138 debug("Remote connections from %.200s:%d forwarded to " 2139 "local address %.200s:%d", 2140 (options.remote_forwards[i].listen_path != NULL) ? 2141 options.remote_forwards[i].listen_path : 2142 (options.remote_forwards[i].listen_host == NULL) ? 2143 "LOCALHOST" : options.remote_forwards[i].listen_host, 2144 options.remote_forwards[i].listen_port, 2145 (options.remote_forwards[i].connect_path != NULL) ? 2146 options.remote_forwards[i].connect_path : 2147 options.remote_forwards[i].connect_host, 2148 options.remote_forwards[i].connect_port); 2149 if ((options.remote_forwards[i].handle = 2150 channel_request_remote_forwarding(ssh, 2151 &options.remote_forwards[i])) >= 0) { 2152 client_register_global_confirm( 2153 ssh_confirm_remote_forward, 2154 &options.remote_forwards[i]); 2155 forward_confirms_pending++; 2156 } else if (options.exit_on_forward_failure) 2157 fatal("Could not request remote forwarding."); 2158 else 2159 logit("Warning: Could not request remote forwarding."); 2160 } 2161 2162 /* Initiate tunnel forwarding. */ 2163 if (options.tun_open != SSH_TUNMODE_NO) { 2164 if ((*ifname = client_request_tun_fwd(ssh, 2165 options.tun_open, options.tun_local, 2166 options.tun_remote, ssh_tun_confirm, NULL)) != NULL) 2167 forward_confirms_pending++; 2168 else if (options.exit_on_forward_failure) 2169 fatal("Could not request tunnel forwarding."); 2170 else 2171 error("Could not request tunnel forwarding."); 2172 } 2173 if (forward_confirms_pending > 0) { 2174 debug_f("expecting replies for %d forwards", 2175 forward_confirms_pending); 2176 } 2177 } 2178 2179 static void 2180 check_agent_present(void) 2181 { 2182 int r; 2183 2184 if (options.forward_agent) { 2185 /* Clear agent forwarding if we don't have an agent. */ 2186 if ((r = ssh_get_authentication_socket(NULL)) != 0) { 2187 options.forward_agent = 0; 2188 if (r != SSH_ERR_AGENT_NOT_PRESENT) 2189 debug_r(r, "ssh_get_authentication_socket"); 2190 } 2191 } 2192 } 2193 2194 static void 2195 ssh_session2_setup(struct ssh *ssh, int id, int success, void *arg) 2196 { 2197 extern char **environ; 2198 const char *display, *term; 2199 int r, interactive = tty_flag; 2200 char *proto = NULL, *data = NULL; 2201 2202 if (!success) 2203 return; /* No need for error message, channels code sends one */ 2204 2205 display = getenv("DISPLAY"); 2206 if (display == NULL && options.forward_x11) 2207 debug("X11 forwarding requested but DISPLAY not set"); 2208 if (options.forward_x11 && client_x11_get_proto(ssh, display, 2209 options.xauth_location, options.forward_x11_trusted, 2210 options.forward_x11_timeout, &proto, &data) == 0) { 2211 /* Request forwarding with authentication spoofing. */ 2212 debug("Requesting X11 forwarding with authentication " 2213 "spoofing."); 2214 x11_request_forwarding_with_spoofing(ssh, id, display, proto, 2215 data, 1); 2216 client_expect_confirm(ssh, id, "X11 forwarding", CONFIRM_WARN); 2217 /* XXX exit_on_forward_failure */ 2218 interactive = 1; 2219 } 2220 2221 check_agent_present(); 2222 if (options.forward_agent) { 2223 debug("Requesting authentication agent forwarding."); 2224 channel_request_start(ssh, id, "auth-agent-req@openssh.com", 0); 2225 if ((r = sshpkt_send(ssh)) != 0) 2226 fatal_fr(r, "send packet"); 2227 } 2228 2229 /* Tell the packet module whether this is an interactive session. */ 2230 ssh_packet_set_interactive(ssh, interactive, 2231 options.ip_qos_interactive, options.ip_qos_bulk); 2232 2233 if ((term = lookup_env_in_list("TERM", options.setenv, 2234 options.num_setenv)) == NULL || *term == '\0') 2235 term = getenv("TERM"); 2236 client_session2_setup(ssh, id, tty_flag, 2237 options.session_type == SESSION_TYPE_SUBSYSTEM, term, 2238 NULL, fileno(stdin), command, environ); 2239 } 2240 2241 /* open new channel for a session */ 2242 static int 2243 ssh_session2_open(struct ssh *ssh) 2244 { 2245 Channel *c; 2246 int window, packetmax, in, out, err; 2247 2248 if (options.stdin_null) { 2249 in = open(_PATH_DEVNULL, O_RDONLY); 2250 } else { 2251 in = dup(STDIN_FILENO); 2252 } 2253 out = dup(STDOUT_FILENO); 2254 err = dup(STDERR_FILENO); 2255 2256 if (in == -1 || out == -1 || err == -1) 2257 fatal("dup() in/out/err failed"); 2258 2259 window = CHAN_SES_WINDOW_DEFAULT; 2260 packetmax = CHAN_SES_PACKET_DEFAULT; 2261 if (tty_flag) { 2262 window >>= 1; 2263 packetmax >>= 1; 2264 } 2265 c = channel_new(ssh, 2266 "session", SSH_CHANNEL_OPENING, in, out, err, 2267 window, packetmax, CHAN_EXTENDED_WRITE, 2268 "client-session", CHANNEL_NONBLOCK_STDIO); 2269 2270 debug3_f("channel_new: %d", c->self); 2271 2272 channel_send_open(ssh, c->self); 2273 if (options.session_type != SESSION_TYPE_NONE) 2274 channel_register_open_confirm(ssh, c->self, 2275 ssh_session2_setup, NULL); 2276 2277 return c->self; 2278 } 2279 2280 static int 2281 ssh_session2(struct ssh *ssh, const struct ssh_conn_info *cinfo) 2282 { 2283 int r, interactive, id = -1; 2284 char *cp, *tun_fwd_ifname = NULL; 2285 2286 /* XXX should be pre-session */ 2287 if (!options.control_persist) 2288 ssh_init_stdio_forwarding(ssh); 2289 2290 ssh_init_forwarding(ssh, &tun_fwd_ifname); 2291 2292 if (options.local_command != NULL) { 2293 debug3("expanding LocalCommand: %s", options.local_command); 2294 cp = options.local_command; 2295 options.local_command = percent_expand(cp, 2296 DEFAULT_CLIENT_PERCENT_EXPAND_ARGS(cinfo), 2297 "T", tun_fwd_ifname == NULL ? "NONE" : tun_fwd_ifname, 2298 (char *)NULL); 2299 debug3("expanded LocalCommand: %s", options.local_command); 2300 free(cp); 2301 } 2302 2303 /* Start listening for multiplex clients */ 2304 if (!ssh_packet_get_mux(ssh)) 2305 muxserver_listen(ssh); 2306 2307 /* 2308 * If we are in control persist mode and have a working mux listen 2309 * socket, then prepare to background ourselves and have a foreground 2310 * client attach as a control client. 2311 * NB. we must save copies of the flags that we override for 2312 * the backgrounding, since we defer attachment of the client until 2313 * after the connection is fully established (in particular, 2314 * async rfwd replies have been received for ExitOnForwardFailure). 2315 */ 2316 if (options.control_persist && muxserver_sock != -1) { 2317 ostdin_null_flag = options.stdin_null; 2318 osession_type = options.session_type; 2319 orequest_tty = options.request_tty; 2320 otty_flag = tty_flag; 2321 ofork_after_authentication = options.fork_after_authentication; 2322 options.stdin_null = 1; 2323 options.session_type = SESSION_TYPE_NONE; 2324 tty_flag = 0; 2325 if ((osession_type != SESSION_TYPE_NONE || 2326 options.stdio_forward_host != NULL)) 2327 need_controlpersist_detach = 1; 2328 options.fork_after_authentication = 1; 2329 } 2330 /* 2331 * ControlPersist mux listen socket setup failed, attempt the 2332 * stdio forward setup that we skipped earlier. 2333 */ 2334 if (options.control_persist && muxserver_sock == -1) 2335 ssh_init_stdio_forwarding(ssh); 2336 2337 if (options.session_type != SESSION_TYPE_NONE) 2338 id = ssh_session2_open(ssh); 2339 else { 2340 interactive = options.control_master == SSHCTL_MASTER_NO; 2341 /* ControlPersist may have clobbered ControlMaster, so check */ 2342 if (need_controlpersist_detach) 2343 interactive = otty_flag != 0; 2344 ssh_packet_set_interactive(ssh, interactive, 2345 options.ip_qos_interactive, options.ip_qos_bulk); 2346 } 2347 2348 /* If we don't expect to open a new session, then disallow it */ 2349 if (options.control_master == SSHCTL_MASTER_NO && 2350 (ssh->compat & SSH_NEW_OPENSSH)) { 2351 debug("Requesting no-more-sessions@openssh.com"); 2352 if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || 2353 (r = sshpkt_put_cstring(ssh, 2354 "no-more-sessions@openssh.com")) != 0 || 2355 (r = sshpkt_put_u8(ssh, 0)) != 0 || 2356 (r = sshpkt_send(ssh)) != 0) 2357 fatal_fr(r, "send packet"); 2358 } 2359 2360 /* Execute a local command */ 2361 if (options.local_command != NULL && 2362 options.permit_local_command) 2363 ssh_local_cmd(options.local_command); 2364 2365 /* 2366 * stdout is now owned by the session channel; clobber it here 2367 * so future channel closes are propagated to the local fd. 2368 * NB. this can only happen after LocalCommand has completed, 2369 * as it may want to write to stdout. 2370 */ 2371 if (!need_controlpersist_detach && stdfd_devnull(0, 1, 0) == -1) 2372 error_f("stdfd_devnull failed"); 2373 2374 /* 2375 * If requested and we are not interested in replies to remote 2376 * forwarding requests, then let ssh continue in the background. 2377 */ 2378 if (options.fork_after_authentication) { 2379 if (options.exit_on_forward_failure && 2380 options.num_remote_forwards > 0) { 2381 debug("deferring postauth fork until remote forward " 2382 "confirmation received"); 2383 } else 2384 fork_postauth(); 2385 } 2386 2387 return client_loop(ssh, tty_flag, tty_flag ? 2388 options.escape_char : SSH_ESCAPECHAR_NONE, id); 2389 } 2390 2391 /* Loads all IdentityFile and CertificateFile keys */ 2392 static void 2393 load_public_identity_files(const struct ssh_conn_info *cinfo) 2394 { 2395 char *filename, *cp; 2396 struct sshkey *public; 2397 int i; 2398 u_int n_ids, n_certs; 2399 char *identity_files[SSH_MAX_IDENTITY_FILES]; 2400 struct sshkey *identity_keys[SSH_MAX_IDENTITY_FILES]; 2401 int identity_file_userprovided[SSH_MAX_IDENTITY_FILES]; 2402 char *certificate_files[SSH_MAX_CERTIFICATE_FILES]; 2403 struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES]; 2404 int certificate_file_userprovided[SSH_MAX_CERTIFICATE_FILES]; 2405 #ifdef ENABLE_PKCS11 2406 struct sshkey **keys = NULL; 2407 char **comments = NULL; 2408 int nkeys; 2409 #endif /* PKCS11 */ 2410 2411 n_ids = n_certs = 0; 2412 memset(identity_files, 0, sizeof(identity_files)); 2413 memset(identity_keys, 0, sizeof(identity_keys)); 2414 memset(identity_file_userprovided, 0, 2415 sizeof(identity_file_userprovided)); 2416 memset(certificate_files, 0, sizeof(certificate_files)); 2417 memset(certificates, 0, sizeof(certificates)); 2418 memset(certificate_file_userprovided, 0, 2419 sizeof(certificate_file_userprovided)); 2420 2421 #ifdef ENABLE_PKCS11 2422 if (options.pkcs11_provider != NULL && 2423 options.num_identity_files < SSH_MAX_IDENTITY_FILES && 2424 (pkcs11_init(!options.batch_mode) == 0) && 2425 (nkeys = pkcs11_add_provider(options.pkcs11_provider, NULL, 2426 &keys, &comments)) > 0) { 2427 for (i = 0; i < nkeys; i++) { 2428 if (n_ids >= SSH_MAX_IDENTITY_FILES) { 2429 sshkey_free(keys[i]); 2430 free(comments[i]); 2431 continue; 2432 } 2433 identity_keys[n_ids] = keys[i]; 2434 identity_files[n_ids] = comments[i]; /* transferred */ 2435 n_ids++; 2436 } 2437 free(keys); 2438 free(comments); 2439 } 2440 #endif /* ENABLE_PKCS11 */ 2441 for (i = 0; i < options.num_identity_files; i++) { 2442 if (n_ids >= SSH_MAX_IDENTITY_FILES || 2443 strcasecmp(options.identity_files[i], "none") == 0) { 2444 free(options.identity_files[i]); 2445 options.identity_files[i] = NULL; 2446 continue; 2447 } 2448 cp = tilde_expand_filename(options.identity_files[i], getuid()); 2449 filename = default_client_percent_dollar_expand(cp, cinfo); 2450 free(cp); 2451 check_load(sshkey_load_public(filename, &public, NULL), 2452 &public, filename, "pubkey"); 2453 debug("identity file %s type %d", filename, 2454 public ? public->type : -1); 2455 free(options.identity_files[i]); 2456 identity_files[n_ids] = filename; 2457 identity_keys[n_ids] = public; 2458 identity_file_userprovided[n_ids] = 2459 options.identity_file_userprovided[i]; 2460 if (++n_ids >= SSH_MAX_IDENTITY_FILES) 2461 continue; 2462 2463 /* 2464 * If no certificates have been explicitly listed then try 2465 * to add the default certificate variant too. 2466 */ 2467 if (options.num_certificate_files != 0) 2468 continue; 2469 xasprintf(&cp, "%s-cert", filename); 2470 check_load(sshkey_load_public(cp, &public, NULL), 2471 &public, filename, "pubkey"); 2472 debug("identity file %s type %d", cp, 2473 public ? public->type : -1); 2474 if (public == NULL) { 2475 free(cp); 2476 continue; 2477 } 2478 if (!sshkey_is_cert(public)) { 2479 debug_f("key %s type %s is not a certificate", 2480 cp, sshkey_type(public)); 2481 sshkey_free(public); 2482 free(cp); 2483 continue; 2484 } 2485 /* NB. leave filename pointing to private key */ 2486 identity_files[n_ids] = xstrdup(filename); 2487 identity_keys[n_ids] = public; 2488 identity_file_userprovided[n_ids] = 2489 options.identity_file_userprovided[i]; 2490 n_ids++; 2491 } 2492 2493 if (options.num_certificate_files > SSH_MAX_CERTIFICATE_FILES) 2494 fatal_f("too many certificates"); 2495 for (i = 0; i < options.num_certificate_files; i++) { 2496 cp = tilde_expand_filename(options.certificate_files[i], 2497 getuid()); 2498 filename = default_client_percent_dollar_expand(cp, cinfo); 2499 free(cp); 2500 2501 check_load(sshkey_load_public(filename, &public, NULL), 2502 &public, filename, "certificate"); 2503 debug("certificate file %s type %d", filename, 2504 public ? public->type : -1); 2505 free(options.certificate_files[i]); 2506 options.certificate_files[i] = NULL; 2507 if (public == NULL) { 2508 free(filename); 2509 continue; 2510 } 2511 if (!sshkey_is_cert(public)) { 2512 debug_f("key %s type %s is not a certificate", 2513 filename, sshkey_type(public)); 2514 sshkey_free(public); 2515 free(filename); 2516 continue; 2517 } 2518 certificate_files[n_certs] = filename; 2519 certificates[n_certs] = public; 2520 certificate_file_userprovided[n_certs] = 2521 options.certificate_file_userprovided[i]; 2522 ++n_certs; 2523 } 2524 2525 options.num_identity_files = n_ids; 2526 memcpy(options.identity_files, identity_files, sizeof(identity_files)); 2527 memcpy(options.identity_keys, identity_keys, sizeof(identity_keys)); 2528 memcpy(options.identity_file_userprovided, 2529 identity_file_userprovided, sizeof(identity_file_userprovided)); 2530 2531 options.num_certificate_files = n_certs; 2532 memcpy(options.certificate_files, 2533 certificate_files, sizeof(certificate_files)); 2534 memcpy(options.certificates, certificates, sizeof(certificates)); 2535 memcpy(options.certificate_file_userprovided, 2536 certificate_file_userprovided, 2537 sizeof(certificate_file_userprovided)); 2538 } 2539 2540 static void 2541 main_sigchld_handler(int sig) 2542 { 2543 int save_errno = errno; 2544 pid_t pid; 2545 int status; 2546 2547 while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || 2548 (pid == -1 && errno == EINTR)) 2549 ; 2550 errno = save_errno; 2551 } 2552