Branch data Line data Source code
1 : : /* $OpenBSD: ssh.c,v 1.401 2014/02/26 20:18:37 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 SSL 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/param.h>
52 : : #include <sys/socket.h>
53 : : #include <sys/wait.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 <unistd.h>
70 : :
71 : : #include <netinet/in.h>
72 : : #include <arpa/inet.h>
73 : :
74 : : #include <openssl/evp.h>
75 : : #include <openssl/err.h>
76 : : #include "openbsd-compat/openssl-compat.h"
77 : : #include "openbsd-compat/sys-queue.h"
78 : :
79 : : #include "xmalloc.h"
80 : : #include "ssh.h"
81 : : #include "ssh1.h"
82 : : #include "ssh2.h"
83 : : #include "canohost.h"
84 : : #include "compat.h"
85 : : #include "cipher.h"
86 : : #include "packet.h"
87 : : #include "buffer.h"
88 : : #include "channels.h"
89 : : #include "key.h"
90 : : #include "authfd.h"
91 : : #include "authfile.h"
92 : : #include "pathnames.h"
93 : : #include "dispatch.h"
94 : : #include "clientloop.h"
95 : : #include "log.h"
96 : : #include "readconf.h"
97 : : #include "sshconnect.h"
98 : : #include "misc.h"
99 : : #include "kex.h"
100 : : #include "mac.h"
101 : : #include "sshpty.h"
102 : : #include "match.h"
103 : : #include "msg.h"
104 : : #include "uidswap.h"
105 : : #include "roaming.h"
106 : : #include "version.h"
107 : :
108 : : #ifdef ENABLE_PKCS11
109 : : #include "ssh-pkcs11.h"
110 : : #endif
111 : :
112 : : extern char *__progname;
113 : :
114 : : /* Saves a copy of argv for setproctitle emulation */
115 : : #ifndef HAVE_SETPROCTITLE
116 : : static char **saved_av;
117 : : #endif
118 : :
119 : : /* Flag indicating whether debug mode is on. May be set on the command line. */
120 : : int debug_flag = 0;
121 : :
122 : : /* Flag indicating whether a tty should be requested */
123 : : int tty_flag = 0;
124 : :
125 : : /* don't exec a shell */
126 : : int no_shell_flag = 0;
127 : :
128 : : /*
129 : : * Flag indicating that nothing should be read from stdin. This can be set
130 : : * on the command line.
131 : : */
132 : : int stdin_null_flag = 0;
133 : :
134 : : /*
135 : : * Flag indicating that the current process should be backgrounded and
136 : : * a new slave launched in the foreground for ControlPersist.
137 : : */
138 : : int need_controlpersist_detach = 0;
139 : :
140 : : /* Copies of flags for ControlPersist foreground slave */
141 : : int ostdin_null_flag, ono_shell_flag, otty_flag, orequest_tty;
142 : :
143 : : /*
144 : : * Flag indicating that ssh should fork after authentication. This is useful
145 : : * so that the passphrase can be entered manually, and then ssh goes to the
146 : : * background.
147 : : */
148 : : int fork_after_authentication_flag = 0;
149 : :
150 : : /* forward stdio to remote host and port */
151 : : char *stdio_forward_host = NULL;
152 : : int stdio_forward_port = 0;
153 : :
154 : : /*
155 : : * General data structure for command line options and options configurable
156 : : * in configuration files. See readconf.h.
157 : : */
158 : : Options options;
159 : :
160 : : /* optional user configfile */
161 : : char *config = NULL;
162 : :
163 : : /*
164 : : * Name of the host we are connecting to. This is the name given on the
165 : : * command line, or the HostName specified for the user-supplied name in a
166 : : * configuration file.
167 : : */
168 : : char *host;
169 : :
170 : : /* socket address the host resolves to */
171 : : struct sockaddr_storage hostaddr;
172 : :
173 : : /* Private host keys. */
174 : : Sensitive sensitive_data;
175 : :
176 : : /* Original real UID. */
177 : : uid_t original_real_uid;
178 : : uid_t original_effective_uid;
179 : :
180 : : /* command to be executed */
181 : : Buffer command;
182 : :
183 : : /* Should we execute a command or invoke a subsystem? */
184 : : int subsystem_flag = 0;
185 : :
186 : : /* # of replies received for global requests */
187 : : static int remote_forward_confirms_received = 0;
188 : :
189 : : /* mux.c */
190 : : extern int muxserver_sock;
191 : : extern u_int muxclient_command;
192 : :
193 : : /* Prints a help message to the user. This function never returns. */
194 : :
195 : : static void
196 : 0 : usage(void)
197 : : {
198 : 0 : fprintf(stderr,
199 : : "usage: ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]\n"
200 : : " [-D [bind_address:]port] [-E log_file] [-e escape_char]\n"
201 : : " [-F configfile] [-I pkcs11] [-i identity_file]\n"
202 : : " [-L [bind_address:]port:host:hostport] [-l login_name] [-m mac_spec]\n"
203 : : " [-O ctl_cmd] [-o option] [-p port]\n"
204 : : " [-Q cipher | cipher-auth | mac | kex | key]\n"
205 : : " [-R [bind_address:]port:host:hostport] [-S ctl_path] [-W host:port]\n"
206 : : " [-w local_tun[:remote_tun]] [user@]hostname [command]\n"
207 : : );
208 : 0 : exit(255);
209 : : }
210 : :
211 : : static int ssh_session(void);
212 : : static int ssh_session2(void);
213 : : static void load_public_identity_files(void);
214 : : static void main_sigchld_handler(int);
215 : :
216 : : /* from muxclient.c */
217 : : void muxclient(const char *);
218 : : void muxserver_listen(void);
219 : :
220 : : /* ~/ expand a list of paths. NB. assumes path[n] is heap-allocated. */
221 : : static void
222 : 1498 : tilde_expand_paths(char **paths, u_int num_paths)
223 : : {
224 : : u_int i;
225 : : char *cp;
226 : :
227 [ + + ]: 2996 : for (i = 0; i < num_paths; i++) {
228 : 1498 : cp = tilde_expand_filename(paths[i], original_real_uid);
229 : 1498 : free(paths[i]);
230 : 1498 : paths[i] = cp;
231 : : }
232 : 1498 : }
233 : :
234 : : /*
235 : : * Attempt to resolve a host name / port to a set of addresses and
236 : : * optionally return any CNAMEs encountered along the way.
237 : : * Returns NULL on failure.
238 : : * NB. this function must operate with a options having undefined members.
239 : : */
240 : : static struct addrinfo *
241 : 82 : resolve_host(const char *name, int port, int logerr, char *cname, size_t clen)
242 : : {
243 : : char strport[NI_MAXSERV];
244 : : struct addrinfo hints, *res;
245 : 82 : int gaierr, loglevel = SYSLOG_LEVEL_DEBUG1;
246 : :
247 [ - + ]: 82 : if (port <= 0)
248 : 0 : port = default_ssh_port();
249 : :
250 : : snprintf(strport, sizeof strport, "%u", port);
251 : : memset(&hints, 0, sizeof(hints));
252 : 164 : hints.ai_family = options.address_family == -1 ?
253 [ + - ]: 82 : AF_UNSPEC : options.address_family;
254 : 82 : hints.ai_socktype = SOCK_STREAM;
255 [ + - ]: 82 : if (cname != NULL)
256 : 82 : hints.ai_flags = AI_CANONNAME;
257 [ - + ]: 82 : if ((gaierr = getaddrinfo(name, strport, &hints, &res)) != 0) {
258 [ # # ][ # # ]: 0 : if (logerr || (gaierr != EAI_NONAME && gaierr != EAI_NODATA))
259 : 0 : loglevel = SYSLOG_LEVEL_ERROR;
260 : 0 : do_log2(loglevel, "%s: Could not resolve hostname %.100s: %s",
261 : : __progname, name, ssh_gai_strerror(gaierr));
262 : 0 : return NULL;
263 : : }
264 [ + - ][ + - ]: 82 : if (cname != NULL && res->ai_canonname != NULL) {
265 [ - + ]: 82 : if (strlcpy(cname, res->ai_canonname, clen) >= clen) {
266 : 0 : error("%s: host \"%s\" cname \"%s\" too long (max %lu)",
267 : 0 : __func__, name, res->ai_canonname, (u_long)clen);
268 [ # # ]: 0 : if (clen > 0)
269 : 0 : *cname = '\0';
270 : : }
271 : : }
272 : 82 : return res;
273 : : }
274 : :
275 : : /*
276 : : * Check whether the cname is a permitted replacement for the hostname
277 : : * and perform the replacement if it is.
278 : : * NB. this function must operate with a options having undefined members.
279 : : */
280 : : static int
281 : 0 : check_follow_cname(char **namep, const char *cname)
282 : : {
283 : : int i;
284 : : struct allowed_cname *rule;
285 : :
286 [ # # ][ # # ]: 0 : if (*cname == '\0' || options.num_permitted_cnames == 0 ||
[ # # ]
287 : 0 : strcmp(*namep, cname) == 0)
288 : : return 0;
289 [ # # ]: 0 : if (options.canonicalize_hostname == SSH_CANONICALISE_NO)
290 : : return 0;
291 : : /*
292 : : * Don't attempt to canonicalize names that will be interpreted by
293 : : * a proxy unless the user specifically requests so.
294 : : */
295 [ # # ][ # # ]: 0 : if (!option_clear_or_none(options.proxy_command) &&
296 : 0 : options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS)
297 : : return 0;
298 : 0 : debug3("%s: check \"%s\" CNAME \"%s\"", __func__, *namep, cname);
299 [ # # ]: 0 : for (i = 0; i < options.num_permitted_cnames; i++) {
300 : 0 : rule = options.permitted_cnames + i;
301 [ # # ]: 0 : if (match_pattern_list(*namep, rule->source_list,
302 [ # # ]: 0 : strlen(rule->source_list), 1) != 1 ||
303 : 0 : match_pattern_list(cname, rule->target_list,
304 : 0 : strlen(rule->target_list), 1) != 1)
305 : 0 : continue;
306 : 0 : verbose("Canonicalized DNS aliased hostname "
307 : : "\"%s\" => \"%s\"", *namep, cname);
308 : 0 : free(*namep);
309 : 0 : *namep = xstrdup(cname);
310 : 0 : return 1;
311 : : }
312 : : return 0;
313 : : }
314 : :
315 : : /*
316 : : * Attempt to resolve the supplied hostname after applying the user's
317 : : * canonicalization rules. Returns the address list for the host or NULL
318 : : * if no name was found after canonicalization.
319 : : * NB. this function must operate with a options having undefined members.
320 : : */
321 : : static struct addrinfo *
322 : 0 : resolve_canonicalize(char **hostp, int port)
323 : : {
324 : : int i, ndots;
325 : : char *cp, *fullhost, cname_target[NI_MAXHOST];
326 : : struct addrinfo *addrs;
327 : :
328 [ # # ]: 0 : if (options.canonicalize_hostname == SSH_CANONICALISE_NO)
329 : : return NULL;
330 : :
331 : : /*
332 : : * Don't attempt to canonicalize names that will be interpreted by
333 : : * a proxy unless the user specifically requests so.
334 : : */
335 [ # # ][ # # ]: 0 : if (!option_clear_or_none(options.proxy_command) &&
336 : 0 : options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS)
337 : : return NULL;
338 : :
339 : : /* Don't apply canonicalization to sufficiently-qualified hostnames */
340 : 0 : ndots = 0;
341 [ # # ]: 0 : for (cp = *hostp; *cp != '\0'; cp++) {
342 [ # # ]: 0 : if (*cp == '.')
343 : 0 : ndots++;
344 : : }
345 [ # # ]: 0 : if (ndots > options.canonicalize_max_dots) {
346 : 0 : debug3("%s: not canonicalizing hostname \"%s\" (max dots %d)",
347 : : __func__, *hostp, options.canonicalize_max_dots);
348 : 0 : return NULL;
349 : : }
350 : : /* Attempt each supplied suffix */
351 [ # # ]: 0 : for (i = 0; i < options.num_canonical_domains; i++) {
352 : 0 : *cname_target = '\0';
353 : 0 : xasprintf(&fullhost, "%s.%s.", *hostp,
354 : : options.canonical_domains[i]);
355 : 0 : debug3("%s: attempting \"%s\" => \"%s\"", __func__,
356 : : *hostp, fullhost);
357 [ # # ]: 0 : if ((addrs = resolve_host(fullhost, port, 0,
358 : : cname_target, sizeof(cname_target))) == NULL) {
359 : 0 : free(fullhost);
360 : 0 : continue;
361 : : }
362 : : /* Remove trailing '.' */
363 : 0 : fullhost[strlen(fullhost) - 1] = '\0';
364 : : /* Follow CNAME if requested */
365 [ # # ]: 0 : if (!check_follow_cname(&fullhost, cname_target)) {
366 : 0 : debug("Canonicalized hostname \"%s\" => \"%s\"",
367 : : *hostp, fullhost);
368 : : }
369 : 0 : free(*hostp);
370 : 0 : *hostp = fullhost;
371 : 0 : return addrs;
372 : : }
373 [ # # ]: 0 : if (!options.canonicalize_fallback_local)
374 : 0 : fatal("%s: Could not resolve host \"%s\"", __progname, *hostp);
375 : 0 : debug2("%s: host %s not found in any suffix", __func__, *hostp);
376 : 0 : return NULL;
377 : : }
378 : :
379 : : /*
380 : : * Read per-user configuration file. Ignore the system wide config
381 : : * file if the user specifies a config file on the command line.
382 : : */
383 : : static void
384 : 2616 : process_config_files(struct passwd *pw)
385 : : {
386 : : char buf[MAXPATHLEN];
387 : : int r;
388 : :
389 [ + - ]: 2616 : if (config != NULL) {
390 [ + - - + ]: 5232 : if (strcasecmp(config, "none") != 0 &&
391 : 2616 : !read_config_file(config, pw, host, &options,
392 : : SSHCONF_USERCONF))
393 : 0 : fatal("Can't open user config file %.100s: "
394 : 0 : "%.100s", config, strerror(errno));
395 : : } else {
396 : 0 : r = snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir,
397 : : _PATH_SSH_USER_CONFFILE);
398 [ # # ]: 0 : if (r > 0 && (size_t)r < sizeof(buf))
399 : 0 : (void)read_config_file(buf, pw, host, &options,
400 : : SSHCONF_CHECKPERM|SSHCONF_USERCONF);
401 : :
402 : : /* Read systemwide configuration file after user config. */
403 : 0 : (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, host,
404 : : &options, 0);
405 : : }
406 : 2616 : }
407 : :
408 : : /*
409 : : * Main program for the ssh client.
410 : : */
411 : : int
412 : 1812 : main(int ac, char **av)
413 : : {
414 : : int i, r, opt, exit_status, use_syslog;
415 : : char *p, *cp, *line, *argv0, buf[MAXPATHLEN], *host_arg, *logfile;
416 : : char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
417 : : char cname[NI_MAXHOST];
418 : : struct stat st;
419 : : struct passwd *pw;
420 : : int timeout_ms;
421 : : extern int optind, optreset;
422 : : extern char *optarg;
423 : : Forward fwd;
424 : 1812 : struct addrinfo *addrs = NULL;
425 : :
426 : : /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
427 : 1812 : sanitise_stdfd();
428 : :
429 : 1812 : __progname = ssh_get_progname(av[0]);
430 : :
431 : : #ifndef HAVE_SETPROCTITLE
432 : : /* Prepare for later setproctitle emulation */
433 : : /* Save argv so it isn't clobbered by setproctitle() emulation */
434 : 1812 : saved_av = xcalloc(ac + 1, sizeof(*saved_av));
435 [ + + ]: 16740 : for (i = 0; i < ac; i++)
436 : 14928 : saved_av[i] = xstrdup(av[i]);
437 : 1812 : saved_av[i] = NULL;
438 : 1812 : compat_init_setproctitle(ac, av);
439 : 1812 : av = saved_av;
440 : : #endif
441 : :
442 : : /*
443 : : * Discard other fds that are hanging around. These can cause problem
444 : : * with backgrounded ssh processes started by ControlPersist.
445 : : */
446 : 1812 : closefrom(STDERR_FILENO + 1);
447 : :
448 : : /*
449 : : * Save the original real uid. It will be needed later (uid-swapping
450 : : * may clobber the real uid).
451 : : */
452 : 1812 : original_real_uid = getuid();
453 : 1812 : original_effective_uid = geteuid();
454 : :
455 : : /*
456 : : * Use uid-swapping to give up root privileges for the duration of
457 : : * option processing. We will re-instantiate the rights when we are
458 : : * ready to create the privileged port, and will permanently drop
459 : : * them when the port has been created (actually, when the connection
460 : : * has been made, as we may need to create the port several times).
461 : : */
462 [ - + ]: 1812 : PRIV_END;
463 : :
464 : : #ifdef HAVE_SETRLIMIT
465 : : /* If we are installed setuid root be careful to not drop core. */
466 [ - + ]: 1812 : if (original_real_uid != original_effective_uid) {
467 : : struct rlimit rlim;
468 : 0 : rlim.rlim_cur = rlim.rlim_max = 0;
469 [ # # ]: 0 : if (setrlimit(RLIMIT_CORE, &rlim) < 0)
470 : 0 : fatal("setrlimit failed: %.100s", strerror(errno));
471 : : }
472 : : #endif
473 : : /* Get user data. */
474 : 1812 : pw = getpwuid(original_real_uid);
475 [ - + ]: 1812 : if (!pw) {
476 : 0 : logit("No user exists for uid %lu", (u_long)original_real_uid);
477 : 0 : exit(255);
478 : : }
479 : : /* Take a copy of the returned structure. */
480 : 1812 : pw = pwcopy(pw);
481 : :
482 : : /*
483 : : * Set our umask to something reasonable, as some files are created
484 : : * with the default umask. This will make them world-readable but
485 : : * writable only by the owner, which is ok for all files for which we
486 : : * don't set the modes explicitly.
487 : : */
488 : 1812 : umask(022);
489 : :
490 : : /*
491 : : * Initialize option structure to indicate that no values have been
492 : : * set.
493 : : */
494 : 1812 : initialize_options(&options);
495 : :
496 : : /* Parse command-line arguments. */
497 : 1812 : host = NULL;
498 : 1812 : use_syslog = 0;
499 : 1812 : logfile = NULL;
500 : 1812 : argv0 = av[0];
501 : :
502 : : again:
503 [ + + ]: 9799 : while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx"
504 : : "ACD:E:F:I:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) {
505 [ + + - - : 7196 : switch (opt) {
+ + + - +
- - + - +
- + - - +
- - + - -
- + - + +
+ + - + +
+ - + - +
+ + - + -
- ]
506 : : case '1':
507 : 64 : options.protocol = SSH_PROTO_1;
508 : 64 : break;
509 : : case '2':
510 : 950 : options.protocol = SSH_PROTO_2;
511 : 950 : break;
512 : : case '4':
513 : 0 : options.address_family = AF_INET;
514 : 0 : break;
515 : : case '6':
516 : 0 : options.address_family = AF_INET6;
517 : 0 : break;
518 : : case 'n':
519 : 97 : stdin_null_flag = 1;
520 : 97 : break;
521 : : case 'f':
522 : 9 : fork_after_authentication_flag = 1;
523 : 9 : stdin_null_flag = 1;
524 : 9 : break;
525 : : case 'x':
526 : 1 : options.forward_x11 = 0;
527 : 1 : break;
528 : : case 'X':
529 : 0 : options.forward_x11 = 1;
530 : 0 : break;
531 : : case 'y':
532 : : use_syslog = 1;
533 : : break;
534 : : case 'E':
535 : 1346 : logfile = xstrdup(optarg);
536 : 7987 : break;
537 : : case 'Y':
538 : 0 : options.forward_x11 = 1;
539 : 0 : options.forward_x11_trusted = 1;
540 : 0 : break;
541 : : case 'g':
542 : 0 : options.gateway_ports = 1;
543 : 0 : break;
544 : : case 'O':
545 [ - + ]: 9 : if (stdio_forward_host != NULL)
546 : 0 : fatal("Cannot specify multiplexing "
547 : : "command with -W");
548 [ - + ]: 9 : else if (muxclient_command != 0)
549 : 0 : fatal("Multiplexing command already specified");
550 [ + + ]: 9 : if (strcmp(optarg, "check") == 0)
551 : 3 : muxclient_command = SSHMUX_COMMAND_ALIVE_CHECK;
552 [ + + ]: 6 : else if (strcmp(optarg, "forward") == 0)
553 : 2 : muxclient_command = SSHMUX_COMMAND_FORWARD;
554 [ + + ]: 4 : else if (strcmp(optarg, "exit") == 0)
555 : 1 : muxclient_command = SSHMUX_COMMAND_TERMINATE;
556 [ + + ]: 3 : else if (strcmp(optarg, "stop") == 0)
557 : 1 : muxclient_command = SSHMUX_COMMAND_STOP;
558 [ + - ]: 2 : else if (strcmp(optarg, "cancel") == 0)
559 : 2 : muxclient_command = SSHMUX_COMMAND_CANCEL_FWD;
560 : : else
561 : 0 : fatal("Invalid multiplex command.");
562 : : break;
563 : : case 'P': /* deprecated */
564 : 0 : options.use_privileged_port = 0;
565 : 0 : break;
566 : : case 'Q':
567 : 499 : cp = NULL;
568 [ + + ]: 499 : if (strcmp(optarg, "cipher") == 0)
569 : 2 : cp = cipher_alg_list('\n', 0);
570 [ + + ]: 497 : else if (strcmp(optarg, "cipher-auth") == 0)
571 : 471 : cp = cipher_alg_list('\n', 1);
572 [ + + ][ + - ]: 26 : else if (strcmp(optarg, "mac") == 0)
[ + - ][ + + ]
573 : 18 : cp = mac_alg_list('\n');
574 [ + - ][ + - ]: 8 : else if (strcmp(optarg, "kex") == 0)
[ + + ][ + + ]
575 : 5 : cp = kex_alg_list('\n');
576 [ + - ][ + - ]: 3 : else if (strcmp(optarg, "key") == 0)
[ + - ][ + + ]
577 : 1 : cp = key_alg_list(0, 0);
578 [ - + ]: 2 : else if (strcmp(optarg, "key-cert") == 0)
579 : 0 : cp = key_alg_list(1, 0);
580 [ + - ]: 2 : else if (strcmp(optarg, "key-plain") == 0)
581 : 2 : cp = key_alg_list(0, 1);
582 [ - + ]: 499 : if (cp == NULL)
583 : 0 : fatal("Unsupported query \"%s\"", optarg);
584 : : printf("%s\n", cp);
585 : 499 : free(cp);
586 : 499 : exit(0);
587 : : break;
588 : : case 'a':
589 : 0 : options.forward_agent = 0;
590 : 0 : break;
591 : : case 'A':
592 : 4 : options.forward_agent = 1;
593 : 4 : break;
594 : : case 'k':
595 : 0 : options.gss_deleg_creds = 0;
596 : 0 : break;
597 : : case 'K':
598 : 0 : options.gss_authentication = 1;
599 : 0 : options.gss_deleg_creds = 1;
600 : 0 : break;
601 : : case 'i':
602 [ - + ]: 342 : if (stat(optarg, &st) < 0) {
603 : 0 : fprintf(stderr, "Warning: Identity file %s "
604 : : "not accessible: %s.\n", optarg,
605 : : strerror(errno));
606 : : break;
607 : : }
608 : 342 : add_identity_file(&options, NULL, optarg, 1);
609 : 342 : break;
610 : : case 'I':
611 : : #ifdef ENABLE_PKCS11
612 : 0 : options.pkcs11_provider = xstrdup(optarg);
613 : : #else
614 : : fprintf(stderr, "no support for PKCS#11.\n");
615 : : #endif
616 : 0 : break;
617 : : case 't':
618 [ # # ]: 0 : if (options.request_tty == REQUEST_TTY_YES)
619 : 0 : options.request_tty = REQUEST_TTY_FORCE;
620 : : else
621 : 0 : options.request_tty = REQUEST_TTY_YES;
622 : : break;
623 : : case 'v':
624 [ + - ]: 75 : if (debug_flag == 0) {
625 : 75 : debug_flag = 1;
626 : 75 : options.log_level = SYSLOG_LEVEL_DEBUG1;
627 : : } else {
628 [ # # ]: 0 : if (options.log_level < SYSLOG_LEVEL_DEBUG3)
629 : 0 : options.log_level++;
630 : : }
631 : : break;
632 : : case 'V':
633 : 0 : fprintf(stderr, "%s, %s\n",
634 : : SSH_RELEASE, SSLeay_version(SSLEAY_VERSION));
635 [ # # ]: 0 : if (opt == 'V')
636 : 0 : exit(0);
637 : : break;
638 : : case 'w':
639 [ # # ]: 0 : if (options.tun_open == -1)
640 : 0 : options.tun_open = SSH_TUNMODE_DEFAULT;
641 : 0 : options.tun_local = a2tun(optarg, &options.tun_remote);
642 [ # # ]: 0 : if (options.tun_local == SSH_TUNID_ERR) {
643 : 0 : fprintf(stderr,
644 : : "Bad tun device '%s'\n", optarg);
645 : 0 : exit(255);
646 : : }
647 : : break;
648 : : case 'W':
649 [ # # ]: 0 : if (stdio_forward_host != NULL)
650 : 0 : fatal("stdio forward already specified");
651 [ # # ]: 0 : if (muxclient_command != 0)
652 : 0 : fatal("Cannot specify stdio forward with -O");
653 [ # # ]: 0 : if (parse_forward(&fwd, optarg, 1, 0)) {
654 : 0 : stdio_forward_host = fwd.listen_host;
655 : 0 : stdio_forward_port = fwd.listen_port;
656 : 0 : free(fwd.connect_host);
657 : : } else {
658 : 0 : fprintf(stderr,
659 : : "Bad stdio forwarding specification '%s'\n",
660 : : optarg);
661 : 0 : exit(255);
662 : : }
663 : 0 : options.request_tty = REQUEST_TTY_NO;
664 : 0 : no_shell_flag = 1;
665 : 0 : options.clear_forwardings = 1;
666 : 0 : options.exit_on_forward_failure = 1;
667 : 0 : break;
668 : : case 'q':
669 : 64 : options.log_level = SYSLOG_LEVEL_QUIET;
670 : 64 : break;
671 : : case 'e':
672 [ # # ][ # # ]: 0 : if (optarg[0] == '^' && optarg[2] == 0 &&
[ # # ]
673 [ # # ]: 0 : (u_char) optarg[1] >= 64 &&
674 : : (u_char) optarg[1] < 128)
675 : 0 : options.escape_char = (u_char) optarg[1] & 31;
676 [ # # ]: 0 : else if (strlen(optarg) == 1)
677 : 0 : options.escape_char = (u_char) optarg[0];
678 [ # # ]: 0 : else if (strcmp(optarg, "none") == 0)
679 : 0 : options.escape_char = SSH_ESCAPECHAR_NONE;
680 : : else {
681 : 0 : fprintf(stderr, "Bad escape character '%s'.\n",
682 : : optarg);
683 : 0 : exit(255);
684 : : }
685 : : break;
686 : : case 'c':
687 [ + + ]: 470 : if (ciphers_valid(optarg)) {
688 : : /* SSH2 only */
689 : 468 : options.ciphers = xstrdup(optarg);
690 : 468 : options.cipher = SSH_CIPHER_INVALID;
691 : : } else {
692 : : /* SSH1 only */
693 : 2 : options.cipher = cipher_number(optarg);
694 [ - + ]: 2 : if (options.cipher == -1) {
695 : 0 : fprintf(stderr,
696 : : "Unknown cipher type '%s'\n",
697 : : optarg);
698 : 0 : exit(255);
699 : : }
700 [ + + ]: 2 : if (options.cipher == SSH_CIPHER_3DES)
701 : 1 : options.ciphers = "3des-cbc";
702 [ + - ]: 1 : else if (options.cipher == SSH_CIPHER_BLOWFISH)
703 : 1 : options.ciphers = "blowfish-cbc";
704 : : else
705 : 0 : options.ciphers = (char *)-1;
706 : : }
707 : : break;
708 : : case 'm':
709 [ + - ]: 438 : if (mac_valid(optarg))
710 : 438 : options.macs = xstrdup(optarg);
711 : : else {
712 : 0 : fprintf(stderr, "Unknown mac type '%s'\n",
713 : : optarg);
714 : 0 : exit(255);
715 : : }
716 : 438 : break;
717 : : case 'M':
718 [ - + ]: 2 : if (options.control_master == SSHCTL_MASTER_YES)
719 : 0 : options.control_master = SSHCTL_MASTER_ASK;
720 : : else
721 : 2 : options.control_master = SSHCTL_MASTER_YES;
722 : : break;
723 : : case 'p':
724 : 56 : options.port = a2port(optarg);
725 [ + + ]: 56 : if (options.port <= 0) {
726 : 5 : fprintf(stderr, "Bad port '%s'\n", optarg);
727 : 5 : exit(255);
728 : : }
729 : : break;
730 : : case 'l':
731 : 0 : options.user = optarg;
732 : 0 : break;
733 : :
734 : : case 'L':
735 [ + - ]: 74 : if (parse_forward(&fwd, optarg, 0, 0))
736 : 74 : add_local_forward(&options, &fwd);
737 : : else {
738 : 0 : fprintf(stderr,
739 : : "Bad local forwarding specification '%s'\n",
740 : : optarg);
741 : 0 : exit(255);
742 : : }
743 : 74 : break;
744 : :
745 : : case 'R':
746 [ + - ]: 64 : if (parse_forward(&fwd, optarg, 0, 1)) {
747 : 64 : add_remote_forward(&options, &fwd);
748 : : } else {
749 : 0 : fprintf(stderr,
750 : : "Bad remote forwarding specification "
751 : : "'%s'\n", optarg);
752 : 0 : exit(255);
753 : : }
754 : 64 : break;
755 : :
756 : : case 'D':
757 [ + - ]: 1 : if (parse_forward(&fwd, optarg, 1, 0)) {
758 : 1 : add_local_forward(&options, &fwd);
759 : : } else {
760 : 0 : fprintf(stderr,
761 : : "Bad dynamic forwarding specification "
762 : : "'%s'\n", optarg);
763 : 0 : exit(255);
764 : : }
765 : 1 : break;
766 : :
767 : : case 'C':
768 : 0 : options.compression = 1;
769 : 0 : break;
770 : : case 'N':
771 : 2 : no_shell_flag = 1;
772 : 2 : options.request_tty = REQUEST_TTY_NO;
773 : 2 : break;
774 : : case 'T':
775 : 0 : options.request_tty = REQUEST_TTY_NO;
776 : 0 : break;
777 : : case 'o':
778 : 1290 : line = xstrdup(optarg);
779 [ - + ][ - + ]: 1290 : if (process_config_line(&options, pw, host ? host : "",
780 : : line, "command-line", 0, NULL, SSHCONF_USERCONF)
781 : : != 0)
782 : 0 : exit(255);
783 : 1290 : free(line);
784 : 1290 : break;
785 : : case 's':
786 : 1 : subsystem_flag = 1;
787 : 1 : break;
788 : : case 'S':
789 [ - + ]: 25 : if (options.control_path != NULL)
790 : 0 : free(options.control_path);
791 : 25 : options.control_path = xstrdup(optarg);
792 : 25 : break;
793 : : case 'b':
794 : 0 : options.bind_address = optarg;
795 : 0 : break;
796 : : case 'F':
797 : 1313 : config = optarg;
798 : 1313 : break;
799 : : default:
800 : 0 : usage();
801 : : }
802 : : }
803 : :
804 : 2603 : ac -= optind;
805 : 2603 : av += optind;
806 : :
807 [ + + ][ + + ]: 2603 : if (ac > 0 && !host) {
808 [ + + ]: 1308 : if (strrchr(*av, '@')) {
809 : 2 : p = xstrdup(*av);
810 : 2 : cp = strrchr(p, '@');
811 [ - + ]: 2 : if (cp == NULL || cp == p)
812 : 0 : usage();
813 : 2 : options.user = p;
814 : 2 : *cp = '\0';
815 : 2 : host = xstrdup(++cp);
816 : : } else
817 : 1306 : host = xstrdup(*av);
818 [ + + ]: 1308 : if (ac > 1) {
819 : 1295 : optind = optreset = 1;
820 : 1295 : goto again;
821 : : }
822 : 13 : ac--, av++;
823 : : }
824 : :
825 : : /* Check that we got a host name. */
826 [ - + ]: 1308 : if (!host)
827 : 0 : usage();
828 : :
829 : 1308 : host_arg = xstrdup(host);
830 : :
831 : 1308 : OpenSSL_add_all_algorithms();
832 : 1308 : ERR_load_crypto_strings();
833 : :
834 : : /* Initialize the command to execute on remote host. */
835 : 1308 : buffer_init(&command);
836 : :
837 : : /*
838 : : * Save the command to execute on the remote host in a buffer. There
839 : : * is no limit on the length of the command, except by the maximum
840 : : * packet size. Also sets the tty flag if there is no command.
841 : : */
842 [ + + ]: 1308 : if (!ac) {
843 : : /* No command specified - execute shell on a tty. */
844 [ - + ]: 15 : if (subsystem_flag) {
845 : 0 : fprintf(stderr,
846 : : "You must specify a subsystem to invoke.\n");
847 : 0 : usage();
848 : : }
849 : : } else {
850 : : /* A command has been specified. Store it into the buffer. */
851 [ + + ]: 2956 : for (i = 0; i < ac; i++) {
852 [ + + ]: 1663 : if (i)
853 : 370 : buffer_append(&command, " ", 1);
854 : 1663 : buffer_append(&command, av[i], strlen(av[i]));
855 : : }
856 : : }
857 : :
858 : : /* Cannot fork to background if no command. */
859 [ + + ][ - + ]: 1308 : if (fork_after_authentication_flag && buffer_len(&command) == 0 &&
[ # # ]
860 : 0 : !no_shell_flag)
861 : 0 : fatal("Cannot fork into background without a command "
862 : : "to execute.");
863 : :
864 : : /*
865 : : * Initialize "log" output. Since we are the client all output
866 : : * goes to stderr unless otherwise specified by -y or -E.
867 : : */
868 [ - + ]: 1308 : if (use_syslog && logfile != NULL)
869 : 0 : fatal("Can't specify both -y and -E");
870 [ + - ]: 1308 : if (logfile != NULL) {
871 : 1308 : log_redirect_stderr_to(logfile);
872 : 1308 : free(logfile);
873 : : }
874 [ + + ]: 1308 : log_init(argv0,
875 : 1308 : options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level,
876 : : SYSLOG_FACILITY_USER, !use_syslog);
877 : :
878 [ + + ]: 1308 : if (debug_flag)
879 : 75 : logit("%s, %s", SSH_VERSION, SSLeay_version(SSLEAY_VERSION));
880 : :
881 : : /* Parse the configuration files */
882 : 1308 : process_config_files(pw);
883 : :
884 : : /* Hostname canonicalisation needs a few options filled. */
885 : 1308 : fill_default_options_for_canonicalization(&options);
886 : :
887 : : /* If the user has replaced the hostname then take it into use now */
888 [ + - ]: 1308 : if (options.hostname != NULL) {
889 : : /* NB. Please keep in sync with readconf.c:match_cfg_line() */
890 : 1308 : cp = percent_expand(options.hostname,
891 : : "h", host, (char *)NULL);
892 : 1308 : free(host);
893 : 1308 : host = cp;
894 : : }
895 : :
896 : : /* If canonicalization requested then try to apply it */
897 : 1308 : lowercase(host);
898 [ - + ]: 1308 : if (options.canonicalize_hostname != SSH_CANONICALISE_NO)
899 : 0 : addrs = resolve_canonicalize(&host, options.port);
900 : :
901 : : /*
902 : : * If CanonicalizePermittedCNAMEs have been specified but
903 : : * other canonicalization did not happen (by not being requested
904 : : * or by failing with fallback) then the hostname may still be changed
905 : : * as a result of CNAME following.
906 : : *
907 : : * Try to resolve the bare hostname name using the system resolver's
908 : : * usual search rules and then apply the CNAME follow rules.
909 : : *
910 : : * Skip the lookup if a ProxyCommand is being used unless the user
911 : : * has specifically requested canonicalisation for this case via
912 : : * CanonicalizeHostname=always
913 : : */
914 [ + - ]: 1308 : if (addrs == NULL && options.num_permitted_cnames != 0 &&
[ - + # # ]
915 [ # # ]: 0 : (option_clear_or_none(options.proxy_command) ||
916 : 0 : options.canonicalize_hostname == SSH_CANONICALISE_ALWAYS)) {
917 [ # # ]: 0 : if ((addrs = resolve_host(host, options.port, 1,
918 : : cname, sizeof(cname))) == NULL)
919 : 0 : cleanup_exit(255); /* resolve_host logs the error */
920 : 0 : check_follow_cname(&host, cname);
921 : : }
922 : :
923 : : /*
924 : : * If the target hostname has changed as a result of canonicalisation
925 : : * then re-parse the configuration files as new stanzas may match.
926 : : */
927 [ + - ]: 1308 : if (strcasecmp(host_arg, host) != 0) {
928 : 1308 : debug("Hostname has changed; re-reading configuration");
929 : 1308 : process_config_files(pw);
930 : : }
931 : :
932 : : /* Fill configuration defaults. */
933 : 1308 : fill_default_options(&options);
934 : :
935 [ - + ]: 1308 : if (options.port == 0)
936 : 0 : options.port = default_ssh_port();
937 : 1308 : channel_set_af(options.address_family);
938 : :
939 : : /* Tidy and check options */
940 [ + - ]: 1308 : if (options.host_key_alias != NULL)
941 : 1308 : lowercase(options.host_key_alias);
942 [ + + ][ - + ]: 2509 : if (options.proxy_command != NULL &&
943 [ - + ][ # # ]: 1201 : strcmp(options.proxy_command, "-") == 0 &&
944 : 0 : options.proxy_use_fdpass)
945 : 0 : fatal("ProxyCommand=- and ProxyUseFDPass are incompatible");
946 : : #ifndef HAVE_CYGWIN
947 [ + - ]: 1308 : if (original_effective_uid != 0)
948 : 1308 : options.use_privileged_port = 0;
949 : : #endif
950 : :
951 : : /* reinit */
952 : 1308 : log_init(argv0, options.log_level, SYSLOG_FACILITY_USER, !use_syslog);
953 : :
954 [ - + ]: 1308 : if (options.request_tty == REQUEST_TTY_YES ||
955 : : options.request_tty == REQUEST_TTY_FORCE)
956 : 0 : tty_flag = 1;
957 : :
958 : : /* Allocate a tty by default if no command specified. */
959 [ + + ]: 1308 : if (buffer_len(&command) == 0)
960 : 15 : tty_flag = options.request_tty != REQUEST_TTY_NO;
961 : :
962 : : /* Force no tty */
963 [ + + ][ + + ]: 1308 : if (options.request_tty == REQUEST_TTY_NO || muxclient_command != 0)
964 : 11 : tty_flag = 0;
965 : : /* Do not allocate a tty if stdin is not a tty. */
966 [ + + ][ + + ]: 1308 : if ((!isatty(fileno(stdin)) || stdin_null_flag) &&
[ + - ]
967 : 217 : options.request_tty != REQUEST_TTY_FORCE) {
968 [ - + ]: 217 : if (tty_flag)
969 : 0 : logit("Pseudo-terminal will not be allocated because "
970 : : "stdin is not a terminal.");
971 : 217 : tty_flag = 0;
972 : : }
973 : :
974 : 1308 : seed_rng();
975 : :
976 [ - + ]: 1308 : if (options.user == NULL)
977 : 0 : options.user = xstrdup(pw->pw_name);
978 : :
979 [ - + ]: 1308 : if (gethostname(thishost, sizeof(thishost)) == -1)
980 : 0 : fatal("gethostname: %s", strerror(errno));
981 : 1308 : strlcpy(shorthost, thishost, sizeof(shorthost));
982 : 2616 : shorthost[strcspn(thishost, ".")] = '\0';
983 : 1308 : snprintf(portstr, sizeof(portstr), "%d", options.port);
984 : :
985 [ + + ]: 1308 : if (options.local_command != NULL) {
986 : 4 : debug3("expanding LocalCommand: %s", options.local_command);
987 : 4 : cp = options.local_command;
988 : 4 : options.local_command = percent_expand(cp, "d", pw->pw_dir,
989 : : "h", host, "l", thishost, "n", host_arg, "r", options.user,
990 : : "p", portstr, "u", pw->pw_name, "L", shorthost,
991 : : (char *)NULL);
992 : 4 : debug3("expanded LocalCommand: %s", options.local_command);
993 : 4 : free(cp);
994 : : }
995 : :
996 [ + + ]: 1308 : if (options.control_path != NULL) {
997 : 27 : cp = tilde_expand_filename(options.control_path,
998 : : original_real_uid);
999 : 27 : free(options.control_path);
1000 : 27 : options.control_path = percent_expand(cp, "h", host,
1001 : : "l", thishost, "n", host_arg, "r", options.user,
1002 : : "p", portstr, "u", pw->pw_name, "L", shorthost,
1003 : : (char *)NULL);
1004 : 27 : free(cp);
1005 : : }
1006 [ + + ][ - + ]: 1308 : if (muxclient_command != 0 && options.control_path == NULL)
1007 : 0 : fatal("No ControlPath specified for \"-O\" command");
1008 [ + + ]: 1308 : if (options.control_path != NULL)
1009 : 27 : muxclient(options.control_path);
1010 : :
1011 : : /*
1012 : : * If hostname canonicalisation was not enabled, then we may not
1013 : : * have yet resolved the hostname. Do so now.
1014 : : */
1015 [ + - ][ + + ]: 1283 : if (addrs == NULL && options.proxy_command == NULL) {
1016 [ - + ]: 82 : if ((addrs = resolve_host(host, options.port, 1,
1017 : : cname, sizeof(cname))) == NULL)
1018 : 0 : cleanup_exit(255); /* resolve_host logs the error */
1019 : : }
1020 : :
1021 : 1283 : timeout_ms = options.connection_timeout * 1000;
1022 : :
1023 : : /* Open a connection to the remote host. */
1024 [ + + ]: 1283 : if (ssh_connect(host, addrs, &hostaddr, options.port,
1025 : : options.address_family, options.connection_attempts,
1026 : : &timeout_ms, options.tcp_keep_alive,
1027 : : options.use_privileged_port) != 0)
1028 : 6 : exit(255);
1029 : :
1030 [ + + ]: 749 : if (addrs != NULL)
1031 : 76 : freeaddrinfo(addrs);
1032 : :
1033 : 749 : packet_set_timeout(options.server_alive_interval,
1034 : : options.server_alive_count_max);
1035 : :
1036 [ - + ]: 749 : if (timeout_ms > 0)
1037 : 0 : debug3("timeout: %d ms remain after connect", timeout_ms);
1038 : :
1039 : : /*
1040 : : * If we successfully made the connection, load the host private key
1041 : : * in case we will need it later for combined rsa-rhosts
1042 : : * authentication. This must be done before releasing extra
1043 : : * privileges, because the file is only readable by root.
1044 : : * If we cannot access the private keys, load the public keys
1045 : : * instead and try to execute the ssh-keysign helper instead.
1046 : : */
1047 : 749 : sensitive_data.nkeys = 0;
1048 : 749 : sensitive_data.keys = NULL;
1049 : 749 : sensitive_data.external_keysign = 0;
1050 [ + - ][ - + ]: 749 : if (options.rhosts_rsa_authentication ||
1051 : 749 : options.hostbased_authentication) {
1052 : 0 : sensitive_data.nkeys = 9;
1053 : 0 : sensitive_data.keys = xcalloc(sensitive_data.nkeys,
1054 : : sizeof(Key));
1055 [ # # ]: 0 : for (i = 0; i < sensitive_data.nkeys; i++)
1056 : 0 : sensitive_data.keys[i] = NULL;
1057 : :
1058 [ # # ]: 0 : PRIV_START;
1059 : 0 : sensitive_data.keys[0] = key_load_private_type(KEY_RSA1,
1060 : : _PATH_HOST_KEY_FILE, "", NULL, NULL);
1061 : 0 : sensitive_data.keys[1] = key_load_private_cert(KEY_DSA,
1062 : : _PATH_HOST_DSA_KEY_FILE, "", NULL);
1063 : : #ifdef OPENSSL_HAS_ECC
1064 : 0 : sensitive_data.keys[2] = key_load_private_cert(KEY_ECDSA,
1065 : : _PATH_HOST_ECDSA_KEY_FILE, "", NULL);
1066 : : #endif
1067 : 0 : sensitive_data.keys[3] = key_load_private_cert(KEY_RSA,
1068 : : _PATH_HOST_RSA_KEY_FILE, "", NULL);
1069 : 0 : sensitive_data.keys[4] = key_load_private_cert(KEY_ED25519,
1070 : : _PATH_HOST_ED25519_KEY_FILE, "", NULL);
1071 : 0 : sensitive_data.keys[5] = key_load_private_type(KEY_DSA,
1072 : : _PATH_HOST_DSA_KEY_FILE, "", NULL, NULL);
1073 : : #ifdef OPENSSL_HAS_ECC
1074 : 0 : sensitive_data.keys[6] = key_load_private_type(KEY_ECDSA,
1075 : : _PATH_HOST_ECDSA_KEY_FILE, "", NULL, NULL);
1076 : : #endif
1077 : 0 : sensitive_data.keys[7] = key_load_private_type(KEY_RSA,
1078 : : _PATH_HOST_RSA_KEY_FILE, "", NULL, NULL);
1079 : 0 : sensitive_data.keys[8] = key_load_private_type(KEY_ED25519,
1080 : : _PATH_HOST_ED25519_KEY_FILE, "", NULL, NULL);
1081 [ # # ]: 0 : PRIV_END;
1082 : :
1083 [ # # ][ # # ]: 0 : if (options.hostbased_authentication == 1 &&
1084 [ # # ]: 0 : sensitive_data.keys[0] == NULL &&
1085 [ # # ]: 0 : sensitive_data.keys[5] == NULL &&
1086 [ # # ]: 0 : sensitive_data.keys[6] == NULL &&
1087 [ # # ]: 0 : sensitive_data.keys[7] == NULL &&
1088 : 0 : sensitive_data.keys[8] == NULL) {
1089 : 0 : sensitive_data.keys[1] = key_load_cert(
1090 : : _PATH_HOST_DSA_KEY_FILE);
1091 : : #ifdef OPENSSL_HAS_ECC
1092 : 0 : sensitive_data.keys[2] = key_load_cert(
1093 : : _PATH_HOST_ECDSA_KEY_FILE);
1094 : : #endif
1095 : 0 : sensitive_data.keys[3] = key_load_cert(
1096 : : _PATH_HOST_RSA_KEY_FILE);
1097 : 0 : sensitive_data.keys[4] = key_load_cert(
1098 : : _PATH_HOST_ED25519_KEY_FILE);
1099 : 0 : sensitive_data.keys[5] = key_load_public(
1100 : : _PATH_HOST_DSA_KEY_FILE, NULL);
1101 : : #ifdef OPENSSL_HAS_ECC
1102 : 0 : sensitive_data.keys[6] = key_load_public(
1103 : : _PATH_HOST_ECDSA_KEY_FILE, NULL);
1104 : : #endif
1105 : 0 : sensitive_data.keys[7] = key_load_public(
1106 : : _PATH_HOST_RSA_KEY_FILE, NULL);
1107 : 0 : sensitive_data.keys[8] = key_load_public(
1108 : : _PATH_HOST_ED25519_KEY_FILE, NULL);
1109 : 0 : sensitive_data.external_keysign = 1;
1110 : : }
1111 : : }
1112 : : /*
1113 : : * Get rid of any extra privileges that we may have. We will no
1114 : : * longer need them. Also, extra privileges could make it very hard
1115 : : * to read identity files and other non-world-readable files from the
1116 : : * user's home directory if it happens to be on a NFS volume where
1117 : : * root is mapped to nobody.
1118 : : */
1119 [ - + ]: 749 : if (original_effective_uid == 0) {
1120 [ # # ]: 0 : PRIV_START;
1121 : 0 : permanently_set_uid(pw);
1122 : : }
1123 : :
1124 : : /*
1125 : : * Now that we are back to our own permissions, create ~/.ssh
1126 : : * directory if it doesn't already exist.
1127 : : */
1128 [ - + ]: 749 : if (config == NULL) {
1129 [ # # ]: 0 : r = snprintf(buf, sizeof buf, "%s%s%s", pw->pw_dir,
1130 [ # # ]: 0 : strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR);
1131 [ # # # # ]: 0 : if (r > 0 && (size_t)r < sizeof(buf) && stat(buf, &st) < 0) {
1132 : : #ifdef WITH_SELINUX
1133 : : ssh_selinux_setfscreatecon(buf);
1134 : : #endif
1135 [ # # ]: 0 : if (mkdir(buf, 0700) < 0)
1136 : 0 : error("Could not create directory '%.200s'.",
1137 : : buf);
1138 : : #ifdef WITH_SELINUX
1139 : : ssh_selinux_setfscreatecon(NULL);
1140 : : #endif
1141 : : }
1142 : : }
1143 : : /* load options.identity_files */
1144 : 749 : load_public_identity_files();
1145 : :
1146 : : /* Expand ~ in known host file names. */
1147 : 749 : tilde_expand_paths(options.system_hostfiles,
1148 : : options.num_system_hostfiles);
1149 : 749 : tilde_expand_paths(options.user_hostfiles, options.num_user_hostfiles);
1150 : :
1151 : 749 : signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */
1152 : 749 : signal(SIGCHLD, main_sigchld_handler);
1153 : :
1154 : : /* Log into the remote system. Never returns if the login fails. */
1155 : 749 : ssh_login(&sensitive_data, host, (struct sockaddr *)&hostaddr,
1156 : 749 : options.port, pw, timeout_ms);
1157 : :
1158 [ + + ]: 749 : if (packet_connection_is_on_socket()) {
1159 : 76 : verbose("Authenticated to %s ([%s]:%d).", host,
1160 : : get_remote_ipaddr(), get_remote_port());
1161 : : } else {
1162 : 673 : verbose("Authenticated to %s (via proxy).", host);
1163 : : }
1164 : :
1165 : : /* We no longer need the private host keys. Clear them now. */
1166 [ - + ]: 749 : if (sensitive_data.nkeys != 0) {
1167 [ # # ]: 0 : for (i = 0; i < sensitive_data.nkeys; i++) {
1168 [ # # ]: 0 : if (sensitive_data.keys[i] != NULL) {
1169 : : /* Destroys contents safely */
1170 : 0 : debug3("clear hostkey %d", i);
1171 : 0 : key_free(sensitive_data.keys[i]);
1172 : 0 : sensitive_data.keys[i] = NULL;
1173 : : }
1174 : : }
1175 : 749 : free(sensitive_data.keys);
1176 : : }
1177 [ + + ]: 3995 : for (i = 0; i < options.num_identity_files; i++) {
1178 : 3246 : free(options.identity_files[i]);
1179 : 3246 : options.identity_files[i] = NULL;
1180 [ + + ]: 3246 : if (options.identity_keys[i]) {
1181 : 1578 : key_free(options.identity_keys[i]);
1182 : 1578 : options.identity_keys[i] = NULL;
1183 : : }
1184 : : }
1185 : :
1186 [ + + ]: 749 : exit_status = compat20 ? ssh_session2() : ssh_session();
1187 : 749 : packet_close();
1188 : :
1189 [ + + ][ + - ]: 749 : if (options.control_path != NULL && muxserver_sock != -1)
1190 : 1 : unlink(options.control_path);
1191 : :
1192 : : /* Kill ProxyCommand if it is running. */
1193 : 749 : ssh_kill_proxy_command();
1194 : :
1195 : 749 : return exit_status;
1196 : : }
1197 : :
1198 : : static void
1199 : 0 : control_persist_detach(void)
1200 : : {
1201 : : pid_t pid;
1202 : : int devnull;
1203 : :
1204 : 0 : debug("%s: backgrounding master process", __func__);
1205 : :
1206 : : /*
1207 : : * master (current process) into the background, and make the
1208 : : * foreground process a client of the backgrounded master.
1209 : : */
1210 [ # # # ]: 0 : switch ((pid = fork())) {
1211 : : case -1:
1212 : 0 : fatal("%s: fork: %s", __func__, strerror(errno));
1213 : : case 0:
1214 : : /* Child: master process continues mainloop */
1215 : : break;
1216 : : default:
1217 : : /* Parent: set up mux slave to connect to backgrounded master */
1218 : 0 : debug2("%s: background process is %ld", __func__, (long)pid);
1219 : 0 : stdin_null_flag = ostdin_null_flag;
1220 : 0 : options.request_tty = orequest_tty;
1221 : 0 : tty_flag = otty_flag;
1222 : 0 : close(muxserver_sock);
1223 : 0 : muxserver_sock = -1;
1224 : 0 : options.control_master = SSHCTL_MASTER_NO;
1225 : 0 : muxclient(options.control_path);
1226 : : /* muxclient() doesn't return on success. */
1227 : 0 : fatal("Failed to connect to new control master");
1228 : : }
1229 [ # # ]: 0 : if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
1230 : 0 : error("%s: open(\"/dev/null\"): %s", __func__,
1231 : 0 : strerror(errno));
1232 : : } else {
1233 [ # # # # ]: 0 : if (dup2(devnull, STDIN_FILENO) == -1 ||
1234 : 0 : dup2(devnull, STDOUT_FILENO) == -1)
1235 : 0 : error("%s: dup2: %s", __func__, strerror(errno));
1236 [ # # ]: 0 : if (devnull > STDERR_FILENO)
1237 : 0 : close(devnull);
1238 : : }
1239 : 0 : daemon(1, 1);
1240 : 0 : setproctitle("%s [mux]", options.control_path);
1241 : 0 : }
1242 : :
1243 : : /* Do fork() after authentication. Used by "ssh -f" */
1244 : : static void
1245 : 9 : fork_postauth(void)
1246 : : {
1247 [ - + ]: 9 : if (need_controlpersist_detach)
1248 : 0 : control_persist_detach();
1249 : 9 : debug("forking to background");
1250 : 9 : fork_after_authentication_flag = 0;
1251 [ - + ]: 9 : if (daemon(1, 1) < 0)
1252 : 0 : fatal("daemon() failed: %.200s", strerror(errno));
1253 : 9 : }
1254 : :
1255 : : /* Callback for remote forward global requests */
1256 : : static void
1257 : 19 : ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
1258 : : {
1259 : 19 : Forward *rfwd = (Forward *)ctxt;
1260 : :
1261 : : /* XXX verbose() on failure? */
1262 [ + + ]: 19 : debug("remote forward %s for: listen %d, connect %s:%d",
1263 : : type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
1264 : : rfwd->listen_port, rfwd->connect_host, rfwd->connect_port);
1265 [ - + ]: 19 : if (rfwd->listen_port == 0) {
1266 [ # # ]: 0 : if (type == SSH2_MSG_REQUEST_SUCCESS) {
1267 : 0 : rfwd->allocated_port = packet_get_int();
1268 : 0 : logit("Allocated port %u for remote forward to %s:%d",
1269 : : rfwd->allocated_port,
1270 : : rfwd->connect_host, rfwd->connect_port);
1271 : 0 : channel_update_permitted_opens(rfwd->handle,
1272 : : rfwd->allocated_port);
1273 : : } else {
1274 : 0 : channel_update_permitted_opens(rfwd->handle, -1);
1275 : : }
1276 : : }
1277 : :
1278 [ + + ]: 19 : if (type == SSH2_MSG_REQUEST_FAILURE) {
1279 [ - + ]: 6 : if (options.exit_on_forward_failure)
1280 : 0 : fatal("Error: remote port forwarding failed for "
1281 : : "listen port %d", rfwd->listen_port);
1282 : : else
1283 : 6 : logit("Warning: remote port forwarding failed for "
1284 : : "listen port %d", rfwd->listen_port);
1285 : : }
1286 [ + + ]: 19 : if (++remote_forward_confirms_received == options.num_remote_forwards) {
1287 : 5 : debug("All remote forwarding requests processed");
1288 [ - + ]: 5 : if (fork_after_authentication_flag)
1289 : 0 : fork_postauth();
1290 : : }
1291 : 19 : }
1292 : :
1293 : : static void
1294 : 0 : client_cleanup_stdio_fwd(int id, void *arg)
1295 : : {
1296 : 0 : debug("stdio forwarding: done");
1297 : 0 : cleanup_exit(0);
1298 : : }
1299 : :
1300 : : static void
1301 : 749 : ssh_init_stdio_forwarding(void)
1302 : : {
1303 : : Channel *c;
1304 : : int in, out;
1305 : :
1306 [ - + ]: 749 : if (stdio_forward_host == NULL)
1307 : 749 : return;
1308 [ # # ]: 0 : if (!compat20)
1309 : 0 : fatal("stdio forwarding require Protocol 2");
1310 : :
1311 : 0 : debug3("%s: %s:%d", __func__, stdio_forward_host, stdio_forward_port);
1312 : :
1313 [ # # ][ # # ]: 0 : if ((in = dup(STDIN_FILENO)) < 0 ||
1314 : : (out = dup(STDOUT_FILENO)) < 0)
1315 : 0 : fatal("channel_connect_stdio_fwd: dup() in/out failed");
1316 [ # # ]: 0 : if ((c = channel_connect_stdio_fwd(stdio_forward_host,
1317 : : stdio_forward_port, in, out)) == NULL)
1318 : 0 : fatal("%s: channel_connect_stdio_fwd failed", __func__);
1319 : 0 : channel_register_cleanup(c->self, client_cleanup_stdio_fwd, 0);
1320 : : }
1321 : :
1322 : : static void
1323 : 749 : ssh_init_forwarding(void)
1324 : : {
1325 : 749 : int success = 0;
1326 : : int i;
1327 : :
1328 : : /* Initiate local TCP/IP port forwardings. */
1329 [ + + ]: 790 : for (i = 0; i < options.num_local_forwards; i++) {
1330 [ + - ]: 82 : debug("Local connections to %.200s:%d forwarded to remote "
1331 : : "address %.200s:%d",
1332 : 41 : (options.local_forwards[i].listen_host == NULL) ?
1333 [ + - ]: 41 : (options.gateway_ports ? "*" : "LOCALHOST") :
1334 : : options.local_forwards[i].listen_host,
1335 : : options.local_forwards[i].listen_port,
1336 : : options.local_forwards[i].connect_host,
1337 : 41 : options.local_forwards[i].connect_port);
1338 : 41 : success += channel_setup_local_fwd_listener(
1339 : 41 : options.local_forwards[i].listen_host,
1340 : 41 : options.local_forwards[i].listen_port,
1341 : 41 : options.local_forwards[i].connect_host,
1342 : 41 : options.local_forwards[i].connect_port,
1343 : : options.gateway_ports);
1344 : : }
1345 [ + + ][ - + ]: 749 : if (i > 0 && success != i && options.exit_on_forward_failure)
1346 : 0 : fatal("Could not request local forwarding.");
1347 [ + + ]: 749 : if (i > 0 && success == 0)
1348 : 749 : error("Could not request local forwarding.");
1349 : :
1350 : : /* Initiate remote TCP/IP port forwardings. */
1351 [ + + ]: 783 : for (i = 0; i < options.num_remote_forwards; i++) {
1352 [ - + ]: 34 : debug("Remote connections from %.200s:%d forwarded to "
1353 : : "local address %.200s:%d",
1354 : 34 : (options.remote_forwards[i].listen_host == NULL) ?
1355 : : "LOCALHOST" : options.remote_forwards[i].listen_host,
1356 : : options.remote_forwards[i].listen_port,
1357 : : options.remote_forwards[i].connect_host,
1358 : 34 : options.remote_forwards[i].connect_port);
1359 : 34 : options.remote_forwards[i].handle =
1360 : 34 : channel_request_remote_forwarding(
1361 : 34 : options.remote_forwards[i].listen_host,
1362 : 34 : options.remote_forwards[i].listen_port,
1363 : 34 : options.remote_forwards[i].connect_host,
1364 : 34 : options.remote_forwards[i].connect_port);
1365 [ + + ]: 34 : if (options.remote_forwards[i].handle < 0) {
1366 [ - + ]: 1 : if (options.exit_on_forward_failure)
1367 : 0 : fatal("Could not request remote forwarding.");
1368 : : else
1369 : 1 : logit("Warning: Could not request remote "
1370 : : "forwarding.");
1371 : : } else {
1372 : 33 : client_register_global_confirm(ssh_confirm_remote_forward,
1373 : : &options.remote_forwards[i]);
1374 : : }
1375 : : }
1376 : :
1377 : : /* Initiate tunnel forwarding. */
1378 [ - + ]: 749 : if (options.tun_open != SSH_TUNMODE_NO) {
1379 [ # # ]: 0 : if (client_request_tun_fwd(options.tun_open,
1380 : : options.tun_local, options.tun_remote) == -1) {
1381 [ # # ]: 0 : if (options.exit_on_forward_failure)
1382 : 0 : fatal("Could not request tunnel forwarding.");
1383 : : else
1384 : 0 : error("Could not request tunnel forwarding.");
1385 : : }
1386 : : }
1387 : 749 : }
1388 : :
1389 : : static void
1390 : 747 : check_agent_present(void)
1391 : : {
1392 [ + + ]: 747 : if (options.forward_agent) {
1393 : : /* Clear agent forwarding if we don't have an agent. */
1394 [ - + ]: 4 : if (!ssh_agent_present())
1395 : 0 : options.forward_agent = 0;
1396 : : }
1397 : 747 : }
1398 : :
1399 : : static int
1400 : 61 : ssh_session(void)
1401 : : {
1402 : : int type;
1403 : 61 : int interactive = 0;
1404 : 61 : int have_tty = 0;
1405 : : struct winsize ws;
1406 : : char *cp;
1407 : : const char *display;
1408 : :
1409 : : /* Enable compression if requested. */
1410 [ - + ]: 61 : if (options.compression) {
1411 : 0 : debug("Requesting compression at level %d.",
1412 : : options.compression_level);
1413 : :
1414 [ # # ]: 0 : if (options.compression_level < 1 ||
1415 : : options.compression_level > 9)
1416 : 0 : fatal("Compression level must be from 1 (fast) to "
1417 : : "9 (slow, best).");
1418 : :
1419 : : /* Send the request. */
1420 : 0 : packet_start(SSH_CMSG_REQUEST_COMPRESSION);
1421 : 0 : packet_put_int(options.compression_level);
1422 : 0 : packet_send();
1423 : 0 : packet_write_wait();
1424 : 0 : type = packet_read();
1425 [ # # ]: 0 : if (type == SSH_SMSG_SUCCESS)
1426 : 0 : packet_start_compression(options.compression_level);
1427 [ # # ]: 0 : else if (type == SSH_SMSG_FAILURE)
1428 : 0 : logit("Warning: Remote host refused compression.");
1429 : : else
1430 : 0 : packet_disconnect("Protocol error waiting for "
1431 : : "compression response.");
1432 : : }
1433 : : /* Allocate a pseudo tty if appropriate. */
1434 [ - + ]: 61 : if (tty_flag) {
1435 : 0 : debug("Requesting pty.");
1436 : :
1437 : : /* Start the packet. */
1438 : 0 : packet_start(SSH_CMSG_REQUEST_PTY);
1439 : :
1440 : : /* Store TERM in the packet. There is no limit on the
1441 : : length of the string. */
1442 : 0 : cp = getenv("TERM");
1443 [ # # ]: 0 : if (!cp)
1444 : 0 : cp = "";
1445 : 0 : packet_put_cstring(cp);
1446 : :
1447 : : /* Store window size in the packet. */
1448 [ # # ]: 0 : if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
1449 : : memset(&ws, 0, sizeof(ws));
1450 : 0 : packet_put_int((u_int)ws.ws_row);
1451 : 0 : packet_put_int((u_int)ws.ws_col);
1452 : 0 : packet_put_int((u_int)ws.ws_xpixel);
1453 : 0 : packet_put_int((u_int)ws.ws_ypixel);
1454 : :
1455 : : /* Store tty modes in the packet. */
1456 : 0 : tty_make_modes(fileno(stdin), NULL);
1457 : :
1458 : : /* Send the packet, and wait for it to leave. */
1459 : 0 : packet_send();
1460 : 0 : packet_write_wait();
1461 : :
1462 : : /* Read response from the server. */
1463 : 0 : type = packet_read();
1464 [ # # ]: 0 : if (type == SSH_SMSG_SUCCESS) {
1465 : : interactive = 1;
1466 : : have_tty = 1;
1467 [ # # ]: 0 : } else if (type == SSH_SMSG_FAILURE)
1468 : 0 : logit("Warning: Remote host failed or refused to "
1469 : : "allocate a pseudo tty.");
1470 : : else
1471 : 0 : packet_disconnect("Protocol error waiting for pty "
1472 : : "request response.");
1473 : : }
1474 : : /* Request X11 forwarding if enabled and DISPLAY is set. */
1475 : 61 : display = getenv("DISPLAY");
1476 [ - + ][ # # ]: 61 : if (options.forward_x11 && display != NULL) {
1477 : : char *proto, *data;
1478 : : /* Get reasonable local authentication information. */
1479 : 0 : client_x11_get_proto(display, options.xauth_location,
1480 : 0 : options.forward_x11_trusted,
1481 : 0 : options.forward_x11_timeout,
1482 : : &proto, &data);
1483 : : /* Request forwarding with authentication spoofing. */
1484 : 0 : debug("Requesting X11 forwarding with authentication "
1485 : : "spoofing.");
1486 : 0 : x11_request_forwarding_with_spoofing(0, display, proto,
1487 : : data, 0);
1488 : : /* Read response from the server. */
1489 : 0 : type = packet_read();
1490 [ # # ]: 0 : if (type == SSH_SMSG_SUCCESS) {
1491 : : interactive = 1;
1492 [ # # ]: 0 : } else if (type == SSH_SMSG_FAILURE) {
1493 : 0 : logit("Warning: Remote host denied X11 forwarding.");
1494 : : } else {
1495 : 0 : packet_disconnect("Protocol error waiting for X11 "
1496 : : "forwarding");
1497 : : }
1498 : : }
1499 : : /* Tell the packet module whether this is an interactive session. */
1500 : 61 : packet_set_interactive(interactive,
1501 : : options.ip_qos_interactive, options.ip_qos_bulk);
1502 : :
1503 : : /* Request authentication agent forwarding if appropriate. */
1504 : 61 : check_agent_present();
1505 : :
1506 [ + + ]: 61 : if (options.forward_agent) {
1507 : 2 : debug("Requesting authentication agent forwarding.");
1508 : 2 : auth_request_forwarding();
1509 : :
1510 : : /* Read response from the server. */
1511 : 2 : type = packet_read();
1512 [ - + ]: 2 : packet_check_eom();
1513 [ - + ]: 2 : if (type != SSH_SMSG_SUCCESS)
1514 : 0 : logit("Warning: Remote host denied authentication agent forwarding.");
1515 : : }
1516 : :
1517 : : /* Initiate port forwardings. */
1518 : 61 : ssh_init_stdio_forwarding();
1519 : 61 : ssh_init_forwarding();
1520 : :
1521 : : /* Execute a local command */
1522 [ + + ][ + - ]: 61 : if (options.local_command != NULL &&
1523 : 2 : options.permit_local_command)
1524 : 2 : ssh_local_cmd(options.local_command);
1525 : :
1526 : : /*
1527 : : * If requested and we are not interested in replies to remote
1528 : : * forwarding requests, then let ssh continue in the background.
1529 : : */
1530 [ + + ]: 61 : if (fork_after_authentication_flag) {
1531 [ - + ][ # # ]: 4 : if (options.exit_on_forward_failure &&
1532 : 0 : options.num_remote_forwards > 0) {
1533 : 0 : debug("deferring postauth fork until remote forward "
1534 : : "confirmation received");
1535 : : } else
1536 : 4 : fork_postauth();
1537 : : }
1538 : :
1539 : : /*
1540 : : * If a command was specified on the command line, execute the
1541 : : * command now. Otherwise request the server to start a shell.
1542 : : */
1543 [ + - ]: 61 : if (buffer_len(&command) > 0) {
1544 : 61 : int len = buffer_len(&command);
1545 [ - + ]: 61 : if (len > 900)
1546 : 0 : len = 900;
1547 : 61 : debug("Sending command: %.*s", len,
1548 : 61 : (u_char *)buffer_ptr(&command));
1549 : 61 : packet_start(SSH_CMSG_EXEC_CMD);
1550 : 61 : packet_put_string(buffer_ptr(&command), buffer_len(&command));
1551 : 61 : packet_send();
1552 : 61 : packet_write_wait();
1553 : : } else {
1554 : 0 : debug("Requesting shell.");
1555 : 0 : packet_start(SSH_CMSG_EXEC_SHELL);
1556 : 0 : packet_send();
1557 : 0 : packet_write_wait();
1558 : : }
1559 : :
1560 : : /* Enter the interactive session. */
1561 [ - + ]: 61 : return client_loop(have_tty, tty_flag ?
1562 : : options.escape_char : SSH_ESCAPECHAR_NONE, 0);
1563 : : }
1564 : :
1565 : : /* request pty/x11/agent/tcpfwd/shell for channel */
1566 : : static void
1567 : 686 : ssh_session2_setup(int id, int success, void *arg)
1568 : : {
1569 : : extern char **environ;
1570 : : const char *display;
1571 : 686 : int interactive = tty_flag;
1572 : :
1573 [ + - ]: 686 : if (!success)
1574 : 686 : return; /* No need for error message, channels code sens one */
1575 : :
1576 : 686 : display = getenv("DISPLAY");
1577 [ - + ][ # # ]: 686 : if (options.forward_x11 && display != NULL) {
1578 : : char *proto, *data;
1579 : : /* Get reasonable local authentication information. */
1580 : 0 : client_x11_get_proto(display, options.xauth_location,
1581 : 0 : options.forward_x11_trusted,
1582 : 0 : options.forward_x11_timeout, &proto, &data);
1583 : : /* Request forwarding with authentication spoofing. */
1584 : 0 : debug("Requesting X11 forwarding with authentication "
1585 : : "spoofing.");
1586 : 0 : x11_request_forwarding_with_spoofing(id, display, proto,
1587 : : data, 1);
1588 : 0 : client_expect_confirm(id, "X11 forwarding", CONFIRM_WARN);
1589 : : /* XXX exit_on_forward_failure */
1590 : 0 : interactive = 1;
1591 : : }
1592 : :
1593 : 686 : check_agent_present();
1594 [ + + ]: 686 : if (options.forward_agent) {
1595 : 2 : debug("Requesting authentication agent forwarding.");
1596 : 2 : channel_request_start(id, "auth-agent-req@openssh.com", 0);
1597 : 2 : packet_send();
1598 : : }
1599 : :
1600 : : /* Tell the packet module whether this is an interactive session. */
1601 : 686 : packet_set_interactive(interactive,
1602 : : options.ip_qos_interactive, options.ip_qos_bulk);
1603 : :
1604 : 686 : client_session2_setup(id, tty_flag, subsystem_flag, getenv("TERM"),
1605 : : NULL, fileno(stdin), &command, environ);
1606 : : }
1607 : :
1608 : : /* open new channel for a session */
1609 : : static int
1610 : 686 : ssh_session2_open(void)
1611 : : {
1612 : : Channel *c;
1613 : : int window, packetmax, in, out, err;
1614 : :
1615 [ + + ]: 686 : if (stdin_null_flag) {
1616 : 16 : in = open(_PATH_DEVNULL, O_RDONLY);
1617 : : } else {
1618 : 670 : in = dup(STDIN_FILENO);
1619 : : }
1620 : 686 : out = dup(STDOUT_FILENO);
1621 : 686 : err = dup(STDERR_FILENO);
1622 : :
1623 [ + - ][ - + ]: 686 : if (in < 0 || out < 0 || err < 0)
1624 : 0 : fatal("dup() in/out/err failed");
1625 : :
1626 : : /* enable nonblocking unless tty */
1627 [ + + ]: 686 : if (!isatty(in))
1628 : 111 : set_nonblock(in);
1629 [ + + ]: 686 : if (!isatty(out))
1630 : 181 : set_nonblock(out);
1631 [ + + ]: 686 : if (!isatty(err))
1632 : 172 : set_nonblock(err);
1633 : :
1634 : 686 : window = CHAN_SES_WINDOW_DEFAULT;
1635 : 686 : packetmax = CHAN_SES_PACKET_DEFAULT;
1636 [ - + ]: 686 : if (tty_flag) {
1637 : 0 : window >>= 1;
1638 : 0 : packetmax >>= 1;
1639 : : }
1640 : 686 : c = channel_new(
1641 : : "session", SSH_CHANNEL_OPENING, in, out, err,
1642 : : window, packetmax, CHAN_EXTENDED_WRITE,
1643 : : "client-session", /*nonblock*/0);
1644 : :
1645 : 686 : debug3("ssh_session2_open: channel_new: %d", c->self);
1646 : :
1647 : 686 : channel_send_open(c->self);
1648 [ + - ]: 686 : if (!no_shell_flag)
1649 : 686 : channel_register_open_confirm(c->self,
1650 : : ssh_session2_setup, NULL);
1651 : :
1652 : 686 : return c->self;
1653 : : }
1654 : :
1655 : : static int
1656 : 688 : ssh_session2(void)
1657 : : {
1658 : 688 : int id = -1;
1659 : :
1660 : : /* XXX should be pre-session */
1661 [ + - ]: 688 : if (!options.control_persist)
1662 : 688 : ssh_init_stdio_forwarding();
1663 : 688 : ssh_init_forwarding();
1664 : :
1665 : : /* Start listening for multiplex clients */
1666 : 688 : muxserver_listen();
1667 : :
1668 : : /*
1669 : : * If we are in control persist mode and have a working mux listen
1670 : : * socket, then prepare to background ourselves and have a foreground
1671 : : * client attach as a control slave.
1672 : : * NB. we must save copies of the flags that we override for
1673 : : * the backgrounding, since we defer attachment of the slave until
1674 : : * after the connection is fully established (in particular,
1675 : : * async rfwd replies have been received for ExitOnForwardFailure).
1676 : : */
1677 [ - + ][ # # ]: 688 : if (options.control_persist && muxserver_sock != -1) {
1678 : 0 : ostdin_null_flag = stdin_null_flag;
1679 : 0 : ono_shell_flag = no_shell_flag;
1680 : 0 : orequest_tty = options.request_tty;
1681 : 0 : otty_flag = tty_flag;
1682 : 0 : stdin_null_flag = 1;
1683 : 0 : no_shell_flag = 1;
1684 : 0 : tty_flag = 0;
1685 [ # # ]: 0 : if (!fork_after_authentication_flag)
1686 : 0 : need_controlpersist_detach = 1;
1687 : 0 : fork_after_authentication_flag = 1;
1688 : : }
1689 : : /*
1690 : : * ControlPersist mux listen socket setup failed, attempt the
1691 : : * stdio forward setup that we skipped earlier.
1692 : : */
1693 [ - + ][ # # ]: 688 : if (options.control_persist && muxserver_sock == -1)
1694 : 0 : ssh_init_stdio_forwarding();
1695 : :
1696 [ + + ][ - + ]: 688 : if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN))
1697 : 686 : id = ssh_session2_open();
1698 : : else {
1699 : 2 : packet_set_interactive(
1700 : 2 : options.control_master == SSHCTL_MASTER_NO,
1701 : : options.ip_qos_interactive, options.ip_qos_bulk);
1702 : : }
1703 : :
1704 : : /* If we don't expect to open a new session, then disallow it */
1705 [ + + ][ + - ]: 688 : if (options.control_master == SSHCTL_MASTER_NO &&
1706 : 686 : (datafellows & SSH_NEW_OPENSSH)) {
1707 : 686 : debug("Requesting no-more-sessions@openssh.com");
1708 : 686 : packet_start(SSH2_MSG_GLOBAL_REQUEST);
1709 : 686 : packet_put_cstring("no-more-sessions@openssh.com");
1710 : 686 : packet_put_char(0);
1711 : 686 : packet_send();
1712 : : }
1713 : :
1714 : : /* Execute a local command */
1715 [ + + ][ + - ]: 688 : if (options.local_command != NULL &&
1716 : 2 : options.permit_local_command)
1717 : 2 : ssh_local_cmd(options.local_command);
1718 : :
1719 : : /*
1720 : : * If requested and we are not interested in replies to remote
1721 : : * forwarding requests, then let ssh continue in the background.
1722 : : */
1723 [ + + ]: 688 : if (fork_after_authentication_flag) {
1724 [ + + ][ - + ]: 5 : if (options.exit_on_forward_failure &&
1725 : 1 : options.num_remote_forwards > 0) {
1726 : 0 : debug("deferring postauth fork until remote forward "
1727 : : "confirmation received");
1728 : : } else
1729 : 5 : fork_postauth();
1730 : : }
1731 : :
1732 [ - + ]: 688 : if (options.use_roaming)
1733 : 0 : request_roaming();
1734 : :
1735 [ - + ]: 688 : return client_loop(tty_flag, tty_flag ?
1736 : : options.escape_char : SSH_ESCAPECHAR_NONE, id);
1737 : : }
1738 : :
1739 : : static void
1740 : 749 : load_public_identity_files(void)
1741 : : {
1742 : : char *filename, *cp, thishost[NI_MAXHOST];
1743 : 749 : char *pwdir = NULL, *pwname = NULL;
1744 : 749 : int i = 0;
1745 : : Key *public;
1746 : : struct passwd *pw;
1747 : : u_int n_ids;
1748 : : char *identity_files[SSH_MAX_IDENTITY_FILES];
1749 : : Key *identity_keys[SSH_MAX_IDENTITY_FILES];
1750 : : #ifdef ENABLE_PKCS11
1751 : : Key **keys;
1752 : : int nkeys;
1753 : : #endif /* PKCS11 */
1754 : :
1755 : 749 : n_ids = 0;
1756 : : memset(identity_files, 0, sizeof(identity_files));
1757 : : memset(identity_keys, 0, sizeof(identity_keys));
1758 : :
1759 : : #ifdef ENABLE_PKCS11
1760 [ - + ][ # # ]: 749 : if (options.pkcs11_provider != NULL &&
1761 [ # # ]: 0 : options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
1762 [ # # ]: 0 : (pkcs11_init(!options.batch_mode) == 0) &&
1763 : 0 : (nkeys = pkcs11_add_provider(options.pkcs11_provider, NULL,
1764 : : &keys)) > 0) {
1765 [ # # ]: 0 : for (i = 0; i < nkeys; i++) {
1766 [ # # ]: 0 : if (n_ids >= SSH_MAX_IDENTITY_FILES) {
1767 : 0 : key_free(keys[i]);
1768 : 0 : continue;
1769 : : }
1770 : 0 : identity_keys[n_ids] = keys[i];
1771 : 0 : identity_files[n_ids] =
1772 : 0 : xstrdup(options.pkcs11_provider); /* XXX */
1773 : 0 : n_ids++;
1774 : : }
1775 : 0 : free(keys);
1776 : : }
1777 : : #endif /* ENABLE_PKCS11 */
1778 [ - + ]: 749 : if ((pw = getpwuid(original_real_uid)) == NULL)
1779 : 0 : fatal("load_public_identity_files: getpwuid failed");
1780 : 749 : pwname = xstrdup(pw->pw_name);
1781 : 749 : pwdir = xstrdup(pw->pw_dir);
1782 [ + - ]: 749 : if (gethostname(thishost, sizeof(thishost)) == -1)
1783 : 0 : fatal("load_public_identity_files: gethostname: %s",
1784 : 0 : strerror(errno));
1785 [ + + ]: 3849 : for (i = 0; i < options.num_identity_files; i++) {
1786 [ + - ][ - + ]: 3100 : if (n_ids >= SSH_MAX_IDENTITY_FILES ||
1787 : 3100 : strcasecmp(options.identity_files[i], "none") == 0) {
1788 : 0 : free(options.identity_files[i]);
1789 : 0 : continue;
1790 : : }
1791 : 3100 : cp = tilde_expand_filename(options.identity_files[i],
1792 : : original_real_uid);
1793 : 3100 : filename = percent_expand(cp, "d", pwdir,
1794 : : "u", pwname, "l", thishost, "h", host,
1795 : : "r", options.user, (char *)NULL);
1796 : 3100 : free(cp);
1797 : 3100 : public = key_load_public(filename, NULL);
1798 [ + - ]: 3100 : debug("identity file %s type %d", filename,
1799 : : public ? public->type : -1);
1800 : 3100 : free(options.identity_files[i]);
1801 : 3100 : identity_files[n_ids] = filename;
1802 : 3100 : identity_keys[n_ids] = public;
1803 : :
1804 [ - + ]: 3100 : if (++n_ids >= SSH_MAX_IDENTITY_FILES)
1805 : 0 : continue;
1806 : :
1807 : : /* Try to add the certificate variant too */
1808 : 3100 : xasprintf(&cp, "%s-cert", filename);
1809 : 3100 : public = key_load_public(cp, NULL);
1810 [ + + ]: 3100 : debug("identity file %s type %d", cp,
1811 : : public ? public->type : -1);
1812 [ + + ]: 3100 : if (public == NULL) {
1813 : 2954 : free(cp);
1814 : 2954 : continue;
1815 : : }
1816 [ - + ]: 146 : if (!key_is_cert(public)) {
1817 : 0 : debug("%s: key %s type %s is not a certificate",
1818 : : __func__, cp, key_type(public));
1819 : 0 : key_free(public);
1820 : 0 : free(cp);
1821 : 0 : continue;
1822 : : }
1823 : 146 : identity_keys[n_ids] = public;
1824 : : /* point to the original path, most likely the private key */
1825 : 146 : identity_files[n_ids] = xstrdup(filename);
1826 : 146 : n_ids++;
1827 : : }
1828 : 749 : options.num_identity_files = n_ids;
1829 : : memcpy(options.identity_files, identity_files, sizeof(identity_files));
1830 : : memcpy(options.identity_keys, identity_keys, sizeof(identity_keys));
1831 : :
1832 : 749 : explicit_bzero(pwname, strlen(pwname));
1833 : 749 : free(pwname);
1834 : 749 : explicit_bzero(pwdir, strlen(pwdir));
1835 : 749 : free(pwdir);
1836 : 749 : }
1837 : :
1838 : : static void
1839 : 389 : main_sigchld_handler(int sig)
1840 : : {
1841 : 389 : int save_errno = errno;
1842 : : pid_t pid;
1843 : : int status;
1844 : :
1845 [ + + ][ + - ]: 778 : while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
1846 [ - + ]: 389 : (pid < 0 && errno == EINTR))
1847 : : ;
1848 : :
1849 : 389 : signal(sig, main_sigchld_handler);
1850 : 389 : errno = save_errno;
1851 : 389 : }
|