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