1 /* $OpenBSD: clientloop.c,v 1.408 2024/07/01 04:31:17 djm Exp $ */
3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
6 * The main loop for the interactive session (client side).
8 * As far as I am concerned, the code I have written for this software
9 * can be used freely for any purpose. Any derived versions of this
10 * software must be clearly marked as such, and if the derived work is
11 * incompatible with the protocol description in the RFC file, it must be
12 * called by a name other than "ssh" or "Secure Shell".
15 * Copyright (c) 1999 Theo de Raadt. All rights reserved.
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution.
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 * SSH2 support added by Markus Friedl.
39 * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved.
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
50 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
51 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
52 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
53 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
54 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
55 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
56 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
57 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
58 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
59 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64 #include <sys/types.h>
65 #include <sys/ioctl.h>
66 #ifdef HAVE_SYS_STAT_H
67 # include <sys/stat.h>
69 #ifdef HAVE_SYS_TIME_H
70 # include <sys/time.h>
72 #include <sys/socket.h>
92 #include "openbsd-compat/sys-queue.h"
100 #include "dispatch.h"
104 #include "myproposal.h"
107 #include "readconf.h"
108 #include "clientloop.h"
109 #include "sshconnect.h"
111 #include "atomicio.h"
116 #include "hostfile.h"
118 /* Permitted RSA signature algorithms for UpdateHostkeys proofs */
119 #define HOSTKEY_PROOF_RSA_ALGS "rsa-sha2-512,rsa-sha2-256"
121 /* Uncertainty (in percent) of keystroke timing intervals */
122 #define SSH_KEYSTROKE_TIMING_FUZZ 10
125 extern Options options
;
128 extern int muxserver_sock
; /* XXX use mux_client_cleanup() instead */
131 * Name of the host we are connecting to. This is the name given on the
132 * command line, or the Hostname specified for the user-supplied name in a
133 * configuration file.
138 * If this field is not NULL, the ForwardAgent socket is this path and different
139 * instead of SSH_AUTH_SOCK.
141 extern char *forward_agent_sock_path
;
144 * Flag to indicate that we have received a window change signal which has
145 * not yet been processed. This will cause a message indicating the new
146 * window size to be sent to the server a little later. This is volatile
147 * because this is updated in a signal handler.
149 static volatile sig_atomic_t received_window_change_signal
= 0;
150 static volatile sig_atomic_t received_signal
= 0;
152 /* Time when backgrounded control master using ControlPersist should exit */
153 static time_t control_persist_exit_time
= 0;
155 /* Common data for the client loop code. */
156 volatile sig_atomic_t quit_pending
; /* Set non-zero to quit the loop. */
157 static int last_was_cr
; /* Last character was a newline. */
158 static int exit_status
; /* Used to store the command exit status. */
159 static int connection_in
; /* Connection to server (input). */
160 static int connection_out
; /* Connection to server (output). */
161 static int need_rekeying
; /* Set to non-zero if rekeying is requested. */
162 static int session_closed
; /* In SSH2: login session closed. */
163 static time_t x11_refuse_time
; /* If >0, refuse x11 opens after this time. */
164 static time_t server_alive_time
; /* Time to do server_alive_check */
165 static int hostkeys_update_complete
;
166 static int session_setup_complete
;
168 static void client_init_dispatch(struct ssh
*ssh
);
169 int session_ident
= -1;
171 /* Track escape per proto2 channel */
172 struct escape_filter_ctx
{
177 /* Context for channel confirmation replies */
178 struct channel_reply_ctx
{
179 const char *request_type
;
181 enum confirm_action action
;
184 /* Global request success/failure callbacks */
185 /* XXX move to struct ssh? */
186 struct global_confirm
{
187 TAILQ_ENTRY(global_confirm
) entry
;
188 global_confirm_cb
*cb
;
192 TAILQ_HEAD(global_confirms
, global_confirm
);
193 static struct global_confirms global_confirms
=
194 TAILQ_HEAD_INITIALIZER(global_confirms
);
196 static void quit_message(const char *fmt
, ...)
197 __attribute__((__format__ (printf
, 1, 2)));
200 quit_message(const char *fmt
, ...)
204 xasprintf(&fmt2
, "%s\r\n", fmt
);
207 xvasprintf(&msg
, fmt2
, args
);
210 (void)atomicio(vwrite
, STDERR_FILENO
, msg
, strlen(msg
));
218 * Signal handler for the window change signal (SIGWINCH). This just sets a
219 * flag indicating that the window has changed.
222 window_change_handler(int sig
)
224 received_window_change_signal
= 1;
228 * Signal handler for signals that cause the program to terminate. These
229 * signals must be trapped to restore terminal modes.
232 signal_handler(int sig
)
234 received_signal
= sig
;
239 * Sets control_persist_exit_time to the absolute time when the
240 * backgrounded control master should exit due to expiry of the
241 * ControlPersist timeout. Sets it to 0 if we are not a backgrounded
242 * control master process, or if there is no ControlPersist timeout.
245 set_control_persist_exit_time(struct ssh
*ssh
)
247 if (muxserver_sock
== -1 || !options
.control_persist
248 || options
.control_persist_timeout
== 0) {
249 /* not using a ControlPersist timeout */
250 control_persist_exit_time
= 0;
251 } else if (channel_still_open(ssh
)) {
252 /* some client connections are still open */
253 if (control_persist_exit_time
> 0)
254 debug2_f("cancel scheduled exit");
255 control_persist_exit_time
= 0;
256 } else if (control_persist_exit_time
<= 0) {
257 /* a client connection has recently closed */
258 control_persist_exit_time
= monotime() +
259 (time_t)options
.control_persist_timeout
;
260 debug2_f("schedule exit in %d seconds",
261 options
.control_persist_timeout
);
263 /* else we are already counting down to the timeout */
266 #define SSH_X11_VALID_DISPLAY_CHARS ":/.-_"
268 client_x11_display_valid(const char *display
)
275 dlen
= strlen(display
);
276 for (i
= 0; i
< dlen
; i
++) {
277 if (!isalnum((u_char
)display
[i
]) &&
278 strchr(SSH_X11_VALID_DISPLAY_CHARS
, display
[i
]) == NULL
) {
279 debug("Invalid character '%c' in DISPLAY", display
[i
]);
286 #define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1"
287 #define X11_TIMEOUT_SLACK 60
289 client_x11_get_proto(struct ssh
*ssh
, const char *display
,
290 const char *xauth_path
, u_int trusted
, u_int timeout
,
291 char **_proto
, char **_data
)
293 char *cmd
, line
[512], xdisplay
[512];
294 char xauthfile
[PATH_MAX
], xauthdir
[PATH_MAX
];
295 static char proto
[512], data
[512];
297 int got_data
= 0, generated
= 0, do_unlink
= 0, r
;
299 u_int now
, x11_timeout_real
;
303 proto
[0] = data
[0] = xauthfile
[0] = xauthdir
[0] = '\0';
305 if (!client_x11_display_valid(display
)) {
307 logit("DISPLAY \"%s\" invalid; disabling X11 forwarding",
311 if (xauth_path
!= NULL
&& stat(xauth_path
, &st
) == -1) {
312 debug("No xauth program.");
316 if (xauth_path
!= NULL
) {
318 * Handle FamilyLocal case where $DISPLAY does
319 * not match an authorization entry. For this we
320 * just try "xauth list unix:displaynum.screennum".
321 * XXX: "localhost" match to determine FamilyLocal
324 if (strncmp(display
, "localhost:", 10) == 0) {
325 if ((r
= snprintf(xdisplay
, sizeof(xdisplay
), "unix:%s",
326 display
+ 10)) < 0 ||
327 (size_t)r
>= sizeof(xdisplay
)) {
328 error_f("display name too long");
335 * Generate an untrusted X11 auth cookie.
337 * The authentication cookie should briefly outlive
338 * ssh's willingness to forward X11 connections to
339 * avoid nasty fail-open behaviour in the X server.
341 mktemp_proto(xauthdir
, sizeof(xauthdir
));
342 if (mkdtemp(xauthdir
) == NULL
) {
343 error_f("mkdtemp: %s", strerror(errno
));
347 if ((r
= snprintf(xauthfile
, sizeof(xauthfile
),
348 "%s/xauthfile", xauthdir
)) < 0 ||
349 (size_t)r
>= sizeof(xauthfile
)) {
350 error_f("xauthfile path too long");
356 /* auth doesn't time out */
357 xasprintf(&cmd
, "%s -f %s generate %s %s "
359 xauth_path
, xauthfile
, display
,
360 SSH_X11_PROTO
, _PATH_DEVNULL
);
362 /* Add some slack to requested expiry */
363 if (timeout
< UINT_MAX
- X11_TIMEOUT_SLACK
)
364 x11_timeout_real
= timeout
+
367 /* Don't overflow on long timeouts */
368 x11_timeout_real
= UINT_MAX
;
370 xasprintf(&cmd
, "%s -f %s generate %s %s "
371 "untrusted timeout %u 2>%s",
372 xauth_path
, xauthfile
, display
,
373 SSH_X11_PROTO
, x11_timeout_real
,
376 debug2_f("xauth command: %s", cmd
);
378 if (timeout
!= 0 && x11_refuse_time
== 0) {
379 now
= monotime() + 1;
380 if (SSH_TIME_T_MAX
- timeout
< now
)
381 x11_refuse_time
= SSH_TIME_T_MAX
;
383 x11_refuse_time
= now
+ timeout
;
384 channel_set_x11_refuse_time(ssh
,
387 if (system(cmd
) == 0)
393 * When in untrusted mode, we read the cookie only if it was
394 * successfully generated as an untrusted one in the step
397 if (trusted
|| generated
) {
399 "%s %s%s list %s 2>" _PATH_DEVNULL
,
401 generated
? "-f " : "" ,
402 generated
? xauthfile
: "",
404 debug2("x11_get_proto: %s", cmd
);
406 if (f
&& fgets(line
, sizeof(line
), f
) &&
407 sscanf(line
, "%*s %511s %511s", proto
, data
) == 2)
420 /* Don't fall back to fake X11 data for untrusted forwarding */
421 if (!trusted
&& !got_data
) {
422 error("Warning: untrusted X11 forwarding setup failed: "
423 "xauth key data not generated");
428 * If we didn't get authentication data, just make up some
429 * data. The forwarding code will check the validity of the
430 * response anyway, and substitute this data. The X11
431 * server, however, will ignore this fake data and use
432 * whatever authentication mechanisms it was using otherwise
433 * for the local connection.
439 logit("Warning: No xauth data; "
440 "using fake authentication data for X11 forwarding.");
441 strlcpy(proto
, SSH_X11_PROTO
, sizeof proto
);
442 arc4random_buf(rnd
, sizeof(rnd
));
443 for (i
= 0; i
< sizeof(rnd
); i
++) {
444 snprintf(data
+ 2 * i
, sizeof data
- 2 * i
, "%02x",
453 * Checks if the client window has changed, and sends a packet about it to
454 * the server if so. The actual change is detected elsewhere (by a software
455 * interrupt on Unix); this just checks the flag and sends a message if
460 client_check_window_change(struct ssh
*ssh
)
462 if (!received_window_change_signal
)
464 received_window_change_signal
= 0;
466 channel_send_window_changes(ssh
);
470 client_global_request_reply(int type
, u_int32_t seq
, struct ssh
*ssh
)
472 struct global_confirm
*gc
;
474 if ((gc
= TAILQ_FIRST(&global_confirms
)) == NULL
)
477 gc
->cb(ssh
, type
, seq
, gc
->ctx
);
478 if (--gc
->ref_count
<= 0) {
479 TAILQ_REMOVE(&global_confirms
, gc
, entry
);
480 freezero(gc
, sizeof(*gc
));
483 ssh_packet_set_alive_timeouts(ssh
, 0);
488 schedule_server_alive_check(void)
490 if (options
.server_alive_interval
> 0)
491 server_alive_time
= monotime() + options
.server_alive_interval
;
495 server_alive_check(struct ssh
*ssh
)
499 if (ssh_packet_inc_alive_timeouts(ssh
) > options
.server_alive_count_max
) {
500 logit("Timeout, server %s not responding.", host
);
503 if ((r
= sshpkt_start(ssh
, SSH2_MSG_GLOBAL_REQUEST
)) != 0 ||
504 (r
= sshpkt_put_cstring(ssh
, "keepalive@openssh.com")) != 0 ||
505 (r
= sshpkt_put_u8(ssh
, 1)) != 0 || /* boolean: want reply */
506 (r
= sshpkt_send(ssh
)) != 0)
507 fatal_fr(r
, "send packet");
508 /* Insert an empty placeholder to maintain ordering */
509 client_register_global_confirm(NULL
, NULL
);
510 schedule_server_alive_check();
513 /* Try to send a dummy keystroke */
515 send_chaff(struct ssh
*ssh
)
519 if (ssh
->kex
== NULL
|| (ssh
->kex
->flags
& KEX_HAS_PING
) == 0)
521 /* XXX probabilistically send chaff? */
523 * a SSH2_MSG_CHANNEL_DATA payload is 9 bytes:
524 * 4 bytes channel ID + 4 bytes string length + 1 byte string data
525 * simulate that here.
527 if ((r
= sshpkt_start(ssh
, SSH2_MSG_PING
)) != 0 ||
528 (r
= sshpkt_put_cstring(ssh
, "PING!")) != 0 ||
529 (r
= sshpkt_send(ssh
)) != 0)
530 fatal_fr(r
, "send packet");
534 /* Sets the next interval to send a keystroke or chaff packet */
536 set_next_interval(const struct timespec
*now
, struct timespec
*next_interval
,
537 u_int interval_ms
, int starting
)
540 long long interval_ns
, fuzz_ns
;
541 static long long rate_fuzz
;
543 interval_ns
= interval_ms
* (1000LL * 1000);
544 fuzz_ns
= (interval_ns
* SSH_KEYSTROKE_TIMING_FUZZ
) / 100;
545 /* Center fuzz around requested interval */
546 if (fuzz_ns
> INT_MAX
)
548 if (fuzz_ns
> interval_ns
) {
549 /* Shouldn't happen */
550 fatal_f("internal error: fuzz %u%% %lldns > interval %lldns",
551 SSH_KEYSTROKE_TIMING_FUZZ
, fuzz_ns
, interval_ns
);
554 * Randomise the keystroke/chaff intervals in two ways:
555 * 1. Each interval has some random jitter applied to make the
556 * interval-to-interval time unpredictable.
557 * 2. The overall interval rate is also randomly perturbed for each
558 * chaffing session to make the average rate unpredictable.
561 rate_fuzz
= arc4random_uniform(fuzz_ns
);
562 interval_ns
-= fuzz_ns
;
563 interval_ns
+= arc4random_uniform(fuzz_ns
) + rate_fuzz
;
565 tmp
.tv_sec
= interval_ns
/ (1000 * 1000 * 1000);
566 tmp
.tv_nsec
= interval_ns
% (1000 * 1000 * 1000);
568 timespecadd(now
, &tmp
, next_interval
);
572 * Performs keystroke timing obfuscation. Returns non-zero if the
573 * output fd should be polled.
576 obfuscate_keystroke_timing(struct ssh
*ssh
, struct timespec
*timeout
,
577 int channel_did_enqueue
)
580 static struct timespec next_interval
, chaff_until
;
581 struct timespec now
, tmp
;
582 int just_started
= 0, had_keystroke
= 0;
583 static unsigned long long nchaff
;
584 char *stop_reason
= NULL
;
589 if (options
.obscure_keystroke_timing_interval
<= 0)
590 return 1; /* disabled in config */
592 if (!channel_tty_open(ssh
) || quit_pending
) {
593 /* Stop if no channels left of we're waiting for one to close */
594 stop_reason
= "no active channels";
595 } else if (ssh_packet_is_rekeying(ssh
)) {
596 /* Stop if we're rekeying */
597 stop_reason
= "rekeying started";
598 } else if (!ssh_packet_interactive_data_to_write(ssh
) &&
599 ssh_packet_have_data_to_write(ssh
)) {
600 /* Stop if the output buffer has more than a few keystrokes */
601 stop_reason
= "output buffer filling";
602 } else if (active
&& channel_did_enqueue
&&
603 ssh_packet_have_data_to_write(ssh
)) {
604 /* Still in active mode and have a keystroke queued. */
607 if (timespeccmp(&now
, &chaff_until
, >=)) {
608 /* Stop if there have been no keystrokes for a while */
609 stop_reason
= "chaff time expired";
610 } else if (timespeccmp(&now
, &next_interval
, >=) &&
611 !ssh_packet_have_data_to_write(ssh
)) {
612 /* If due to send but have no data, then send chaff */
618 if (stop_reason
!= NULL
) {
620 debug3_f("stopping: %s (%llu chaff packets sent)",
621 stop_reason
, nchaff
);
628 * If we're in interactive mode, and only have a small amount
629 * of outbound data, then we assume that the user is typing
630 * interactively. In this case, start quantising outbound packets to
631 * fixed time intervals to hide inter-keystroke timing.
633 if (!active
&& ssh_packet_interactive_data_to_write(ssh
) &&
634 channel_did_enqueue
&& ssh_packet_have_data_to_write(ssh
)) {
635 debug3_f("starting: interval ~%dms",
636 options
.obscure_keystroke_timing_interval
);
637 just_started
= had_keystroke
= active
= 1;
639 set_next_interval(&now
, &next_interval
,
640 options
.obscure_keystroke_timing_interval
, 1);
643 /* Don't hold off if obfuscation inactive */
649 * Arrange to send chaff packets for a random interval after
650 * the last keystroke was sent.
652 ms_to_timespec(&tmp
, SSH_KEYSTROKE_CHAFF_MIN_MS
+
653 arc4random_uniform(SSH_KEYSTROKE_CHAFF_RNG_MS
));
654 timespecadd(&now
, &tmp
, &chaff_until
);
657 ptimeout_deadline_monotime_tsp(timeout
, &next_interval
);
662 /* Don't arm output fd for poll until the timing interval has elapsed */
663 if (timespeccmp(&now
, &next_interval
, <))
666 /* Calculate number of intervals missed since the last check */
667 n
= (now
.tv_sec
- next_interval
.tv_sec
) * 1000LL * 1000 * 1000;
668 n
+= now
.tv_nsec
- next_interval
.tv_nsec
;
669 n
/= options
.obscure_keystroke_timing_interval
* 1000LL * 1000;
670 n
= (n
< 0) ? 1 : n
+ 1;
672 /* Advance to the next interval */
673 set_next_interval(&now
, &next_interval
,
674 options
.obscure_keystroke_timing_interval
* n
, 0);
679 * Waits until the client can do something (some data becomes available on
680 * one of the file descriptors).
683 client_wait_until_can_do_something(struct ssh
*ssh
, struct pollfd
**pfdp
,
684 u_int
*npfd_allocp
, u_int
*npfd_activep
, int channel_did_enqueue
,
685 sigset_t
*sigsetp
, int *conn_in_readyp
, int *conn_out_readyp
)
687 struct timespec timeout
;
691 *conn_in_readyp
= *conn_out_readyp
= 0;
693 /* Prepare channel poll. First two pollfd entries are reserved */
694 ptimeout_init(&timeout
);
695 channel_prepare_poll(ssh
, pfdp
, npfd_allocp
, npfd_activep
, 2, &timeout
);
696 if (*npfd_activep
< 2)
697 fatal_f("bad npfd %u", *npfd_activep
); /* shouldn't happen */
699 /* channel_prepare_poll could have closed the last channel */
700 if (session_closed
&& !channel_still_open(ssh
) &&
701 !ssh_packet_have_data_to_write(ssh
)) {
702 /* clear events since we did not call poll() */
703 for (p
= 0; p
< *npfd_activep
; p
++)
704 (*pfdp
)[p
].revents
= 0;
708 oready
= obfuscate_keystroke_timing(ssh
, &timeout
, channel_did_enqueue
);
710 /* Monitor server connection on reserved pollfd entries */
711 (*pfdp
)[0].fd
= connection_in
;
712 (*pfdp
)[0].events
= POLLIN
;
713 (*pfdp
)[1].fd
= connection_out
;
714 (*pfdp
)[1].events
= (oready
&& ssh_packet_have_data_to_write(ssh
)) ?
718 * Wait for something to happen. This will suspend the process until
719 * some polled descriptor can be read, written, or has some other
720 * event pending, or a timeout expires.
722 set_control_persist_exit_time(ssh
);
723 if (control_persist_exit_time
> 0)
724 ptimeout_deadline_monotime(&timeout
, control_persist_exit_time
);
725 if (options
.server_alive_interval
> 0)
726 ptimeout_deadline_monotime(&timeout
, server_alive_time
);
727 if (options
.rekey_interval
> 0 && !ssh_packet_is_rekeying(ssh
)) {
728 ptimeout_deadline_sec(&timeout
,
729 ssh_packet_get_rekey_timeout(ssh
));
732 ret
= ppoll(*pfdp
, *npfd_activep
, ptimeout_get_tsp(&timeout
), sigsetp
);
736 * We have to clear the events because we return.
737 * We have to return, because the mainloop checks for the flags
738 * set by the signal handlers.
740 for (p
= 0; p
< *npfd_activep
; p
++)
741 (*pfdp
)[p
].revents
= 0;
744 /* Note: we might still have data in the buffers. */
745 quit_message("poll: %s", strerror(errno
));
749 *conn_in_readyp
= (*pfdp
)[0].revents
!= 0;
750 *conn_out_readyp
= (*pfdp
)[1].revents
!= 0;
752 if (options
.server_alive_interval
> 0 && !*conn_in_readyp
&&
753 monotime() >= server_alive_time
) {
755 * ServerAlive check is needed. We can't rely on the poll
756 * timing out since traffic on the client side such as port
757 * forwards can keep waking it up.
759 server_alive_check(ssh
);
764 client_suspend_self(struct sshbuf
*bin
, struct sshbuf
*bout
, struct sshbuf
*berr
)
766 /* Flush stdout and stderr buffers. */
767 if (sshbuf_len(bout
) > 0)
768 atomicio(vwrite
, fileno(stdout
), sshbuf_mutable_ptr(bout
),
770 if (sshbuf_len(berr
) > 0)
771 atomicio(vwrite
, fileno(stderr
), sshbuf_mutable_ptr(berr
),
774 leave_raw_mode(options
.request_tty
== REQUEST_TTY_FORCE
);
780 /* Send the suspend signal to the program itself. */
781 kill(getpid(), SIGTSTP
);
783 /* Reset window sizes in case they have changed */
784 received_window_change_signal
= 1;
786 enter_raw_mode(options
.request_tty
== REQUEST_TTY_FORCE
);
790 client_process_net_input(struct ssh
*ssh
)
795 * Read input from the server, and add any such data to the buffer of
796 * the packet subsystem.
798 schedule_server_alive_check();
799 if ((r
= ssh_packet_process_read(ssh
, connection_in
)) == 0)
800 return; /* success */
801 if (r
== SSH_ERR_SYSTEM_ERROR
) {
802 if (errno
== EAGAIN
|| errno
== EINTR
|| errno
== EWOULDBLOCK
)
804 if (errno
== EPIPE
) {
805 quit_message("Connection to %s closed by remote host.",
810 quit_message("Read from remote host %s: %s", host
, ssh_err(r
));
814 client_status_confirm(struct ssh
*ssh
, int type
, Channel
*c
, void *ctx
)
816 struct channel_reply_ctx
*cr
= (struct channel_reply_ctx
*)ctx
;
821 * If a TTY was explicitly requested, then a failure to allocate
824 if (cr
->action
== CONFIRM_TTY
&&
825 (options
.request_tty
== REQUEST_TTY_FORCE
||
826 options
.request_tty
== REQUEST_TTY_YES
))
827 cr
->action
= CONFIRM_CLOSE
;
829 /* XXX suppress on mux _client_ quietmode */
830 tochan
= options
.log_level
>= SYSLOG_LEVEL_ERROR
&&
831 c
->ctl_chan
!= -1 && c
->extended_usage
== CHAN_EXTENDED_WRITE
;
833 if (type
== SSH2_MSG_CHANNEL_SUCCESS
) {
834 debug2("%s request accepted on channel %d",
835 cr
->request_type
, c
->self
);
836 } else if (type
== SSH2_MSG_CHANNEL_FAILURE
) {
838 snprintf(errmsg
, sizeof(errmsg
),
839 "%s request failed\r\n", cr
->request_type
);
841 snprintf(errmsg
, sizeof(errmsg
),
842 "%s request failed on channel %d",
843 cr
->request_type
, c
->self
);
845 /* If error occurred on primary session channel, then exit */
846 if (cr
->action
== CONFIRM_CLOSE
&& c
->self
== session_ident
)
849 * If error occurred on mux client, append to
853 debug3_f("channel %d: mux request: %s", c
->self
,
855 if ((r
= sshbuf_put(c
->extended
, errmsg
,
856 strlen(errmsg
))) != 0)
857 fatal_fr(r
, "sshbuf_put");
860 if (cr
->action
== CONFIRM_TTY
) {
862 * If a TTY allocation error occurred, then arrange
863 * for the correct TTY to leave raw mode.
865 if (c
->self
== session_ident
)
868 mux_tty_alloc_failed(ssh
, c
);
869 } else if (cr
->action
== CONFIRM_CLOSE
) {
870 chan_read_failed(ssh
, c
);
871 chan_write_failed(ssh
, c
);
878 client_abandon_status_confirm(struct ssh
*ssh
, Channel
*c
, void *ctx
)
884 client_expect_confirm(struct ssh
*ssh
, int id
, const char *request
,
885 enum confirm_action action
)
887 struct channel_reply_ctx
*cr
= xcalloc(1, sizeof(*cr
));
889 cr
->request_type
= request
;
892 channel_register_status_confirm(ssh
, id
, client_status_confirm
,
893 client_abandon_status_confirm
, cr
);
897 client_register_global_confirm(global_confirm_cb
*cb
, void *ctx
)
899 struct global_confirm
*gc
, *last_gc
;
901 /* Coalesce identical callbacks */
902 last_gc
= TAILQ_LAST(&global_confirms
, global_confirms
);
903 if (last_gc
&& last_gc
->cb
== cb
&& last_gc
->ctx
== ctx
) {
904 if (++last_gc
->ref_count
>= INT_MAX
)
905 fatal_f("last_gc->ref_count = %d",
910 gc
= xcalloc(1, sizeof(*gc
));
914 TAILQ_INSERT_TAIL(&global_confirms
, gc
, entry
);
918 * Returns non-zero if the client is able to handle a hostkeys-00@openssh.com
919 * hostkey update request.
922 can_update_hostkeys(void)
924 if (hostkeys_update_complete
)
926 if (options
.update_hostkeys
== SSH_UPDATE_HOSTKEYS_ASK
&&
928 return 0; /* won't ask in batchmode, so don't even try */
929 if (!options
.update_hostkeys
|| options
.num_user_hostfiles
<= 0)
935 client_repledge(void)
939 /* Might be able to tighten pledge now that session is established */
940 if (options
.control_master
|| options
.control_path
!= NULL
||
941 options
.forward_x11
|| options
.fork_after_authentication
||
942 can_update_hostkeys() ||
943 (session_ident
!= -1 && !session_setup_complete
)) {
948 * LocalCommand and UpdateHostkeys have finished, so can get rid of
951 * XXX protocol allows a server can to change hostkeys during the
952 * connection at rekey time that could trigger a hostkeys update
953 * but AFAIK no implementations support this. Could improve by
954 * forcing known_hosts to be read-only or via unveil(2).
956 if (options
.num_local_forwards
!= 0 ||
957 options
.num_remote_forwards
!= 0 ||
958 options
.num_permitted_remote_opens
!= 0 ||
959 options
.enable_escape_commandline
!= 0) {
960 /* rfwd needs inet */
961 debug("pledge: network");
962 if (pledge("stdio unix inet dns proc tty", NULL
) == -1)
963 fatal_f("pledge(): %s", strerror(errno
));
964 } else if (options
.forward_agent
!= 0) {
965 /* agent forwarding needs to open $SSH_AUTH_SOCK at will */
966 debug("pledge: agent");
967 if (pledge("stdio unix proc tty", NULL
) == -1)
968 fatal_f("pledge(): %s", strerror(errno
));
970 debug("pledge: fork");
971 if (pledge("stdio proc tty", NULL
) == -1)
972 fatal_f("pledge(): %s", strerror(errno
));
974 /* XXX further things to do:
976 * - might be able to get rid of proc if we kill ~^Z
977 * - ssh -N (no session)
979 * - sessions without tty
984 process_cmdline(struct ssh
*ssh
)
986 void (*handler
)(int);
988 int ok
, delete = 0, local
= 0, remote
= 0, dynamic
= 0;
991 memset(&fwd
, 0, sizeof(fwd
));
993 leave_raw_mode(options
.request_tty
== REQUEST_TTY_FORCE
);
994 handler
= ssh_signal(SIGINT
, SIG_IGN
);
995 cmd
= s
= read_passphrase("\r\nssh> ", RP_ECHO
);
998 while (isspace((u_char
)*s
))
1001 s
++; /* Skip cmdline '-', if any */
1005 if (*s
== 'h' || *s
== 'H' || *s
== '?') {
1007 logit(" -L[bind_address:]port:host:hostport "
1008 "Request local forward");
1009 logit(" -R[bind_address:]port:host:hostport "
1010 "Request remote forward");
1011 logit(" -D[bind_address:]port "
1012 "Request dynamic forward");
1013 logit(" -KL[bind_address:]port "
1014 "Cancel local forward");
1015 logit(" -KR[bind_address:]port "
1016 "Cancel remote forward");
1017 logit(" -KD[bind_address:]port "
1018 "Cancel dynamic forward");
1019 if (!options
.permit_local_command
)
1022 "Execute local command");
1026 if (*s
== '!' && options
.permit_local_command
) {
1043 logit("Invalid command.");
1047 while (isspace((u_char
)*++s
))
1050 /* XXX update list of forwards in options */
1052 /* We pass 1 for dynamicfwd to restrict to 1 or 2 fields. */
1053 if (!parse_forward(&fwd
, s
, 1, 0)) {
1054 logit("Bad forwarding close specification.");
1058 ok
= channel_request_rforward_cancel(ssh
, &fwd
) == 0;
1060 ok
= channel_cancel_lport_listener(ssh
, &fwd
,
1061 0, &options
.fwd_opts
) > 0;
1063 ok
= channel_cancel_lport_listener(ssh
, &fwd
,
1064 CHANNEL_CANCEL_PORT_STATIC
,
1065 &options
.fwd_opts
) > 0;
1067 logit("Unknown port forwarding.");
1070 logit("Canceled forwarding.");
1072 /* -R specs can be both dynamic or not, so check both. */
1074 if (!parse_forward(&fwd
, s
, 0, remote
) &&
1075 !parse_forward(&fwd
, s
, 1, remote
)) {
1076 logit("Bad remote forwarding specification.");
1079 } else if (!parse_forward(&fwd
, s
, dynamic
, remote
)) {
1080 logit("Bad local forwarding specification.");
1083 if (local
|| dynamic
) {
1084 if (!channel_setup_local_fwd_listener(ssh
, &fwd
,
1085 &options
.fwd_opts
)) {
1086 logit("Port forwarding failed.");
1090 if (channel_request_remote_forwarding(ssh
, &fwd
) < 0) {
1091 logit("Port forwarding failed.");
1095 logit("Forwarding port.");
1099 ssh_signal(SIGINT
, handler
);
1100 enter_raw_mode(options
.request_tty
== REQUEST_TTY_FORCE
);
1102 free(fwd
.listen_host
);
1103 free(fwd
.listen_path
);
1104 free(fwd
.connect_host
);
1105 free(fwd
.connect_path
);
1108 /* reasons to suppress output of an escape command in help output */
1109 #define SUPPRESS_NEVER 0 /* never suppress, always show */
1110 #define SUPPRESS_MUXCLIENT 1 /* don't show in mux client sessions */
1111 #define SUPPRESS_MUXMASTER 2 /* don't show in mux master sessions */
1112 #define SUPPRESS_SYSLOG 4 /* don't show when logging to syslog */
1113 #define SUPPRESS_NOCMDLINE 8 /* don't show when cmdline disabled*/
1114 struct escape_help_text
{
1119 static struct escape_help_text esc_txt
[] = {
1120 {".", "terminate session", SUPPRESS_MUXMASTER
},
1121 {".", "terminate connection (and any multiplexed sessions)",
1122 SUPPRESS_MUXCLIENT
},
1123 {"B", "send a BREAK to the remote system", SUPPRESS_NEVER
},
1124 {"C", "open a command line", SUPPRESS_MUXCLIENT
|SUPPRESS_NOCMDLINE
},
1125 {"R", "request rekey", SUPPRESS_NEVER
},
1126 {"V/v", "decrease/increase verbosity (LogLevel)", SUPPRESS_MUXCLIENT
},
1127 {"^Z", "suspend ssh", SUPPRESS_MUXCLIENT
},
1128 {"#", "list forwarded connections", SUPPRESS_NEVER
},
1129 {"&", "background ssh (when waiting for connections to terminate)",
1130 SUPPRESS_MUXCLIENT
},
1131 {"?", "this message", SUPPRESS_NEVER
},
1135 print_escape_help(struct sshbuf
*b
, int escape_char
, int mux_client
,
1138 unsigned int i
, suppress_flags
;
1141 if ((r
= sshbuf_putf(b
,
1142 "%c?\r\nSupported escape sequences:\r\n", escape_char
)) != 0)
1143 fatal_fr(r
, "sshbuf_putf");
1146 (mux_client
? SUPPRESS_MUXCLIENT
: 0) |
1147 (mux_client
? 0 : SUPPRESS_MUXMASTER
) |
1148 (using_stderr
? 0 : SUPPRESS_SYSLOG
) |
1149 (options
.enable_escape_commandline
== 0 ? SUPPRESS_NOCMDLINE
: 0);
1151 for (i
= 0; i
< sizeof(esc_txt
)/sizeof(esc_txt
[0]); i
++) {
1152 if (esc_txt
[i
].flags
& suppress_flags
)
1154 if ((r
= sshbuf_putf(b
, " %c%-3s - %s\r\n",
1155 escape_char
, esc_txt
[i
].cmd
, esc_txt
[i
].text
)) != 0)
1156 fatal_fr(r
, "sshbuf_putf");
1159 if ((r
= sshbuf_putf(b
,
1160 " %c%c - send the escape character by typing it twice\r\n"
1161 "(Note that escapes are only recognized immediately after "
1162 "newline.)\r\n", escape_char
, escape_char
)) != 0)
1163 fatal_fr(r
, "sshbuf_putf");
1167 * Process the characters one by one.
1170 process_escapes(struct ssh
*ssh
, Channel
*c
,
1171 struct sshbuf
*bin
, struct sshbuf
*bout
, struct sshbuf
*berr
,
1179 struct escape_filter_ctx
*efc
;
1181 if (c
== NULL
|| c
->filter_ctx
== NULL
|| len
<= 0)
1184 efc
= (struct escape_filter_ctx
*)c
->filter_ctx
;
1186 for (i
= 0; i
< (u_int
)len
; i
++) {
1187 /* Get one character at a time. */
1190 if (efc
->escape_pending
) {
1191 /* We have previously seen an escape character. */
1192 /* Clear the flag now. */
1193 efc
->escape_pending
= 0;
1195 /* Process the escaped character. */
1198 /* Terminate the connection. */
1199 if ((r
= sshbuf_putf(berr
, "%c.\r\n",
1200 efc
->escape_char
)) != 0)
1201 fatal_fr(r
, "sshbuf_putf");
1202 if (c
&& c
->ctl_chan
!= -1) {
1203 channel_force_close(ssh
, c
, 1);
1210 /* XXX support this for mux clients */
1211 if (c
&& c
->ctl_chan
!= -1) {
1215 snprintf(b
, sizeof b
, "^Z");
1217 snprintf(b
, sizeof b
, "%c", ch
);
1218 if ((r
= sshbuf_putf(berr
,
1219 "%c%s escape not available to "
1220 "multiplexed sessions\r\n",
1221 efc
->escape_char
, b
)) != 0)
1222 fatal_fr(r
, "sshbuf_putf");
1225 /* Suspend the program. Inform the user */
1226 if ((r
= sshbuf_putf(berr
,
1227 "%c^Z [suspend ssh]\r\n",
1228 efc
->escape_char
)) != 0)
1229 fatal_fr(r
, "sshbuf_putf");
1231 /* Restore terminal modes and suspend. */
1232 client_suspend_self(bin
, bout
, berr
);
1234 /* We have been continued. */
1238 if ((r
= sshbuf_putf(berr
,
1239 "%cB\r\n", efc
->escape_char
)) != 0)
1240 fatal_fr(r
, "sshbuf_putf");
1241 channel_request_start(ssh
, c
->self
, "break", 0);
1242 if ((r
= sshpkt_put_u32(ssh
, 1000)) != 0 ||
1243 (r
= sshpkt_send(ssh
)) != 0)
1244 fatal_fr(r
, "send packet");
1248 if (ssh
->compat
& SSH_BUG_NOREKEY
)
1249 logit("Server does not "
1250 "support re-keying");
1258 if (c
&& c
->ctl_chan
!= -1)
1260 if (!log_is_on_stderr()) {
1261 if ((r
= sshbuf_putf(berr
,
1262 "%c%c [Logging to syslog]\r\n",
1263 efc
->escape_char
, ch
)) != 0)
1264 fatal_fr(r
, "sshbuf_putf");
1267 if (ch
== 'V' && options
.log_level
>
1269 log_change_level(--options
.log_level
);
1270 if (ch
== 'v' && options
.log_level
<
1271 SYSLOG_LEVEL_DEBUG3
)
1272 log_change_level(++options
.log_level
);
1273 if ((r
= sshbuf_putf(berr
,
1274 "%c%c [LogLevel %s]\r\n",
1275 efc
->escape_char
, ch
,
1276 log_level_name(options
.log_level
))) != 0)
1277 fatal_fr(r
, "sshbuf_putf");
1281 if (c
->ctl_chan
!= -1)
1284 * Detach the program (continue to serve
1285 * connections, but put in background and no
1286 * more new connections).
1288 /* Restore tty modes. */
1290 options
.request_tty
== REQUEST_TTY_FORCE
);
1292 /* Stop listening for new connections. */
1293 channel_stop_listening(ssh
);
1295 if ((r
= sshbuf_putf(berr
, "%c& "
1296 "[backgrounded]\n", efc
->escape_char
)) != 0)
1297 fatal_fr(r
, "sshbuf_putf");
1299 /* Fork into background. */
1302 error("fork: %.100s", strerror(errno
));
1305 if (pid
!= 0) { /* This is the parent. */
1306 /* The parent just exits. */
1309 /* The child continues serving connections. */
1310 /* fake EOF on stdin */
1311 if ((r
= sshbuf_put_u8(bin
, 4)) != 0)
1312 fatal_fr(r
, "sshbuf_put_u8");
1315 print_escape_help(berr
, efc
->escape_char
,
1316 (c
&& c
->ctl_chan
!= -1),
1317 log_is_on_stderr());
1321 if ((r
= sshbuf_putf(berr
, "%c#\r\n",
1322 efc
->escape_char
)) != 0)
1323 fatal_fr(r
, "sshbuf_putf");
1324 s
= channel_open_message(ssh
);
1325 if ((r
= sshbuf_put(berr
, s
, strlen(s
))) != 0)
1326 fatal_fr(r
, "sshbuf_put");
1331 if (c
&& c
->ctl_chan
!= -1)
1333 if (options
.enable_escape_commandline
== 0) {
1334 if ((r
= sshbuf_putf(berr
,
1335 "commandline disabled\r\n")) != 0)
1336 fatal_fr(r
, "sshbuf_putf");
1339 process_cmdline(ssh
);
1343 if (ch
!= efc
->escape_char
) {
1344 if ((r
= sshbuf_put_u8(bin
,
1345 efc
->escape_char
)) != 0)
1346 fatal_fr(r
, "sshbuf_put_u8");
1349 /* Escaped characters fall through here */
1354 * The previous character was not an escape char.
1355 * Check if this is an escape.
1357 if (last_was_cr
&& ch
== efc
->escape_char
) {
1359 * It is. Set the flag and continue to
1362 efc
->escape_pending
= 1;
1368 * Normal character. Record whether it was a newline,
1369 * and append it to the buffer.
1371 last_was_cr
= (ch
== '\r' || ch
== '\n');
1372 if ((r
= sshbuf_put_u8(bin
, ch
)) != 0)
1373 fatal_fr(r
, "sshbuf_put_u8");
1380 * Get packets from the connection input buffer, and process them as long as
1381 * there are packets available.
1383 * Any unknown packets received during the actual
1384 * session cause the session to terminate. This is
1385 * intended to make debugging easier since no
1386 * confirmations are sent. Any compatible protocol
1387 * extensions must be negotiated during the
1388 * preparatory phase.
1392 client_process_buffered_input_packets(struct ssh
*ssh
)
1394 ssh_dispatch_run_fatal(ssh
, DISPATCH_NONBLOCK
, &quit_pending
);
1397 /* scan buf[] for '~' before sending data to the peer */
1399 /* Helper: allocate a new escape_filter_ctx and fill in its escape char */
1401 client_new_escape_filter_ctx(int escape_char
)
1403 struct escape_filter_ctx
*ret
;
1405 ret
= xcalloc(1, sizeof(*ret
));
1406 ret
->escape_pending
= 0;
1407 ret
->escape_char
= escape_char
;
1411 /* Free the escape filter context on channel free */
1413 client_filter_cleanup(struct ssh
*ssh
, int cid
, void *ctx
)
1419 client_simple_escape_filter(struct ssh
*ssh
, Channel
*c
, char *buf
, int len
)
1421 if (c
->extended_usage
!= CHAN_EXTENDED_WRITE
)
1424 return process_escapes(ssh
, c
, c
->input
, c
->output
, c
->extended
,
1429 client_channel_closed(struct ssh
*ssh
, int id
, int force
, void *arg
)
1431 channel_cancel_cleanup(ssh
, id
);
1433 leave_raw_mode(options
.request_tty
== REQUEST_TTY_FORCE
);
1437 * Implements the interactive session with the server. This is called after
1438 * the user has been authenticated, and a command has been started on the
1439 * remote host. If escape_char != SSH_ESCAPECHAR_NONE, it is the character
1440 * used as an escape character for terminating or suspending the session.
1443 client_loop(struct ssh
*ssh
, int have_pty
, int escape_char_arg
,
1446 struct pollfd
*pfd
= NULL
;
1447 u_int npfd_alloc
= 0, npfd_active
= 0;
1448 double start_time
, total_time
;
1449 int channel_did_enqueue
= 0, r
;
1450 u_int64_t ibytes
, obytes
;
1451 int conn_in_ready
, conn_out_ready
;
1452 sigset_t bsigset
, osigset
;
1454 debug("Entering interactive session.");
1455 session_ident
= ssh2_chan_id
;
1457 if (options
.control_master
&&
1458 !option_clear_or_none(options
.control_path
)) {
1459 debug("pledge: id");
1460 if (pledge("stdio rpath wpath cpath unix inet dns recvfd sendfd proc exec id tty",
1462 fatal_f("pledge(): %s", strerror(errno
));
1464 } else if (options
.forward_x11
|| options
.permit_local_command
) {
1465 debug("pledge: exec");
1466 if (pledge("stdio rpath wpath cpath unix inet dns proc exec tty",
1468 fatal_f("pledge(): %s", strerror(errno
));
1470 } else if (options
.update_hostkeys
) {
1471 debug("pledge: filesystem");
1472 if (pledge("stdio rpath wpath cpath unix inet dns proc tty",
1474 fatal_f("pledge(): %s", strerror(errno
));
1476 } else if (!option_clear_or_none(options
.proxy_command
) ||
1477 options
.fork_after_authentication
) {
1478 debug("pledge: proc");
1479 if (pledge("stdio cpath unix inet dns proc tty", NULL
) == -1)
1480 fatal_f("pledge(): %s", strerror(errno
));
1483 debug("pledge: network");
1484 if (pledge("stdio unix inet dns proc tty", NULL
) == -1)
1485 fatal_f("pledge(): %s", strerror(errno
));
1488 /* might be able to tighten now */
1491 start_time
= monotime_double();
1493 /* Initialize variables. */
1496 connection_in
= ssh_packet_get_connection_in(ssh
);
1497 connection_out
= ssh_packet_get_connection_out(ssh
);
1501 client_init_dispatch(ssh
);
1504 * Set signal handlers, (e.g. to restore non-blocking mode)
1505 * but don't overwrite SIG_IGN, matches behaviour from rsh(1)
1507 if (ssh_signal(SIGHUP
, SIG_IGN
) != SIG_IGN
)
1508 ssh_signal(SIGHUP
, signal_handler
);
1509 if (ssh_signal(SIGINT
, SIG_IGN
) != SIG_IGN
)
1510 ssh_signal(SIGINT
, signal_handler
);
1511 if (ssh_signal(SIGQUIT
, SIG_IGN
) != SIG_IGN
)
1512 ssh_signal(SIGQUIT
, signal_handler
);
1513 if (ssh_signal(SIGTERM
, SIG_IGN
) != SIG_IGN
)
1514 ssh_signal(SIGTERM
, signal_handler
);
1515 ssh_signal(SIGWINCH
, window_change_handler
);
1518 enter_raw_mode(options
.request_tty
== REQUEST_TTY_FORCE
);
1520 if (session_ident
!= -1) {
1521 if (escape_char_arg
!= SSH_ESCAPECHAR_NONE
) {
1522 channel_register_filter(ssh
, session_ident
,
1523 client_simple_escape_filter
, NULL
,
1524 client_filter_cleanup
,
1525 client_new_escape_filter_ctx(
1528 channel_register_cleanup(ssh
, session_ident
,
1529 client_channel_closed
, 0);
1532 schedule_server_alive_check();
1534 if (sigemptyset(&bsigset
) == -1 ||
1535 sigaddset(&bsigset
, SIGHUP
) == -1 ||
1536 sigaddset(&bsigset
, SIGINT
) == -1 ||
1537 sigaddset(&bsigset
, SIGQUIT
) == -1 ||
1538 sigaddset(&bsigset
, SIGTERM
) == -1)
1539 error_f("bsigset setup: %s", strerror(errno
));
1541 /* Main loop of the client for the interactive session mode. */
1542 while (!quit_pending
) {
1543 channel_did_enqueue
= 0;
1545 /* Process buffered packets sent by the server. */
1546 client_process_buffered_input_packets(ssh
);
1548 if (session_closed
&& !channel_still_open(ssh
))
1551 if (ssh_packet_is_rekeying(ssh
)) {
1552 debug("rekeying in progress");
1553 } else if (need_rekeying
) {
1554 /* manual rekey request */
1555 debug("need rekeying");
1556 if ((r
= kex_start_rekex(ssh
)) != 0)
1557 fatal_fr(r
, "kex_start_rekex");
1561 * Make packets from buffered channel data, and
1562 * enqueue them for sending to the server.
1564 if (ssh_packet_not_very_much_data_to_write(ssh
))
1565 channel_did_enqueue
= channel_output_poll(ssh
);
1568 * Check if the window size has changed, and buffer a
1569 * message about it to the server if so.
1571 client_check_window_change(ssh
);
1574 * Wait until we have something to do (something becomes
1575 * available on one of the descriptors).
1577 if (sigprocmask(SIG_BLOCK
, &bsigset
, &osigset
) == -1)
1578 error_f("bsigset sigprocmask: %s", strerror(errno
));
1581 client_wait_until_can_do_something(ssh
, &pfd
, &npfd_alloc
,
1582 &npfd_active
, channel_did_enqueue
, &osigset
,
1583 &conn_in_ready
, &conn_out_ready
);
1584 if (sigprocmask(SIG_SETMASK
, &osigset
, NULL
) == -1)
1585 error_f("osigset sigprocmask: %s", strerror(errno
));
1590 /* Do channel operations. */
1591 channel_after_poll(ssh
, pfd
, npfd_active
);
1593 /* Buffer input from the connection. */
1595 client_process_net_input(ssh
);
1600 /* A timeout may have triggered rekeying */
1601 if ((r
= ssh_packet_check_rekey(ssh
)) != 0)
1602 fatal_fr(r
, "cannot start rekeying");
1605 * Send as much buffered packet data as possible to the
1608 if (conn_out_ready
) {
1609 if ((r
= ssh_packet_write_poll(ssh
)) != 0) {
1610 sshpkt_fatal(ssh
, r
,
1611 "%s: ssh_packet_write_poll", __func__
);
1616 * If we are a backgrounded control master, and the
1617 * timeout has expired without any active client
1618 * connections, then quit.
1620 if (control_persist_exit_time
> 0) {
1621 if (monotime() >= control_persist_exit_time
) {
1622 debug("ControlPersist timeout expired");
1629 /* Terminate the session. */
1632 * In interactive mode (with pseudo tty) display a message indicating
1633 * that the connection has been closed.
1635 if (have_pty
&& options
.log_level
>= SYSLOG_LEVEL_INFO
)
1636 quit_message("Connection to %s closed.", host
);
1639 /* Stop watching for window change. */
1640 ssh_signal(SIGWINCH
, SIG_DFL
);
1642 if ((r
= sshpkt_start(ssh
, SSH2_MSG_DISCONNECT
)) != 0 ||
1643 (r
= sshpkt_put_u32(ssh
, SSH2_DISCONNECT_BY_APPLICATION
)) != 0 ||
1644 (r
= sshpkt_put_cstring(ssh
, "disconnected by user")) != 0 ||
1645 (r
= sshpkt_put_cstring(ssh
, "")) != 0 || /* language tag */
1646 (r
= sshpkt_send(ssh
)) != 0 ||
1647 (r
= ssh_packet_write_wait(ssh
)) != 0)
1648 fatal_fr(r
, "send disconnect");
1650 channel_free_all(ssh
);
1653 leave_raw_mode(options
.request_tty
== REQUEST_TTY_FORCE
);
1656 * If there was no shell or command requested, there will be no remote
1657 * exit status to be returned. In that case, clear error code if the
1658 * connection was deliberately terminated at this end.
1660 if (options
.session_type
== SESSION_TYPE_NONE
&&
1661 received_signal
== SIGTERM
) {
1662 received_signal
= 0;
1666 if (received_signal
) {
1667 verbose("Killed by signal %d.", (int) received_signal
);
1671 /* Report bytes transferred, and transfer rates. */
1672 total_time
= monotime_double() - start_time
;
1673 ssh_packet_get_bytes(ssh
, &ibytes
, &obytes
);
1674 verbose("Transferred: sent %llu, received %llu bytes, in %.1f seconds",
1675 (unsigned long long)obytes
, (unsigned long long)ibytes
, total_time
);
1677 verbose("Bytes per second: sent %.1f, received %.1f",
1678 obytes
/ total_time
, ibytes
/ total_time
);
1679 /* Return the exit status of the program. */
1680 debug("Exit status %d", exit_status
);
1687 client_request_forwarded_tcpip(struct ssh
*ssh
, const char *request_type
,
1688 int rchan
, u_int rwindow
, u_int rmaxpack
)
1691 struct sshbuf
*b
= NULL
;
1692 char *listen_address
, *originator_address
;
1693 u_int listen_port
, originator_port
;
1696 /* Get rest of the packet */
1697 if ((r
= sshpkt_get_cstring(ssh
, &listen_address
, NULL
)) != 0 ||
1698 (r
= sshpkt_get_u32(ssh
, &listen_port
)) != 0 ||
1699 (r
= sshpkt_get_cstring(ssh
, &originator_address
, NULL
)) != 0 ||
1700 (r
= sshpkt_get_u32(ssh
, &originator_port
)) != 0 ||
1701 (r
= sshpkt_get_end(ssh
)) != 0)
1702 fatal_fr(r
, "parse packet");
1704 debug_f("listen %s port %d, originator %s port %d",
1705 listen_address
, listen_port
, originator_address
, originator_port
);
1707 if (listen_port
> 0xffff)
1708 error_f("invalid listen port");
1709 else if (originator_port
> 0xffff)
1710 error_f("invalid originator port");
1712 c
= channel_connect_by_listen_address(ssh
,
1713 listen_address
, listen_port
, "forwarded-tcpip",
1714 originator_address
);
1717 if (c
!= NULL
&& c
->type
== SSH_CHANNEL_MUX_CLIENT
) {
1718 if ((b
= sshbuf_new()) == NULL
) {
1719 error_f("alloc reply");
1722 /* reconstruct and send to muxclient */
1723 if ((r
= sshbuf_put_u8(b
, 0)) != 0 || /* padlen */
1724 (r
= sshbuf_put_u8(b
, SSH2_MSG_CHANNEL_OPEN
)) != 0 ||
1725 (r
= sshbuf_put_cstring(b
, request_type
)) != 0 ||
1726 (r
= sshbuf_put_u32(b
, rchan
)) != 0 ||
1727 (r
= sshbuf_put_u32(b
, rwindow
)) != 0 ||
1728 (r
= sshbuf_put_u32(b
, rmaxpack
)) != 0 ||
1729 (r
= sshbuf_put_cstring(b
, listen_address
)) != 0 ||
1730 (r
= sshbuf_put_u32(b
, listen_port
)) != 0 ||
1731 (r
= sshbuf_put_cstring(b
, originator_address
)) != 0 ||
1732 (r
= sshbuf_put_u32(b
, originator_port
)) != 0 ||
1733 (r
= sshbuf_put_stringb(c
->output
, b
)) != 0) {
1734 error_fr(r
, "compose for muxclient");
1741 free(originator_address
);
1742 free(listen_address
);
1747 client_request_forwarded_streamlocal(struct ssh
*ssh
,
1748 const char *request_type
, int rchan
)
1754 /* Get the remote path. */
1755 if ((r
= sshpkt_get_cstring(ssh
, &listen_path
, NULL
)) != 0 ||
1756 (r
= sshpkt_get_string(ssh
, NULL
, NULL
)) != 0 || /* reserved */
1757 (r
= sshpkt_get_end(ssh
)) != 0)
1758 fatal_fr(r
, "parse packet");
1760 debug_f("request: %s", listen_path
);
1762 c
= channel_connect_by_listen_path(ssh
, listen_path
,
1763 "forwarded-streamlocal@openssh.com", "forwarded-streamlocal");
1769 client_request_x11(struct ssh
*ssh
, const char *request_type
, int rchan
)
1773 u_int originator_port
;
1776 if (!options
.forward_x11
) {
1777 error("Warning: ssh server tried X11 forwarding.");
1778 error("Warning: this is probably a break-in attempt by a "
1779 "malicious server.");
1782 if (x11_refuse_time
!= 0 && monotime() >= x11_refuse_time
) {
1783 verbose("Rejected X11 connection after ForwardX11Timeout "
1787 if ((r
= sshpkt_get_cstring(ssh
, &originator
, NULL
)) != 0 ||
1788 (r
= sshpkt_get_u32(ssh
, &originator_port
)) != 0 ||
1789 (r
= sshpkt_get_end(ssh
)) != 0)
1790 fatal_fr(r
, "parse packet");
1791 /* XXX check permission */
1792 /* XXX range check originator port? */
1793 debug("client_request_x11: request from %s %u", originator
,
1796 sock
= x11_connect_display(ssh
);
1799 c
= channel_new(ssh
, "x11-connection",
1800 SSH_CHANNEL_X11_OPEN
, sock
, sock
, -1,
1801 CHAN_TCP_WINDOW_DEFAULT
, CHAN_X11_PACKET_DEFAULT
, 0, "x11", 1);
1807 client_request_agent(struct ssh
*ssh
, const char *request_type
, int rchan
)
1812 if (!options
.forward_agent
) {
1813 error("Warning: ssh server tried agent forwarding.");
1814 error("Warning: this is probably a break-in attempt by a "
1815 "malicious server.");
1818 if (forward_agent_sock_path
== NULL
) {
1819 r
= ssh_get_authentication_socket(&sock
);
1821 r
= ssh_get_authentication_socket_path(forward_agent_sock_path
, &sock
);
1824 if (r
!= SSH_ERR_AGENT_NOT_PRESENT
)
1825 debug_fr(r
, "ssh_get_authentication_socket");
1828 if ((r
= ssh_agent_bind_hostkey(sock
, ssh
->kex
->initial_hostkey
,
1829 ssh
->kex
->session_id
, ssh
->kex
->initial_sig
, 1)) == 0)
1830 debug_f("bound agent to hostkey");
1832 debug2_fr(r
, "ssh_agent_bind_hostkey");
1834 c
= channel_new(ssh
, "agent-connection",
1835 SSH_CHANNEL_OPEN
, sock
, sock
, -1,
1836 CHAN_X11_WINDOW_DEFAULT
, CHAN_TCP_PACKET_DEFAULT
, 0,
1837 "authentication agent connection", 1);
1843 client_request_tun_fwd(struct ssh
*ssh
, int tun_mode
,
1844 int local_tun
, int remote_tun
, channel_open_fn
*cb
, void *cbctx
)
1848 char *ifname
= NULL
;
1850 if (tun_mode
== SSH_TUNMODE_NO
)
1853 debug("Requesting tun unit %d in mode %d", local_tun
, tun_mode
);
1855 /* Open local tunnel device */
1856 if ((fd
= tun_open(local_tun
, tun_mode
, &ifname
)) == -1) {
1857 error("Tunnel device open failed.");
1860 debug("Tunnel forwarding using interface %s", ifname
);
1862 c
= channel_new(ssh
, "tun-connection", SSH_CHANNEL_OPENING
, fd
, fd
, -1,
1863 CHAN_TCP_WINDOW_DEFAULT
, CHAN_TCP_PACKET_DEFAULT
, 0, "tun", 1);
1866 #if defined(SSH_TUN_FILTER)
1867 if (options
.tun_open
== SSH_TUNMODE_POINTOPOINT
)
1868 channel_register_filter(ssh
, c
->self
, sys_tun_infilter
,
1869 sys_tun_outfilter
, NULL
, NULL
);
1873 channel_register_open_confirm(ssh
, c
->self
, cb
, cbctx
);
1875 if ((r
= sshpkt_start(ssh
, SSH2_MSG_CHANNEL_OPEN
)) != 0 ||
1876 (r
= sshpkt_put_cstring(ssh
, "tun@openssh.com")) != 0 ||
1877 (r
= sshpkt_put_u32(ssh
, c
->self
)) != 0 ||
1878 (r
= sshpkt_put_u32(ssh
, c
->local_window_max
)) != 0 ||
1879 (r
= sshpkt_put_u32(ssh
, c
->local_maxpacket
)) != 0 ||
1880 (r
= sshpkt_put_u32(ssh
, tun_mode
)) != 0 ||
1881 (r
= sshpkt_put_u32(ssh
, remote_tun
)) != 0 ||
1882 (r
= sshpkt_send(ssh
)) != 0)
1883 sshpkt_fatal(ssh
, r
, "%s: send reply", __func__
);
1888 /* XXXX move to generic input handler */
1890 client_input_channel_open(int type
, u_int32_t seq
, struct ssh
*ssh
)
1897 u_int rmaxpack
, rwindow
;
1899 if ((r
= sshpkt_get_cstring(ssh
, &ctype
, &len
)) != 0 ||
1900 (r
= sshpkt_get_u32(ssh
, &rchan
)) != 0 ||
1901 (r
= sshpkt_get_u32(ssh
, &rwindow
)) != 0 ||
1902 (r
= sshpkt_get_u32(ssh
, &rmaxpack
)) != 0)
1905 debug("client_input_channel_open: ctype %s rchan %d win %d max %d",
1906 ctype
, rchan
, rwindow
, rmaxpack
);
1908 if (strcmp(ctype
, "forwarded-tcpip") == 0) {
1909 c
= client_request_forwarded_tcpip(ssh
, ctype
, rchan
, rwindow
,
1911 } else if (strcmp(ctype
, "forwarded-streamlocal@openssh.com") == 0) {
1912 c
= client_request_forwarded_streamlocal(ssh
, ctype
, rchan
);
1913 } else if (strcmp(ctype
, "x11") == 0) {
1914 c
= client_request_x11(ssh
, ctype
, rchan
);
1915 } else if (strcmp(ctype
, "auth-agent@openssh.com") == 0) {
1916 c
= client_request_agent(ssh
, ctype
, rchan
);
1918 if (c
!= NULL
&& c
->type
== SSH_CHANNEL_MUX_CLIENT
) {
1919 debug3("proxied to downstream: %s", ctype
);
1920 } else if (c
!= NULL
) {
1921 debug("confirm %s", ctype
);
1922 c
->remote_id
= rchan
;
1923 c
->have_remote_id
= 1;
1924 c
->remote_window
= rwindow
;
1925 c
->remote_maxpacket
= rmaxpack
;
1926 if (c
->type
!= SSH_CHANNEL_CONNECTING
) {
1927 if ((r
= sshpkt_start(ssh
, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION
)) != 0 ||
1928 (r
= sshpkt_put_u32(ssh
, c
->remote_id
)) != 0 ||
1929 (r
= sshpkt_put_u32(ssh
, c
->self
)) != 0 ||
1930 (r
= sshpkt_put_u32(ssh
, c
->local_window
)) != 0 ||
1931 (r
= sshpkt_put_u32(ssh
, c
->local_maxpacket
)) != 0 ||
1932 (r
= sshpkt_send(ssh
)) != 0)
1933 sshpkt_fatal(ssh
, r
, "%s: send reply", __func__
);
1936 debug("failure %s", ctype
);
1937 if ((r
= sshpkt_start(ssh
, SSH2_MSG_CHANNEL_OPEN_FAILURE
)) != 0 ||
1938 (r
= sshpkt_put_u32(ssh
, rchan
)) != 0 ||
1939 (r
= sshpkt_put_u32(ssh
, SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED
)) != 0 ||
1940 (r
= sshpkt_put_cstring(ssh
, "open failed")) != 0 ||
1941 (r
= sshpkt_put_cstring(ssh
, "")) != 0 ||
1942 (r
= sshpkt_send(ssh
)) != 0)
1943 sshpkt_fatal(ssh
, r
, "%s: send failure", __func__
);
1952 client_input_channel_req(int type
, u_int32_t seq
, struct ssh
*ssh
)
1960 if ((r
= sshpkt_get_u32(ssh
, &id
)) != 0)
1963 c
= channel_lookup(ssh
, id
);
1964 if (channel_proxy_upstream(c
, type
, seq
, ssh
))
1966 if ((r
= sshpkt_get_cstring(ssh
, &rtype
, NULL
)) != 0 ||
1967 (r
= sshpkt_get_u8(ssh
, &reply
)) != 0)
1970 debug("client_input_channel_req: channel %u rtype %s reply %d",
1974 error("client_input_channel_req: channel %d: "
1975 "unknown channel", id
);
1976 } else if (strcmp(rtype
, "eow@openssh.com") == 0) {
1977 if ((r
= sshpkt_get_end(ssh
)) != 0)
1979 chan_rcvd_eow(ssh
, c
);
1980 } else if (strcmp(rtype
, "exit-status") == 0) {
1981 if ((r
= sshpkt_get_u32(ssh
, &exitval
)) != 0)
1983 if (c
->ctl_chan
!= -1) {
1984 mux_exit_message(ssh
, c
, exitval
);
1986 } else if ((int)id
== session_ident
) {
1987 /* Record exit value of local session */
1989 exit_status
= exitval
;
1991 /* Probably for a mux channel that has already closed */
1992 debug_f("no sink for exit-status on channel %d",
1995 if ((r
= sshpkt_get_end(ssh
)) != 0)
1998 if (reply
&& c
!= NULL
&& !(c
->flags
& CHAN_CLOSE_SENT
)) {
1999 if (!c
->have_remote_id
)
2000 fatal_f("channel %d: no remote_id", c
->self
);
2001 if ((r
= sshpkt_start(ssh
, success
?
2002 SSH2_MSG_CHANNEL_SUCCESS
: SSH2_MSG_CHANNEL_FAILURE
)) != 0 ||
2003 (r
= sshpkt_put_u32(ssh
, c
->remote_id
)) != 0 ||
2004 (r
= sshpkt_send(ssh
)) != 0)
2005 sshpkt_fatal(ssh
, r
, "%s: send failure", __func__
);
2013 struct hostkeys_update_ctx
{
2014 /* The hostname and (optionally) IP address string for the server */
2015 char *host_str
, *ip_str
;
2018 * Keys received from the server and a flag for each indicating
2019 * whether they already exist in known_hosts.
2020 * keys_match is filled in by hostkeys_find() and later (for new
2021 * keys) by client_global_hostkeys_prove_confirm().
2023 struct sshkey
**keys
;
2024 u_int
*keys_match
; /* mask of HKF_MATCH_* from hostfile.h */
2025 int *keys_verified
; /* flag for new keys verified by server */
2026 size_t nkeys
, nnew
, nincomplete
; /* total, new keys, incomplete match */
2029 * Keys that are in known_hosts, but were not present in the update
2030 * from the server (i.e. scheduled to be deleted).
2031 * Filled in by hostkeys_find().
2033 struct sshkey
**old_keys
;
2036 /* Various special cases. */
2037 int complex_hostspec
; /* wildcard or manual pattern-list host name */
2038 int ca_available
; /* saw CA key for this host */
2039 int old_key_seen
; /* saw old key with other name/addr */
2040 int other_name_seen
; /* saw key with other name/addr */
2044 hostkeys_update_ctx_free(struct hostkeys_update_ctx
*ctx
)
2050 for (i
= 0; i
< ctx
->nkeys
; i
++)
2051 sshkey_free(ctx
->keys
[i
]);
2053 free(ctx
->keys_match
);
2054 free(ctx
->keys_verified
);
2055 for (i
= 0; i
< ctx
->nold
; i
++)
2056 sshkey_free(ctx
->old_keys
[i
]);
2057 free(ctx
->old_keys
);
2058 free(ctx
->host_str
);
2064 * Returns non-zero if a known_hosts hostname list is not of a form that
2065 * can be handled by UpdateHostkeys. These include wildcard hostnames and
2066 * hostnames lists that do not follow the form host[,ip].
2069 hostspec_is_complex(const char *hosts
)
2074 if (strchr(hosts
, '*') != NULL
|| strchr(hosts
, '?') != NULL
)
2076 /* single host/ip = ok */
2077 if ((cp
= strchr(hosts
, ',')) == NULL
)
2079 /* more than two entries on the line */
2080 if (strchr(cp
+ 1, ',') != NULL
)
2082 /* XXX maybe parse cp+1 and ensure it is an IP? */
2086 /* callback to search for ctx->keys in known_hosts */
2088 hostkeys_find(struct hostkey_foreach_line
*l
, void *_ctx
)
2090 struct hostkeys_update_ctx
*ctx
= (struct hostkeys_update_ctx
*)_ctx
;
2092 struct sshkey
**tmp
;
2096 if (l
->status
!= HKF_STATUS_MATCHED
) {
2097 /* Record if one of the keys appears on a non-matching line */
2098 for (i
= 0; i
< ctx
->nkeys
; i
++) {
2099 if (sshkey_equal(l
->key
, ctx
->keys
[i
])) {
2100 ctx
->other_name_seen
= 1;
2101 debug3_f("found %s key under different "
2102 "name/addr at %s:%ld",
2103 sshkey_ssh_name(ctx
->keys
[i
]),
2104 l
->path
, l
->linenum
);
2110 /* Don't proceed if revocation or CA markers are present */
2111 /* XXX relax this */
2112 if (l
->marker
!= MRK_NONE
) {
2113 debug3_f("hostkeys file %s:%ld has CA/revocation marker",
2114 l
->path
, l
->linenum
);
2115 ctx
->complex_hostspec
= 1;
2119 /* If CheckHostIP is enabled, then check for mismatched hostname/addr */
2120 if (ctx
->ip_str
!= NULL
&& strchr(l
->hosts
, ',') != NULL
) {
2121 if ((l
->match
& HKF_MATCH_HOST
) == 0) {
2122 /* Record if address matched a different hostname. */
2123 ctx
->other_name_seen
= 1;
2124 debug3_f("found address %s against different hostname "
2125 "at %s:%ld", ctx
->ip_str
, l
->path
, l
->linenum
);
2127 } else if ((l
->match
& HKF_MATCH_IP
) == 0) {
2128 /* Record if hostname matched a different address. */
2129 ctx
->other_name_seen
= 1;
2130 debug3_f("found hostname %s against different address "
2131 "at %s:%ld", ctx
->host_str
, l
->path
, l
->linenum
);
2136 * UpdateHostkeys is skipped for wildcard host names and hostnames
2137 * that contain more than two entries (ssh never writes these).
2139 if (hostspec_is_complex(l
->hosts
)) {
2140 debug3_f("hostkeys file %s:%ld complex host specification",
2141 l
->path
, l
->linenum
);
2142 ctx
->complex_hostspec
= 1;
2146 /* Mark off keys we've already seen for this host */
2147 for (i
= 0; i
< ctx
->nkeys
; i
++) {
2148 if (!sshkey_equal(l
->key
, ctx
->keys
[i
]))
2150 debug3_f("found %s key at %s:%ld",
2151 sshkey_ssh_name(ctx
->keys
[i
]), l
->path
, l
->linenum
);
2152 ctx
->keys_match
[i
] |= l
->match
;
2155 /* This line contained a key that not offered by the server */
2156 debug3_f("deprecated %s key at %s:%ld", sshkey_ssh_name(l
->key
),
2157 l
->path
, l
->linenum
);
2158 if ((tmp
= recallocarray(ctx
->old_keys
, ctx
->nold
, ctx
->nold
+ 1,
2159 sizeof(*ctx
->old_keys
))) == NULL
)
2160 fatal_f("recallocarray failed nold = %zu", ctx
->nold
);
2161 ctx
->old_keys
= tmp
;
2162 ctx
->old_keys
[ctx
->nold
++] = l
->key
;
2168 /* callback to search for ctx->old_keys in known_hosts under other names */
2170 hostkeys_check_old(struct hostkey_foreach_line
*l
, void *_ctx
)
2172 struct hostkeys_update_ctx
*ctx
= (struct hostkeys_update_ctx
*)_ctx
;
2176 /* only care about lines that *don't* match the active host spec */
2177 if (l
->status
== HKF_STATUS_MATCHED
|| l
->key
== NULL
)
2180 hashed
= l
->match
& (HKF_MATCH_HOST_HASHED
|HKF_MATCH_IP_HASHED
);
2181 for (i
= 0; i
< ctx
->nold
; i
++) {
2182 if (!sshkey_equal(l
->key
, ctx
->old_keys
[i
]))
2184 debug3_f("found deprecated %s key at %s:%ld as %s",
2185 sshkey_ssh_name(ctx
->old_keys
[i
]), l
->path
, l
->linenum
,
2186 hashed
? "[HASHED]" : l
->hosts
);
2187 ctx
->old_key_seen
= 1;
2194 * Check known_hosts files for deprecated keys under other names. Returns 0
2195 * on success or -1 on failure. Updates ctx->old_key_seen if deprecated keys
2196 * exist under names other than the active hostname/IP.
2199 check_old_keys_othernames(struct hostkeys_update_ctx
*ctx
)
2204 debug2_f("checking for %zu deprecated keys", ctx
->nold
);
2205 for (i
= 0; i
< options
.num_user_hostfiles
; i
++) {
2206 debug3_f("searching %s for %s / %s",
2207 options
.user_hostfiles
[i
], ctx
->host_str
,
2208 ctx
->ip_str
? ctx
->ip_str
: "(none)");
2209 if ((r
= hostkeys_foreach(options
.user_hostfiles
[i
],
2210 hostkeys_check_old
, ctx
, ctx
->host_str
, ctx
->ip_str
,
2211 HKF_WANT_PARSE_KEY
, 0)) != 0) {
2212 if (r
== SSH_ERR_SYSTEM_ERROR
&& errno
== ENOENT
) {
2213 debug_f("hostkeys file %s does not exist",
2214 options
.user_hostfiles
[i
]);
2217 error_fr(r
, "hostkeys_foreach failed for %s",
2218 options
.user_hostfiles
[i
]);
2226 hostkey_change_preamble(LogLevel loglevel
)
2228 do_log2(loglevel
, "The server has updated its host keys.");
2229 do_log2(loglevel
, "These changes were verified by the server's "
2230 "existing trusted key.");
2234 update_known_hosts(struct hostkeys_update_ctx
*ctx
)
2236 int r
, was_raw
= 0, first
= 1;
2237 int asking
= options
.update_hostkeys
== SSH_UPDATE_HOSTKEYS_ASK
;
2238 LogLevel loglevel
= asking
? SYSLOG_LEVEL_INFO
: SYSLOG_LEVEL_VERBOSE
;
2239 char *fp
, *response
;
2243 for (i
= 0; i
< ctx
->nkeys
; i
++) {
2244 if (!ctx
->keys_verified
[i
])
2246 if ((fp
= sshkey_fingerprint(ctx
->keys
[i
],
2247 options
.fingerprint_hash
, SSH_FP_DEFAULT
)) == NULL
)
2248 fatal_f("sshkey_fingerprint failed");
2249 if (first
&& asking
)
2250 hostkey_change_preamble(loglevel
);
2251 do_log2(loglevel
, "Learned new hostkey: %s %s",
2252 sshkey_type(ctx
->keys
[i
]), fp
);
2256 for (i
= 0; i
< ctx
->nold
; i
++) {
2257 if ((fp
= sshkey_fingerprint(ctx
->old_keys
[i
],
2258 options
.fingerprint_hash
, SSH_FP_DEFAULT
)) == NULL
)
2259 fatal_f("sshkey_fingerprint failed");
2260 if (first
&& asking
)
2261 hostkey_change_preamble(loglevel
);
2262 do_log2(loglevel
, "Deprecating obsolete hostkey: %s %s",
2263 sshkey_type(ctx
->old_keys
[i
]), fp
);
2267 if (options
.update_hostkeys
== SSH_UPDATE_HOSTKEYS_ASK
) {
2268 if (get_saved_tio() != NULL
) {
2273 for (i
= 0; !quit_pending
&& i
< 3; i
++) {
2275 response
= read_passphrase("Accept updated hostkeys? "
2276 "(yes/no): ", RP_ECHO
);
2277 if (response
!= NULL
&& strcasecmp(response
, "yes") == 0)
2279 else if (quit_pending
|| response
== NULL
||
2280 strcasecmp(response
, "no") == 0) {
2281 options
.update_hostkeys
= 0;
2284 do_log2(loglevel
, "Please enter "
2285 "\"yes\" or \"no\"");
2288 if (quit_pending
|| i
>= 3 || response
== NULL
)
2289 options
.update_hostkeys
= 0;
2294 if (options
.update_hostkeys
== 0)
2297 * Now that all the keys are verified, we can go ahead and replace
2298 * them in known_hosts (assuming SSH_UPDATE_HOSTKEYS_ASK didn't
2299 * cancel the operation).
2301 for (i
= 0; i
< options
.num_user_hostfiles
; i
++) {
2303 * NB. keys are only added to hostfiles[0], for the rest we
2304 * just delete the hostname entries.
2306 if (stat(options
.user_hostfiles
[i
], &sb
) != 0) {
2307 if (errno
== ENOENT
) {
2308 debug_f("known hosts file %s does not "
2309 "exist", options
.user_hostfiles
[i
]);
2311 error_f("known hosts file %s "
2313 options
.user_hostfiles
[i
], strerror(errno
));
2317 if ((r
= hostfile_replace_entries(options
.user_hostfiles
[i
],
2318 ctx
->host_str
, ctx
->ip_str
,
2319 i
== 0 ? ctx
->keys
: NULL
, i
== 0 ? ctx
->nkeys
: 0,
2320 options
.hash_known_hosts
, 0,
2321 options
.fingerprint_hash
)) != 0) {
2322 error_fr(r
, "hostfile_replace_entries failed for %s",
2323 options
.user_hostfiles
[i
]);
2329 client_global_hostkeys_prove_confirm(struct ssh
*ssh
, int type
,
2330 u_int32_t seq
, void *_ctx
)
2332 struct hostkeys_update_ctx
*ctx
= (struct hostkeys_update_ctx
*)_ctx
;
2334 struct sshbuf
*signdata
;
2337 const char *rsa_kexalg
= NULL
;
2342 fatal_f("ctx->nnew == 0"); /* sanity */
2343 if (type
!= SSH2_MSG_REQUEST_SUCCESS
) {
2344 error("Server failed to confirm ownership of "
2345 "private host keys");
2346 hostkeys_update_ctx_free(ctx
);
2349 if (sshkey_type_plain(sshkey_type_from_name(
2350 ssh
->kex
->hostkey_alg
)) == KEY_RSA
)
2351 rsa_kexalg
= ssh
->kex
->hostkey_alg
;
2352 if ((signdata
= sshbuf_new()) == NULL
)
2353 fatal_f("sshbuf_new failed");
2355 * Expect a signature for each of the ctx->nnew private keys we
2356 * haven't seen before. They will be in the same order as the
2357 * ctx->keys where the corresponding ctx->keys_match[i] == 0.
2359 for (ndone
= i
= 0; i
< ctx
->nkeys
; i
++) {
2360 if (ctx
->keys_match
[i
])
2362 plaintype
= sshkey_type_plain(ctx
->keys
[i
]->type
);
2363 /* Prepare data to be signed: session ID, unique string, key */
2364 sshbuf_reset(signdata
);
2365 if ( (r
= sshbuf_put_cstring(signdata
,
2366 "hostkeys-prove-00@openssh.com")) != 0 ||
2367 (r
= sshbuf_put_stringb(signdata
,
2368 ssh
->kex
->session_id
)) != 0 ||
2369 (r
= sshkey_puts(ctx
->keys
[i
], signdata
)) != 0)
2370 fatal_fr(r
, "compose signdata");
2371 /* Extract and verify signature */
2372 if ((r
= sshpkt_get_string_direct(ssh
, &sig
, &siglen
)) != 0) {
2373 error_fr(r
, "parse sig");
2376 if ((r
= sshkey_get_sigtype(sig
, siglen
, &alg
)) != 0) {
2377 error_fr(r
, "server gave unintelligible signature "
2378 "for %s key %zu", sshkey_type(ctx
->keys
[i
]), i
);
2382 * Special case for RSA keys: if a RSA hostkey was negotiated,
2383 * then use its signature type for verification of RSA hostkey
2384 * proofs. Otherwise, accept only RSA-SHA256/512 signatures.
2386 if (plaintype
== KEY_RSA
&& rsa_kexalg
== NULL
&&
2387 match_pattern_list(alg
, HOSTKEY_PROOF_RSA_ALGS
, 0) != 1) {
2388 debug_f("server used untrusted RSA signature algorithm "
2389 "%s for key %zu, disregarding", alg
, i
);
2391 /* zap the key from the list */
2392 sshkey_free(ctx
->keys
[i
]);
2393 ctx
->keys
[i
] = NULL
;
2397 debug3_f("verify %s key %zu using sigalg %s",
2398 sshkey_type(ctx
->keys
[i
]), i
, alg
);
2400 if ((r
= sshkey_verify(ctx
->keys
[i
], sig
, siglen
,
2401 sshbuf_ptr(signdata
), sshbuf_len(signdata
),
2402 plaintype
== KEY_RSA
? rsa_kexalg
: NULL
, 0, NULL
)) != 0) {
2403 error_fr(r
, "server gave bad signature for %s key %zu",
2404 sshkey_type(ctx
->keys
[i
]), i
);
2407 /* Key is good. Mark it as 'seen' */
2408 ctx
->keys_verified
[i
] = 1;
2411 /* Shouldn't happen */
2412 if (ndone
!= ctx
->nnew
)
2413 fatal_f("ndone != ctx->nnew (%zu / %zu)", ndone
, ctx
->nnew
);
2414 if ((r
= sshpkt_get_end(ssh
)) != 0) {
2415 error_f("protocol error");
2419 /* Make the edits to known_hosts */
2420 update_known_hosts(ctx
);
2422 hostkeys_update_ctx_free(ctx
);
2423 hostkeys_update_complete
= 1;
2428 * Handle hostkeys-00@openssh.com global request to inform the client of all
2429 * the server's hostkeys. The keys are checked against the user's
2430 * HostkeyAlgorithms preference before they are accepted.
2433 client_input_hostkeys(struct ssh
*ssh
)
2435 const u_char
*blob
= NULL
;
2437 struct sshbuf
*buf
= NULL
;
2438 struct sshkey
*key
= NULL
, **tmp
;
2439 int r
, prove_sent
= 0;
2441 static int hostkeys_seen
= 0; /* XXX use struct ssh */
2442 extern struct sockaddr_storage hostaddr
; /* XXX from ssh.c */
2443 struct hostkeys_update_ctx
*ctx
= NULL
;
2447 fatal_f("server already sent hostkeys");
2448 if (!can_update_hostkeys())
2452 ctx
= xcalloc(1, sizeof(*ctx
));
2453 while (ssh_packet_remaining(ssh
) > 0) {
2456 if ((r
= sshpkt_get_string_direct(ssh
, &blob
, &len
)) != 0) {
2457 error_fr(r
, "parse key");
2460 if ((r
= sshkey_from_blob(blob
, len
, &key
)) != 0) {
2461 do_log2_fr(r
, r
== SSH_ERR_KEY_TYPE_UNKNOWN
?
2462 SYSLOG_LEVEL_DEBUG1
: SYSLOG_LEVEL_ERROR
,
2466 fp
= sshkey_fingerprint(key
, options
.fingerprint_hash
,
2468 debug3_f("received %s key %s", sshkey_type(key
), fp
);
2471 if (!hostkey_accepted_by_hostkeyalgs(key
)) {
2472 debug3_f("%s key not permitted by "
2473 "HostkeyAlgorithms", sshkey_ssh_name(key
));
2477 if (sshkey_is_cert(key
)) {
2478 debug3_f("%s key is a certificate; skipping",
2479 sshkey_ssh_name(key
));
2482 /* Ensure keys are unique */
2483 for (i
= 0; i
< ctx
->nkeys
; i
++) {
2484 if (sshkey_equal(key
, ctx
->keys
[i
])) {
2485 error_f("received duplicated %s host key",
2486 sshkey_ssh_name(key
));
2490 /* Key is good, record it */
2491 if ((tmp
= recallocarray(ctx
->keys
, ctx
->nkeys
, ctx
->nkeys
+ 1,
2492 sizeof(*ctx
->keys
))) == NULL
)
2493 fatal_f("recallocarray failed nkeys = %zu",
2496 ctx
->keys
[ctx
->nkeys
++] = key
;
2500 if (ctx
->nkeys
== 0) {
2501 debug_f("server sent no hostkeys");
2505 if ((ctx
->keys_match
= calloc(ctx
->nkeys
,
2506 sizeof(*ctx
->keys_match
))) == NULL
||
2507 (ctx
->keys_verified
= calloc(ctx
->nkeys
,
2508 sizeof(*ctx
->keys_verified
))) == NULL
)
2509 fatal_f("calloc failed");
2511 get_hostfile_hostname_ipaddr(host
,
2512 options
.check_host_ip
? (struct sockaddr
*)&hostaddr
: NULL
,
2513 options
.port
, &ctx
->host_str
,
2514 options
.check_host_ip
? &ctx
->ip_str
: NULL
);
2516 /* Find which keys we already know about. */
2517 for (i
= 0; i
< options
.num_user_hostfiles
; i
++) {
2518 debug_f("searching %s for %s / %s",
2519 options
.user_hostfiles
[i
], ctx
->host_str
,
2520 ctx
->ip_str
? ctx
->ip_str
: "(none)");
2521 if ((r
= hostkeys_foreach(options
.user_hostfiles
[i
],
2522 hostkeys_find
, ctx
, ctx
->host_str
, ctx
->ip_str
,
2523 HKF_WANT_PARSE_KEY
, 0)) != 0) {
2524 if (r
== SSH_ERR_SYSTEM_ERROR
&& errno
== ENOENT
) {
2525 debug_f("hostkeys file %s does not exist",
2526 options
.user_hostfiles
[i
]);
2529 error_fr(r
, "hostkeys_foreach failed for %s",
2530 options
.user_hostfiles
[i
]);
2535 /* Figure out if we have any new keys to add */
2536 ctx
->nnew
= ctx
->nincomplete
= 0;
2537 want
= HKF_MATCH_HOST
| ( options
.check_host_ip
? HKF_MATCH_IP
: 0);
2538 for (i
= 0; i
< ctx
->nkeys
; i
++) {
2539 if (ctx
->keys_match
[i
] == 0)
2541 if ((ctx
->keys_match
[i
] & want
) != want
)
2545 debug3_f("%zu server keys: %zu new, %zu retained, "
2546 "%zu incomplete match. %zu to remove", ctx
->nkeys
, ctx
->nnew
,
2547 ctx
->nkeys
- ctx
->nnew
- ctx
->nincomplete
,
2548 ctx
->nincomplete
, ctx
->nold
);
2550 if (ctx
->nnew
== 0 && ctx
->nold
== 0) {
2551 debug_f("no new or deprecated keys from server");
2555 /* Various reasons why we cannot proceed with the update */
2556 if (ctx
->complex_hostspec
) {
2557 debug_f("CA/revocation marker, manual host list or wildcard "
2558 "host pattern found, skipping UserKnownHostsFile update");
2561 if (ctx
->other_name_seen
) {
2562 debug_f("host key found matching a different name/address, "
2563 "skipping UserKnownHostsFile update");
2567 * If removing keys, check whether they appear under different
2568 * names/addresses and refuse to proceed if they do. This avoids
2569 * cases such as hosts with multiple names becoming inconsistent
2570 * with regards to CheckHostIP entries.
2571 * XXX UpdateHostkeys=force to override this (and other) checks?
2573 if (ctx
->nold
!= 0) {
2574 if (check_old_keys_othernames(ctx
) != 0)
2575 goto out
; /* error already logged */
2576 if (ctx
->old_key_seen
) {
2577 debug_f("key(s) for %s%s%s exist under other names; "
2578 "skipping UserKnownHostsFile update",
2579 ctx
->host_str
, ctx
->ip_str
== NULL
? "" : ",",
2580 ctx
->ip_str
== NULL
? "" : ctx
->ip_str
);
2585 if (ctx
->nnew
== 0) {
2587 * We have some keys to remove or fix matching for.
2588 * We can proceed to do this without requiring a fresh proof
2591 update_known_hosts(ctx
);
2595 * We have received previously-unseen keys from the server.
2596 * Ask the server to confirm ownership of the private halves.
2598 debug3_f("asking server to prove ownership for %zu keys", ctx
->nnew
);
2599 if ((r
= sshpkt_start(ssh
, SSH2_MSG_GLOBAL_REQUEST
)) != 0 ||
2600 (r
= sshpkt_put_cstring(ssh
,
2601 "hostkeys-prove-00@openssh.com")) != 0 ||
2602 (r
= sshpkt_put_u8(ssh
, 1)) != 0) /* bool: want reply */
2603 fatal_fr(r
, "prepare hostkeys-prove");
2604 if ((buf
= sshbuf_new()) == NULL
)
2605 fatal_f("sshbuf_new");
2606 for (i
= 0; i
< ctx
->nkeys
; i
++) {
2607 if (ctx
->keys_match
[i
])
2610 if ((r
= sshkey_putb(ctx
->keys
[i
], buf
)) != 0 ||
2611 (r
= sshpkt_put_stringb(ssh
, buf
)) != 0)
2612 fatal_fr(r
, "assemble hostkeys-prove");
2614 if ((r
= sshpkt_send(ssh
)) != 0)
2615 fatal_fr(r
, "send hostkeys-prove");
2616 client_register_global_confirm(
2617 client_global_hostkeys_prove_confirm
, ctx
);
2618 ctx
= NULL
; /* will be freed in callback */
2623 hostkeys_update_ctx_free(ctx
);
2627 /* UpdateHostkeys handling completed */
2628 hostkeys_update_complete
= 1;
2632 * NB. Return success for all cases. The server doesn't need to know
2633 * what the client does with its hosts file.
2639 client_input_global_request(int type
, u_int32_t seq
, struct ssh
*ssh
)
2645 if ((r
= sshpkt_get_cstring(ssh
, &rtype
, NULL
)) != 0 ||
2646 (r
= sshpkt_get_u8(ssh
, &want_reply
)) != 0)
2648 debug("client_input_global_request: rtype %s want_reply %d",
2650 if (strcmp(rtype
, "hostkeys-00@openssh.com") == 0)
2651 success
= client_input_hostkeys(ssh
);
2653 if ((r
= sshpkt_start(ssh
, success
? SSH2_MSG_REQUEST_SUCCESS
:
2654 SSH2_MSG_REQUEST_FAILURE
)) != 0 ||
2655 (r
= sshpkt_send(ssh
)) != 0 ||
2656 (r
= ssh_packet_write_wait(ssh
)) != 0)
2666 client_send_env(struct ssh
*ssh
, int id
, const char *name
, const char *val
)
2670 debug("channel %d: setting env %s = \"%s\"", id
, name
, val
);
2671 channel_request_start(ssh
, id
, "env", 0);
2672 if ((r
= sshpkt_put_cstring(ssh
, name
)) != 0 ||
2673 (r
= sshpkt_put_cstring(ssh
, val
)) != 0 ||
2674 (r
= sshpkt_send(ssh
)) != 0)
2675 fatal_fr(r
, "send setenv");
2679 client_session2_setup(struct ssh
*ssh
, int id
, int want_tty
, int want_subsystem
,
2680 const char *term
, struct termios
*tiop
, int in_fd
, struct sshbuf
*cmd
,
2688 debug2_f("id %d", id
);
2690 if ((c
= channel_lookup(ssh
, id
)) == NULL
)
2691 fatal_f("channel %d: unknown channel", id
);
2693 ssh_packet_set_interactive(ssh
, want_tty
,
2694 options
.ip_qos_interactive
, options
.ip_qos_bulk
);
2699 /* Store window size in the packet. */
2700 if (ioctl(in_fd
, TIOCGWINSZ
, &ws
) == -1)
2701 memset(&ws
, 0, sizeof(ws
));
2703 channel_request_start(ssh
, id
, "pty-req", 1);
2704 client_expect_confirm(ssh
, id
, "PTY allocation", CONFIRM_TTY
);
2705 if ((r
= sshpkt_put_cstring(ssh
, term
!= NULL
? term
: ""))
2707 (r
= sshpkt_put_u32(ssh
, (u_int
)ws
.ws_col
)) != 0 ||
2708 (r
= sshpkt_put_u32(ssh
, (u_int
)ws
.ws_row
)) != 0 ||
2709 (r
= sshpkt_put_u32(ssh
, (u_int
)ws
.ws_xpixel
)) != 0 ||
2710 (r
= sshpkt_put_u32(ssh
, (u_int
)ws
.ws_ypixel
)) != 0)
2711 fatal_fr(r
, "build pty-req");
2713 tiop
= get_saved_tio();
2714 ssh_tty_make_modes(ssh
, -1, tiop
);
2715 if ((r
= sshpkt_send(ssh
)) != 0)
2716 fatal_fr(r
, "send pty-req");
2717 /* XXX wait for reply */
2721 /* Transfer any environment variables from client to server */
2722 if (options
.num_send_env
!= 0 && env
!= NULL
) {
2723 debug("Sending environment.");
2724 for (i
= 0; env
[i
] != NULL
; i
++) {
2726 name
= xstrdup(env
[i
]);
2727 if ((val
= strchr(name
, '=')) == NULL
) {
2734 for (j
= 0; j
< options
.num_send_env
; j
++) {
2735 if (match_pattern(name
, options
.send_env
[j
])) {
2741 debug3("Ignored env %s", name
);
2745 client_send_env(ssh
, id
, name
, val
);
2749 for (i
= 0; i
< options
.num_setenv
; i
++) {
2751 name
= xstrdup(options
.setenv
[i
]);
2752 if ((val
= strchr(name
, '=')) == NULL
) {
2757 client_send_env(ssh
, id
, name
, val
);
2761 len
= sshbuf_len(cmd
);
2765 if (want_subsystem
) {
2766 debug("Sending subsystem: %.*s",
2767 (int)len
, (const u_char
*)sshbuf_ptr(cmd
));
2768 channel_request_start(ssh
, id
, "subsystem", 1);
2769 client_expect_confirm(ssh
, id
, "subsystem",
2772 debug("Sending command: %.*s",
2773 (int)len
, (const u_char
*)sshbuf_ptr(cmd
));
2774 channel_request_start(ssh
, id
, "exec", 1);
2775 client_expect_confirm(ssh
, id
, "exec", CONFIRM_CLOSE
);
2777 if ((r
= sshpkt_put_stringb(ssh
, cmd
)) != 0 ||
2778 (r
= sshpkt_send(ssh
)) != 0)
2779 fatal_fr(r
, "send command");
2781 channel_request_start(ssh
, id
, "shell", 1);
2782 client_expect_confirm(ssh
, id
, "shell", CONFIRM_CLOSE
);
2783 if ((r
= sshpkt_send(ssh
)) != 0)
2784 fatal_fr(r
, "send shell");
2787 session_setup_complete
= 1;
2792 client_init_dispatch(struct ssh
*ssh
)
2794 ssh_dispatch_init(ssh
, &dispatch_protocol_error
);
2796 ssh_dispatch_set(ssh
, SSH2_MSG_CHANNEL_CLOSE
, &channel_input_oclose
);
2797 ssh_dispatch_set(ssh
, SSH2_MSG_CHANNEL_DATA
, &channel_input_data
);
2798 ssh_dispatch_set(ssh
, SSH2_MSG_CHANNEL_EOF
, &channel_input_ieof
);
2799 ssh_dispatch_set(ssh
, SSH2_MSG_CHANNEL_EXTENDED_DATA
, &channel_input_extended_data
);
2800 ssh_dispatch_set(ssh
, SSH2_MSG_CHANNEL_OPEN
, &client_input_channel_open
);
2801 ssh_dispatch_set(ssh
, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION
, &channel_input_open_confirmation
);
2802 ssh_dispatch_set(ssh
, SSH2_MSG_CHANNEL_OPEN_FAILURE
, &channel_input_open_failure
);
2803 ssh_dispatch_set(ssh
, SSH2_MSG_CHANNEL_REQUEST
, &client_input_channel_req
);
2804 ssh_dispatch_set(ssh
, SSH2_MSG_CHANNEL_WINDOW_ADJUST
, &channel_input_window_adjust
);
2805 ssh_dispatch_set(ssh
, SSH2_MSG_CHANNEL_SUCCESS
, &channel_input_status_confirm
);
2806 ssh_dispatch_set(ssh
, SSH2_MSG_CHANNEL_FAILURE
, &channel_input_status_confirm
);
2807 ssh_dispatch_set(ssh
, SSH2_MSG_GLOBAL_REQUEST
, &client_input_global_request
);
2810 ssh_dispatch_set(ssh
, SSH2_MSG_KEXINIT
, &kex_input_kexinit
);
2812 /* global request reply messages */
2813 ssh_dispatch_set(ssh
, SSH2_MSG_REQUEST_FAILURE
, &client_global_request_reply
);
2814 ssh_dispatch_set(ssh
, SSH2_MSG_REQUEST_SUCCESS
, &client_global_request_reply
);
2818 client_stop_mux(void)
2820 if (options
.control_path
!= NULL
&& muxserver_sock
!= -1)
2821 unlink(options
.control_path
);
2823 * If we are in persist mode, or don't have a shell, signal that we
2824 * should close when all active channels are closed.
2826 if (options
.control_persist
|| options
.session_type
== SESSION_TYPE_NONE
) {
2828 setproctitle("[stopped mux]");
2832 /* client specific fatal cleanup */
2836 leave_raw_mode(options
.request_tty
== REQUEST_TTY_FORCE
);
2837 if (options
.control_path
!= NULL
&& muxserver_sock
!= -1)
2838 unlink(options
.control_path
);
2839 ssh_kill_proxy_command();