1 /* $OpenBSD: clientloop.c,v 1.410 2024/12/03 22:30:03 jsg 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
, <))
664 /* ...unless there's x11 communication happening */
665 return x11_channel_used_recently(ssh
);
667 /* Calculate number of intervals missed since the last check */
668 n
= (now
.tv_sec
- next_interval
.tv_sec
) * 1000LL * 1000 * 1000;
669 n
+= now
.tv_nsec
- next_interval
.tv_nsec
;
670 n
/= options
.obscure_keystroke_timing_interval
* 1000LL * 1000;
671 n
= (n
< 0) ? 1 : n
+ 1;
673 /* Advance to the next interval */
674 set_next_interval(&now
, &next_interval
,
675 options
.obscure_keystroke_timing_interval
* n
, 0);
680 * Waits until the client can do something (some data becomes available on
681 * one of the file descriptors).
684 client_wait_until_can_do_something(struct ssh
*ssh
, struct pollfd
**pfdp
,
685 u_int
*npfd_allocp
, u_int
*npfd_activep
, int channel_did_enqueue
,
686 sigset_t
*sigsetp
, int *conn_in_readyp
, int *conn_out_readyp
)
688 struct timespec timeout
;
692 *conn_in_readyp
= *conn_out_readyp
= 0;
694 /* Prepare channel poll. First two pollfd entries are reserved */
695 ptimeout_init(&timeout
);
696 channel_prepare_poll(ssh
, pfdp
, npfd_allocp
, npfd_activep
, 2, &timeout
);
697 if (*npfd_activep
< 2)
698 fatal_f("bad npfd %u", *npfd_activep
); /* shouldn't happen */
700 /* channel_prepare_poll could have closed the last channel */
701 if (session_closed
&& !channel_still_open(ssh
) &&
702 !ssh_packet_have_data_to_write(ssh
)) {
703 /* clear events since we did not call poll() */
704 for (p
= 0; p
< *npfd_activep
; p
++)
705 (*pfdp
)[p
].revents
= 0;
709 oready
= obfuscate_keystroke_timing(ssh
, &timeout
, channel_did_enqueue
);
711 /* Monitor server connection on reserved pollfd entries */
712 (*pfdp
)[0].fd
= connection_in
;
713 (*pfdp
)[0].events
= POLLIN
;
714 (*pfdp
)[1].fd
= connection_out
;
715 (*pfdp
)[1].events
= (oready
&& ssh_packet_have_data_to_write(ssh
)) ?
719 * Wait for something to happen. This will suspend the process until
720 * some polled descriptor can be read, written, or has some other
721 * event pending, or a timeout expires.
723 set_control_persist_exit_time(ssh
);
724 if (control_persist_exit_time
> 0)
725 ptimeout_deadline_monotime(&timeout
, control_persist_exit_time
);
726 if (options
.server_alive_interval
> 0)
727 ptimeout_deadline_monotime(&timeout
, server_alive_time
);
728 if (options
.rekey_interval
> 0 && !ssh_packet_is_rekeying(ssh
)) {
729 ptimeout_deadline_sec(&timeout
,
730 ssh_packet_get_rekey_timeout(ssh
));
733 ret
= ppoll(*pfdp
, *npfd_activep
, ptimeout_get_tsp(&timeout
), sigsetp
);
737 * We have to clear the events because we return.
738 * We have to return, because the mainloop checks for the flags
739 * set by the signal handlers.
741 for (p
= 0; p
< *npfd_activep
; p
++)
742 (*pfdp
)[p
].revents
= 0;
745 /* Note: we might still have data in the buffers. */
746 quit_message("poll: %s", strerror(errno
));
750 *conn_in_readyp
= (*pfdp
)[0].revents
!= 0;
751 *conn_out_readyp
= (*pfdp
)[1].revents
!= 0;
753 if (options
.server_alive_interval
> 0 && !*conn_in_readyp
&&
754 monotime() >= server_alive_time
) {
756 * ServerAlive check is needed. We can't rely on the poll
757 * timing out since traffic on the client side such as port
758 * forwards can keep waking it up.
760 server_alive_check(ssh
);
765 client_suspend_self(struct sshbuf
*bin
, struct sshbuf
*bout
, struct sshbuf
*berr
)
767 /* Flush stdout and stderr buffers. */
768 if (sshbuf_len(bout
) > 0)
769 atomicio(vwrite
, fileno(stdout
), sshbuf_mutable_ptr(bout
),
771 if (sshbuf_len(berr
) > 0)
772 atomicio(vwrite
, fileno(stderr
), sshbuf_mutable_ptr(berr
),
775 leave_raw_mode(options
.request_tty
== REQUEST_TTY_FORCE
);
781 /* Send the suspend signal to the program itself. */
782 kill(getpid(), SIGTSTP
);
784 /* Reset window sizes in case they have changed */
785 received_window_change_signal
= 1;
787 enter_raw_mode(options
.request_tty
== REQUEST_TTY_FORCE
);
791 client_process_net_input(struct ssh
*ssh
)
796 * Read input from the server, and add any such data to the buffer of
797 * the packet subsystem.
799 schedule_server_alive_check();
800 if ((r
= ssh_packet_process_read(ssh
, connection_in
)) == 0)
801 return; /* success */
802 if (r
== SSH_ERR_SYSTEM_ERROR
) {
803 if (errno
== EAGAIN
|| errno
== EINTR
|| errno
== EWOULDBLOCK
)
805 if (errno
== EPIPE
) {
806 quit_message("Connection to %s closed by remote host.",
811 quit_message("Read from remote host %s: %s", host
, ssh_err(r
));
815 client_status_confirm(struct ssh
*ssh
, int type
, Channel
*c
, void *ctx
)
817 struct channel_reply_ctx
*cr
= (struct channel_reply_ctx
*)ctx
;
822 * If a TTY was explicitly requested, then a failure to allocate
825 if (cr
->action
== CONFIRM_TTY
&&
826 (options
.request_tty
== REQUEST_TTY_FORCE
||
827 options
.request_tty
== REQUEST_TTY_YES
))
828 cr
->action
= CONFIRM_CLOSE
;
830 /* XXX suppress on mux _client_ quietmode */
831 tochan
= options
.log_level
>= SYSLOG_LEVEL_ERROR
&&
832 c
->ctl_chan
!= -1 && c
->extended_usage
== CHAN_EXTENDED_WRITE
;
834 if (type
== SSH2_MSG_CHANNEL_SUCCESS
) {
835 debug2("%s request accepted on channel %d",
836 cr
->request_type
, c
->self
);
837 } else if (type
== SSH2_MSG_CHANNEL_FAILURE
) {
839 snprintf(errmsg
, sizeof(errmsg
),
840 "%s request failed\r\n", cr
->request_type
);
842 snprintf(errmsg
, sizeof(errmsg
),
843 "%s request failed on channel %d",
844 cr
->request_type
, c
->self
);
846 /* If error occurred on primary session channel, then exit */
847 if (cr
->action
== CONFIRM_CLOSE
&& c
->self
== session_ident
)
850 * If error occurred on mux client, append to
854 debug3_f("channel %d: mux request: %s", c
->self
,
856 if ((r
= sshbuf_put(c
->extended
, errmsg
,
857 strlen(errmsg
))) != 0)
858 fatal_fr(r
, "sshbuf_put");
861 if (cr
->action
== CONFIRM_TTY
) {
863 * If a TTY allocation error occurred, then arrange
864 * for the correct TTY to leave raw mode.
866 if (c
->self
== session_ident
)
869 mux_tty_alloc_failed(ssh
, c
);
870 } else if (cr
->action
== CONFIRM_CLOSE
) {
871 chan_read_failed(ssh
, c
);
872 chan_write_failed(ssh
, c
);
879 client_abandon_status_confirm(struct ssh
*ssh
, Channel
*c
, void *ctx
)
885 client_expect_confirm(struct ssh
*ssh
, int id
, const char *request
,
886 enum confirm_action action
)
888 struct channel_reply_ctx
*cr
= xcalloc(1, sizeof(*cr
));
890 cr
->request_type
= request
;
893 channel_register_status_confirm(ssh
, id
, client_status_confirm
,
894 client_abandon_status_confirm
, cr
);
898 client_register_global_confirm(global_confirm_cb
*cb
, void *ctx
)
900 struct global_confirm
*gc
, *last_gc
;
902 /* Coalesce identical callbacks */
903 last_gc
= TAILQ_LAST(&global_confirms
, global_confirms
);
904 if (last_gc
&& last_gc
->cb
== cb
&& last_gc
->ctx
== ctx
) {
905 if (++last_gc
->ref_count
>= INT_MAX
)
906 fatal_f("last_gc->ref_count = %d",
911 gc
= xcalloc(1, sizeof(*gc
));
915 TAILQ_INSERT_TAIL(&global_confirms
, gc
, entry
);
919 * Returns non-zero if the client is able to handle a hostkeys-00@openssh.com
920 * hostkey update request.
923 can_update_hostkeys(void)
925 if (hostkeys_update_complete
)
927 if (options
.update_hostkeys
== SSH_UPDATE_HOSTKEYS_ASK
&&
929 return 0; /* won't ask in batchmode, so don't even try */
930 if (!options
.update_hostkeys
|| options
.num_user_hostfiles
<= 0)
936 client_repledge(void)
940 /* Might be able to tighten pledge now that session is established */
941 if (options
.control_master
|| options
.control_path
!= NULL
||
942 options
.forward_x11
|| options
.fork_after_authentication
||
943 can_update_hostkeys() ||
944 (session_ident
!= -1 && !session_setup_complete
)) {
949 * LocalCommand and UpdateHostkeys have finished, so can get rid of
952 * XXX protocol allows a server can to change hostkeys during the
953 * connection at rekey time that could trigger a hostkeys update
954 * but AFAIK no implementations support this. Could improve by
955 * forcing known_hosts to be read-only or via unveil(2).
957 if (options
.num_local_forwards
!= 0 ||
958 options
.num_remote_forwards
!= 0 ||
959 options
.num_permitted_remote_opens
!= 0 ||
960 options
.enable_escape_commandline
!= 0) {
961 /* rfwd needs inet */
962 debug("pledge: network");
963 if (pledge("stdio unix inet dns proc tty", NULL
) == -1)
964 fatal_f("pledge(): %s", strerror(errno
));
965 } else if (options
.forward_agent
!= 0) {
966 /* agent forwarding needs to open $SSH_AUTH_SOCK at will */
967 debug("pledge: agent");
968 if (pledge("stdio unix proc tty", NULL
) == -1)
969 fatal_f("pledge(): %s", strerror(errno
));
971 debug("pledge: fork");
972 if (pledge("stdio proc tty", NULL
) == -1)
973 fatal_f("pledge(): %s", strerror(errno
));
975 /* XXX further things to do:
977 * - might be able to get rid of proc if we kill ~^Z
978 * - ssh -N (no session)
980 * - sessions without tty
985 process_cmdline(struct ssh
*ssh
)
987 void (*handler
)(int);
989 int ok
, delete = 0, local
= 0, remote
= 0, dynamic
= 0;
992 memset(&fwd
, 0, sizeof(fwd
));
994 leave_raw_mode(options
.request_tty
== REQUEST_TTY_FORCE
);
995 handler
= ssh_signal(SIGINT
, SIG_IGN
);
996 cmd
= s
= read_passphrase("\r\nssh> ", RP_ECHO
);
999 while (isspace((u_char
)*s
))
1002 s
++; /* Skip cmdline '-', if any */
1006 if (*s
== 'h' || *s
== 'H' || *s
== '?') {
1008 logit(" -L[bind_address:]port:host:hostport "
1009 "Request local forward");
1010 logit(" -R[bind_address:]port:host:hostport "
1011 "Request remote forward");
1012 logit(" -D[bind_address:]port "
1013 "Request dynamic forward");
1014 logit(" -KL[bind_address:]port "
1015 "Cancel local forward");
1016 logit(" -KR[bind_address:]port "
1017 "Cancel remote forward");
1018 logit(" -KD[bind_address:]port "
1019 "Cancel dynamic forward");
1020 if (!options
.permit_local_command
)
1023 "Execute local command");
1027 if (*s
== '!' && options
.permit_local_command
) {
1044 logit("Invalid command.");
1048 while (isspace((u_char
)*++s
))
1051 /* XXX update list of forwards in options */
1053 /* We pass 1 for dynamicfwd to restrict to 1 or 2 fields. */
1054 if (!parse_forward(&fwd
, s
, 1, 0)) {
1055 logit("Bad forwarding close specification.");
1059 ok
= channel_request_rforward_cancel(ssh
, &fwd
) == 0;
1061 ok
= channel_cancel_lport_listener(ssh
, &fwd
,
1062 0, &options
.fwd_opts
) > 0;
1064 ok
= channel_cancel_lport_listener(ssh
, &fwd
,
1065 CHANNEL_CANCEL_PORT_STATIC
,
1066 &options
.fwd_opts
) > 0;
1068 logit("Unknown port forwarding.");
1071 logit("Canceled forwarding.");
1073 /* -R specs can be both dynamic or not, so check both. */
1075 if (!parse_forward(&fwd
, s
, 0, remote
) &&
1076 !parse_forward(&fwd
, s
, 1, remote
)) {
1077 logit("Bad remote forwarding specification.");
1080 } else if (!parse_forward(&fwd
, s
, dynamic
, remote
)) {
1081 logit("Bad local forwarding specification.");
1084 if (local
|| dynamic
) {
1085 if (!channel_setup_local_fwd_listener(ssh
, &fwd
,
1086 &options
.fwd_opts
)) {
1087 logit("Port forwarding failed.");
1091 if (channel_request_remote_forwarding(ssh
, &fwd
) < 0) {
1092 logit("Port forwarding failed.");
1096 logit("Forwarding port.");
1100 ssh_signal(SIGINT
, handler
);
1101 enter_raw_mode(options
.request_tty
== REQUEST_TTY_FORCE
);
1103 free(fwd
.listen_host
);
1104 free(fwd
.listen_path
);
1105 free(fwd
.connect_host
);
1106 free(fwd
.connect_path
);
1109 /* reasons to suppress output of an escape command in help output */
1110 #define SUPPRESS_NEVER 0 /* never suppress, always show */
1111 #define SUPPRESS_MUXCLIENT 1 /* don't show in mux client sessions */
1112 #define SUPPRESS_MUXMASTER 2 /* don't show in mux master sessions */
1113 #define SUPPRESS_SYSLOG 4 /* don't show when logging to syslog */
1114 #define SUPPRESS_NOCMDLINE 8 /* don't show when cmdline disabled*/
1115 struct escape_help_text
{
1120 static struct escape_help_text esc_txt
[] = {
1121 {".", "terminate session", SUPPRESS_MUXMASTER
},
1122 {".", "terminate connection (and any multiplexed sessions)",
1123 SUPPRESS_MUXCLIENT
},
1124 {"B", "send a BREAK to the remote system", SUPPRESS_NEVER
},
1125 {"C", "open a command line", SUPPRESS_MUXCLIENT
|SUPPRESS_NOCMDLINE
},
1126 {"R", "request rekey", SUPPRESS_NEVER
},
1127 {"V/v", "decrease/increase verbosity (LogLevel)", SUPPRESS_MUXCLIENT
},
1128 {"^Z", "suspend ssh", SUPPRESS_MUXCLIENT
},
1129 {"#", "list forwarded connections", SUPPRESS_NEVER
},
1130 {"&", "background ssh (when waiting for connections to terminate)",
1131 SUPPRESS_MUXCLIENT
},
1132 {"?", "this message", SUPPRESS_NEVER
},
1136 print_escape_help(struct sshbuf
*b
, int escape_char
, int mux_client
,
1139 unsigned int i
, suppress_flags
;
1142 if ((r
= sshbuf_putf(b
,
1143 "%c?\r\nSupported escape sequences:\r\n", escape_char
)) != 0)
1144 fatal_fr(r
, "sshbuf_putf");
1147 (mux_client
? SUPPRESS_MUXCLIENT
: 0) |
1148 (mux_client
? 0 : SUPPRESS_MUXMASTER
) |
1149 (using_stderr
? 0 : SUPPRESS_SYSLOG
) |
1150 (options
.enable_escape_commandline
== 0 ? SUPPRESS_NOCMDLINE
: 0);
1152 for (i
= 0; i
< sizeof(esc_txt
)/sizeof(esc_txt
[0]); i
++) {
1153 if (esc_txt
[i
].flags
& suppress_flags
)
1155 if ((r
= sshbuf_putf(b
, " %c%-3s - %s\r\n",
1156 escape_char
, esc_txt
[i
].cmd
, esc_txt
[i
].text
)) != 0)
1157 fatal_fr(r
, "sshbuf_putf");
1160 if ((r
= sshbuf_putf(b
,
1161 " %c%c - send the escape character by typing it twice\r\n"
1162 "(Note that escapes are only recognized immediately after "
1163 "newline.)\r\n", escape_char
, escape_char
)) != 0)
1164 fatal_fr(r
, "sshbuf_putf");
1168 * Process the characters one by one.
1171 process_escapes(struct ssh
*ssh
, Channel
*c
,
1172 struct sshbuf
*bin
, struct sshbuf
*bout
, struct sshbuf
*berr
,
1180 struct escape_filter_ctx
*efc
;
1182 if (c
== NULL
|| c
->filter_ctx
== NULL
|| len
<= 0)
1185 efc
= (struct escape_filter_ctx
*)c
->filter_ctx
;
1187 for (i
= 0; i
< (u_int
)len
; i
++) {
1188 /* Get one character at a time. */
1191 if (efc
->escape_pending
) {
1192 /* We have previously seen an escape character. */
1193 /* Clear the flag now. */
1194 efc
->escape_pending
= 0;
1196 /* Process the escaped character. */
1199 /* Terminate the connection. */
1200 if ((r
= sshbuf_putf(berr
, "%c.\r\n",
1201 efc
->escape_char
)) != 0)
1202 fatal_fr(r
, "sshbuf_putf");
1203 if (c
&& c
->ctl_chan
!= -1) {
1204 channel_force_close(ssh
, c
, 1);
1211 /* XXX support this for mux clients */
1212 if (c
&& c
->ctl_chan
!= -1) {
1216 snprintf(b
, sizeof b
, "^Z");
1218 snprintf(b
, sizeof b
, "%c", ch
);
1219 if ((r
= sshbuf_putf(berr
,
1220 "%c%s escape not available to "
1221 "multiplexed sessions\r\n",
1222 efc
->escape_char
, b
)) != 0)
1223 fatal_fr(r
, "sshbuf_putf");
1226 /* Suspend the program. Inform the user */
1227 if ((r
= sshbuf_putf(berr
,
1228 "%c^Z [suspend ssh]\r\n",
1229 efc
->escape_char
)) != 0)
1230 fatal_fr(r
, "sshbuf_putf");
1232 /* Restore terminal modes and suspend. */
1233 client_suspend_self(bin
, bout
, berr
);
1235 /* We have been continued. */
1239 if ((r
= sshbuf_putf(berr
,
1240 "%cB\r\n", efc
->escape_char
)) != 0)
1241 fatal_fr(r
, "sshbuf_putf");
1242 channel_request_start(ssh
, c
->self
, "break", 0);
1243 if ((r
= sshpkt_put_u32(ssh
, 1000)) != 0 ||
1244 (r
= sshpkt_send(ssh
)) != 0)
1245 fatal_fr(r
, "send packet");
1249 if (ssh
->compat
& SSH_BUG_NOREKEY
)
1250 logit("Server does not "
1251 "support re-keying");
1259 if (c
&& c
->ctl_chan
!= -1)
1261 if (!log_is_on_stderr()) {
1262 if ((r
= sshbuf_putf(berr
,
1263 "%c%c [Logging to syslog]\r\n",
1264 efc
->escape_char
, ch
)) != 0)
1265 fatal_fr(r
, "sshbuf_putf");
1268 if (ch
== 'V' && options
.log_level
>
1270 log_change_level(--options
.log_level
);
1271 if (ch
== 'v' && options
.log_level
<
1272 SYSLOG_LEVEL_DEBUG3
)
1273 log_change_level(++options
.log_level
);
1274 if ((r
= sshbuf_putf(berr
,
1275 "%c%c [LogLevel %s]\r\n",
1276 efc
->escape_char
, ch
,
1277 log_level_name(options
.log_level
))) != 0)
1278 fatal_fr(r
, "sshbuf_putf");
1282 if (c
->ctl_chan
!= -1)
1285 * Detach the program (continue to serve
1286 * connections, but put in background and no
1287 * more new connections).
1289 /* Restore tty modes. */
1291 options
.request_tty
== REQUEST_TTY_FORCE
);
1293 /* Stop listening for new connections. */
1294 channel_stop_listening(ssh
);
1296 if ((r
= sshbuf_putf(berr
, "%c& "
1297 "[backgrounded]\n", efc
->escape_char
)) != 0)
1298 fatal_fr(r
, "sshbuf_putf");
1300 /* Fork into background. */
1303 error("fork: %.100s", strerror(errno
));
1306 if (pid
!= 0) { /* This is the parent. */
1307 /* The parent just exits. */
1310 /* The child continues serving connections. */
1311 /* fake EOF on stdin */
1312 if ((r
= sshbuf_put_u8(bin
, 4)) != 0)
1313 fatal_fr(r
, "sshbuf_put_u8");
1316 print_escape_help(berr
, efc
->escape_char
,
1317 (c
&& c
->ctl_chan
!= -1),
1318 log_is_on_stderr());
1322 if ((r
= sshbuf_putf(berr
, "%c#\r\n",
1323 efc
->escape_char
)) != 0)
1324 fatal_fr(r
, "sshbuf_putf");
1325 s
= channel_open_message(ssh
);
1326 if ((r
= sshbuf_put(berr
, s
, strlen(s
))) != 0)
1327 fatal_fr(r
, "sshbuf_put");
1332 if (c
&& c
->ctl_chan
!= -1)
1334 if (options
.enable_escape_commandline
== 0) {
1335 if ((r
= sshbuf_putf(berr
,
1336 "commandline disabled\r\n")) != 0)
1337 fatal_fr(r
, "sshbuf_putf");
1340 process_cmdline(ssh
);
1344 if (ch
!= efc
->escape_char
) {
1345 if ((r
= sshbuf_put_u8(bin
,
1346 efc
->escape_char
)) != 0)
1347 fatal_fr(r
, "sshbuf_put_u8");
1350 /* Escaped characters fall through here */
1355 * The previous character was not an escape char.
1356 * Check if this is an escape.
1358 if (last_was_cr
&& ch
== efc
->escape_char
) {
1360 * It is. Set the flag and continue to
1363 efc
->escape_pending
= 1;
1369 * Normal character. Record whether it was a newline,
1370 * and append it to the buffer.
1372 last_was_cr
= (ch
== '\r' || ch
== '\n');
1373 if ((r
= sshbuf_put_u8(bin
, ch
)) != 0)
1374 fatal_fr(r
, "sshbuf_put_u8");
1381 * Get packets from the connection input buffer, and process them as long as
1382 * there are packets available.
1384 * Any unknown packets received during the actual
1385 * session cause the session to terminate. This is
1386 * intended to make debugging easier since no
1387 * confirmations are sent. Any compatible protocol
1388 * extensions must be negotiated during the
1389 * preparatory phase.
1393 client_process_buffered_input_packets(struct ssh
*ssh
)
1395 ssh_dispatch_run_fatal(ssh
, DISPATCH_NONBLOCK
, &quit_pending
);
1398 /* scan buf[] for '~' before sending data to the peer */
1400 /* Helper: allocate a new escape_filter_ctx and fill in its escape char */
1402 client_new_escape_filter_ctx(int escape_char
)
1404 struct escape_filter_ctx
*ret
;
1406 ret
= xcalloc(1, sizeof(*ret
));
1407 ret
->escape_pending
= 0;
1408 ret
->escape_char
= escape_char
;
1412 /* Free the escape filter context on channel free */
1414 client_filter_cleanup(struct ssh
*ssh
, int cid
, void *ctx
)
1420 client_simple_escape_filter(struct ssh
*ssh
, Channel
*c
, char *buf
, int len
)
1422 if (c
->extended_usage
!= CHAN_EXTENDED_WRITE
)
1425 return process_escapes(ssh
, c
, c
->input
, c
->output
, c
->extended
,
1430 client_channel_closed(struct ssh
*ssh
, int id
, int force
, void *arg
)
1432 channel_cancel_cleanup(ssh
, id
);
1434 leave_raw_mode(options
.request_tty
== REQUEST_TTY_FORCE
);
1438 * Implements the interactive session with the server. This is called after
1439 * the user has been authenticated, and a command has been started on the
1440 * remote host. If escape_char != SSH_ESCAPECHAR_NONE, it is the character
1441 * used as an escape character for terminating or suspending the session.
1444 client_loop(struct ssh
*ssh
, int have_pty
, int escape_char_arg
,
1447 struct pollfd
*pfd
= NULL
;
1448 u_int npfd_alloc
= 0, npfd_active
= 0;
1449 double start_time
, total_time
;
1450 int channel_did_enqueue
= 0, r
;
1451 u_int64_t ibytes
, obytes
;
1452 int conn_in_ready
, conn_out_ready
;
1453 sigset_t bsigset
, osigset
;
1455 debug("Entering interactive session.");
1456 session_ident
= ssh2_chan_id
;
1458 if (options
.control_master
&&
1459 !option_clear_or_none(options
.control_path
)) {
1460 debug("pledge: id");
1461 if (pledge("stdio rpath wpath cpath unix inet dns recvfd sendfd proc exec id tty",
1463 fatal_f("pledge(): %s", strerror(errno
));
1465 } else if (options
.forward_x11
|| options
.permit_local_command
) {
1466 debug("pledge: exec");
1467 if (pledge("stdio rpath wpath cpath unix inet dns proc exec tty",
1469 fatal_f("pledge(): %s", strerror(errno
));
1471 } else if (options
.update_hostkeys
) {
1472 debug("pledge: filesystem");
1473 if (pledge("stdio rpath wpath cpath unix inet dns proc tty",
1475 fatal_f("pledge(): %s", strerror(errno
));
1477 } else if (!option_clear_or_none(options
.proxy_command
) ||
1478 options
.fork_after_authentication
) {
1479 debug("pledge: proc");
1480 if (pledge("stdio cpath unix inet dns proc tty", NULL
) == -1)
1481 fatal_f("pledge(): %s", strerror(errno
));
1484 debug("pledge: network");
1485 if (pledge("stdio unix inet dns proc tty", NULL
) == -1)
1486 fatal_f("pledge(): %s", strerror(errno
));
1489 /* might be able to tighten now */
1492 start_time
= monotime_double();
1494 /* Initialize variables. */
1497 connection_in
= ssh_packet_get_connection_in(ssh
);
1498 connection_out
= ssh_packet_get_connection_out(ssh
);
1502 client_init_dispatch(ssh
);
1505 * Set signal handlers, (e.g. to restore non-blocking mode)
1506 * but don't overwrite SIG_IGN, matches behaviour from rsh(1)
1508 if (ssh_signal(SIGHUP
, SIG_IGN
) != SIG_IGN
)
1509 ssh_signal(SIGHUP
, signal_handler
);
1510 if (ssh_signal(SIGINT
, SIG_IGN
) != SIG_IGN
)
1511 ssh_signal(SIGINT
, signal_handler
);
1512 if (ssh_signal(SIGQUIT
, SIG_IGN
) != SIG_IGN
)
1513 ssh_signal(SIGQUIT
, signal_handler
);
1514 if (ssh_signal(SIGTERM
, SIG_IGN
) != SIG_IGN
)
1515 ssh_signal(SIGTERM
, signal_handler
);
1516 ssh_signal(SIGWINCH
, window_change_handler
);
1519 enter_raw_mode(options
.request_tty
== REQUEST_TTY_FORCE
);
1521 if (session_ident
!= -1) {
1522 if (escape_char_arg
!= SSH_ESCAPECHAR_NONE
) {
1523 channel_register_filter(ssh
, session_ident
,
1524 client_simple_escape_filter
, NULL
,
1525 client_filter_cleanup
,
1526 client_new_escape_filter_ctx(
1529 channel_register_cleanup(ssh
, session_ident
,
1530 client_channel_closed
, 0);
1533 schedule_server_alive_check();
1535 if (sigemptyset(&bsigset
) == -1 ||
1536 sigaddset(&bsigset
, SIGHUP
) == -1 ||
1537 sigaddset(&bsigset
, SIGINT
) == -1 ||
1538 sigaddset(&bsigset
, SIGQUIT
) == -1 ||
1539 sigaddset(&bsigset
, SIGTERM
) == -1)
1540 error_f("bsigset setup: %s", strerror(errno
));
1542 /* Main loop of the client for the interactive session mode. */
1543 while (!quit_pending
) {
1544 channel_did_enqueue
= 0;
1546 /* Process buffered packets sent by the server. */
1547 client_process_buffered_input_packets(ssh
);
1549 if (session_closed
&& !channel_still_open(ssh
))
1552 if (ssh_packet_is_rekeying(ssh
)) {
1553 debug("rekeying in progress");
1554 } else if (need_rekeying
) {
1555 /* manual rekey request */
1556 debug("need rekeying");
1557 if ((r
= kex_start_rekex(ssh
)) != 0)
1558 fatal_fr(r
, "kex_start_rekex");
1562 * Make packets from buffered channel data, and
1563 * enqueue them for sending to the server.
1565 if (ssh_packet_not_very_much_data_to_write(ssh
))
1566 channel_did_enqueue
= channel_output_poll(ssh
);
1569 * Check if the window size has changed, and buffer a
1570 * message about it to the server if so.
1572 client_check_window_change(ssh
);
1575 * Wait until we have something to do (something becomes
1576 * available on one of the descriptors).
1578 if (sigprocmask(SIG_BLOCK
, &bsigset
, &osigset
) == -1)
1579 error_f("bsigset sigprocmask: %s", strerror(errno
));
1582 client_wait_until_can_do_something(ssh
, &pfd
, &npfd_alloc
,
1583 &npfd_active
, channel_did_enqueue
, &osigset
,
1584 &conn_in_ready
, &conn_out_ready
);
1585 if (sigprocmask(SIG_SETMASK
, &osigset
, NULL
) == -1)
1586 error_f("osigset sigprocmask: %s", strerror(errno
));
1591 /* Do channel operations. */
1592 channel_after_poll(ssh
, pfd
, npfd_active
);
1594 /* Buffer input from the connection. */
1596 client_process_net_input(ssh
);
1601 /* A timeout may have triggered rekeying */
1602 if ((r
= ssh_packet_check_rekey(ssh
)) != 0)
1603 fatal_fr(r
, "cannot start rekeying");
1606 * Send as much buffered packet data as possible to the
1609 if (conn_out_ready
) {
1610 if ((r
= ssh_packet_write_poll(ssh
)) != 0) {
1611 sshpkt_fatal(ssh
, r
,
1612 "%s: ssh_packet_write_poll", __func__
);
1617 * If we are a backgrounded control master, and the
1618 * timeout has expired without any active client
1619 * connections, then quit.
1621 if (control_persist_exit_time
> 0) {
1622 if (monotime() >= control_persist_exit_time
) {
1623 debug("ControlPersist timeout expired");
1630 /* Terminate the session. */
1633 * In interactive mode (with pseudo tty) display a message indicating
1634 * that the connection has been closed.
1636 if (have_pty
&& options
.log_level
>= SYSLOG_LEVEL_INFO
)
1637 quit_message("Connection to %s closed.", host
);
1640 /* Stop watching for window change. */
1641 ssh_signal(SIGWINCH
, SIG_DFL
);
1643 if ((r
= sshpkt_start(ssh
, SSH2_MSG_DISCONNECT
)) != 0 ||
1644 (r
= sshpkt_put_u32(ssh
, SSH2_DISCONNECT_BY_APPLICATION
)) != 0 ||
1645 (r
= sshpkt_put_cstring(ssh
, "disconnected by user")) != 0 ||
1646 (r
= sshpkt_put_cstring(ssh
, "")) != 0 || /* language tag */
1647 (r
= sshpkt_send(ssh
)) != 0 ||
1648 (r
= ssh_packet_write_wait(ssh
)) != 0)
1649 fatal_fr(r
, "send disconnect");
1651 channel_free_all(ssh
);
1654 leave_raw_mode(options
.request_tty
== REQUEST_TTY_FORCE
);
1657 * If there was no shell or command requested, there will be no remote
1658 * exit status to be returned. In that case, clear error code if the
1659 * connection was deliberately terminated at this end.
1661 if (options
.session_type
== SESSION_TYPE_NONE
&&
1662 received_signal
== SIGTERM
) {
1663 received_signal
= 0;
1667 if (received_signal
) {
1668 verbose("Killed by signal %d.", (int) received_signal
);
1672 /* Report bytes transferred, and transfer rates. */
1673 total_time
= monotime_double() - start_time
;
1674 ssh_packet_get_bytes(ssh
, &ibytes
, &obytes
);
1675 verbose("Transferred: sent %llu, received %llu bytes, in %.1f seconds",
1676 (unsigned long long)obytes
, (unsigned long long)ibytes
, total_time
);
1678 verbose("Bytes per second: sent %.1f, received %.1f",
1679 obytes
/ total_time
, ibytes
/ total_time
);
1680 /* Return the exit status of the program. */
1681 debug("Exit status %d", exit_status
);
1688 client_request_forwarded_tcpip(struct ssh
*ssh
, const char *request_type
,
1689 int rchan
, u_int rwindow
, u_int rmaxpack
)
1692 struct sshbuf
*b
= NULL
;
1693 char *listen_address
, *originator_address
;
1694 u_int listen_port
, originator_port
;
1697 /* Get rest of the packet */
1698 if ((r
= sshpkt_get_cstring(ssh
, &listen_address
, NULL
)) != 0 ||
1699 (r
= sshpkt_get_u32(ssh
, &listen_port
)) != 0 ||
1700 (r
= sshpkt_get_cstring(ssh
, &originator_address
, NULL
)) != 0 ||
1701 (r
= sshpkt_get_u32(ssh
, &originator_port
)) != 0 ||
1702 (r
= sshpkt_get_end(ssh
)) != 0)
1703 fatal_fr(r
, "parse packet");
1705 debug_f("listen %s port %d, originator %s port %d",
1706 listen_address
, listen_port
, originator_address
, originator_port
);
1708 if (listen_port
> 0xffff)
1709 error_f("invalid listen port");
1710 else if (originator_port
> 0xffff)
1711 error_f("invalid originator port");
1713 c
= channel_connect_by_listen_address(ssh
,
1714 listen_address
, listen_port
, "forwarded-tcpip",
1715 originator_address
);
1718 if (c
!= NULL
&& c
->type
== SSH_CHANNEL_MUX_CLIENT
) {
1719 if ((b
= sshbuf_new()) == NULL
) {
1720 error_f("alloc reply");
1723 /* reconstruct and send to muxclient */
1724 if ((r
= sshbuf_put_u8(b
, 0)) != 0 || /* padlen */
1725 (r
= sshbuf_put_u8(b
, SSH2_MSG_CHANNEL_OPEN
)) != 0 ||
1726 (r
= sshbuf_put_cstring(b
, request_type
)) != 0 ||
1727 (r
= sshbuf_put_u32(b
, rchan
)) != 0 ||
1728 (r
= sshbuf_put_u32(b
, rwindow
)) != 0 ||
1729 (r
= sshbuf_put_u32(b
, rmaxpack
)) != 0 ||
1730 (r
= sshbuf_put_cstring(b
, listen_address
)) != 0 ||
1731 (r
= sshbuf_put_u32(b
, listen_port
)) != 0 ||
1732 (r
= sshbuf_put_cstring(b
, originator_address
)) != 0 ||
1733 (r
= sshbuf_put_u32(b
, originator_port
)) != 0 ||
1734 (r
= sshbuf_put_stringb(c
->output
, b
)) != 0) {
1735 error_fr(r
, "compose for muxclient");
1742 free(originator_address
);
1743 free(listen_address
);
1748 client_request_forwarded_streamlocal(struct ssh
*ssh
,
1749 const char *request_type
, int rchan
)
1755 /* Get the remote path. */
1756 if ((r
= sshpkt_get_cstring(ssh
, &listen_path
, NULL
)) != 0 ||
1757 (r
= sshpkt_get_string(ssh
, NULL
, NULL
)) != 0 || /* reserved */
1758 (r
= sshpkt_get_end(ssh
)) != 0)
1759 fatal_fr(r
, "parse packet");
1761 debug_f("request: %s", listen_path
);
1763 c
= channel_connect_by_listen_path(ssh
, listen_path
,
1764 "forwarded-streamlocal@openssh.com", "forwarded-streamlocal");
1770 client_request_x11(struct ssh
*ssh
, const char *request_type
, int rchan
)
1774 u_int originator_port
;
1777 if (!options
.forward_x11
) {
1778 error("Warning: ssh server tried X11 forwarding.");
1779 error("Warning: this is probably a break-in attempt by a "
1780 "malicious server.");
1783 if (x11_refuse_time
!= 0 && monotime() >= x11_refuse_time
) {
1784 verbose("Rejected X11 connection after ForwardX11Timeout "
1788 if ((r
= sshpkt_get_cstring(ssh
, &originator
, NULL
)) != 0 ||
1789 (r
= sshpkt_get_u32(ssh
, &originator_port
)) != 0 ||
1790 (r
= sshpkt_get_end(ssh
)) != 0)
1791 fatal_fr(r
, "parse packet");
1792 /* XXX check permission */
1793 /* XXX range check originator port? */
1794 debug("client_request_x11: request from %s %u", originator
,
1797 sock
= x11_connect_display(ssh
);
1800 c
= channel_new(ssh
, "x11-connection",
1801 SSH_CHANNEL_X11_OPEN
, sock
, sock
, -1,
1802 CHAN_TCP_WINDOW_DEFAULT
, CHAN_X11_PACKET_DEFAULT
, 0, "x11", 1);
1808 client_request_agent(struct ssh
*ssh
, const char *request_type
, int rchan
)
1813 if (!options
.forward_agent
) {
1814 error("Warning: ssh server tried agent forwarding.");
1815 error("Warning: this is probably a break-in attempt by a "
1816 "malicious server.");
1819 if (forward_agent_sock_path
== NULL
) {
1820 r
= ssh_get_authentication_socket(&sock
);
1822 r
= ssh_get_authentication_socket_path(forward_agent_sock_path
, &sock
);
1825 if (r
!= SSH_ERR_AGENT_NOT_PRESENT
)
1826 debug_fr(r
, "ssh_get_authentication_socket");
1829 if ((r
= ssh_agent_bind_hostkey(sock
, ssh
->kex
->initial_hostkey
,
1830 ssh
->kex
->session_id
, ssh
->kex
->initial_sig
, 1)) == 0)
1831 debug_f("bound agent to hostkey");
1833 debug2_fr(r
, "ssh_agent_bind_hostkey");
1835 c
= channel_new(ssh
, "agent-connection",
1836 SSH_CHANNEL_OPEN
, sock
, sock
, -1,
1837 CHAN_X11_WINDOW_DEFAULT
, CHAN_TCP_PACKET_DEFAULT
, 0,
1838 "authentication agent connection", 1);
1844 client_request_tun_fwd(struct ssh
*ssh
, int tun_mode
,
1845 int local_tun
, int remote_tun
, channel_open_fn
*cb
, void *cbctx
)
1849 char *ifname
= NULL
;
1851 if (tun_mode
== SSH_TUNMODE_NO
)
1854 debug("Requesting tun unit %d in mode %d", local_tun
, tun_mode
);
1856 /* Open local tunnel device */
1857 if ((fd
= tun_open(local_tun
, tun_mode
, &ifname
)) == -1) {
1858 error("Tunnel device open failed.");
1861 debug("Tunnel forwarding using interface %s", ifname
);
1863 c
= channel_new(ssh
, "tun-connection", SSH_CHANNEL_OPENING
, fd
, fd
, -1,
1864 CHAN_TCP_WINDOW_DEFAULT
, CHAN_TCP_PACKET_DEFAULT
, 0, "tun", 1);
1867 #if defined(SSH_TUN_FILTER)
1868 if (options
.tun_open
== SSH_TUNMODE_POINTOPOINT
)
1869 channel_register_filter(ssh
, c
->self
, sys_tun_infilter
,
1870 sys_tun_outfilter
, NULL
, NULL
);
1874 channel_register_open_confirm(ssh
, c
->self
, cb
, cbctx
);
1876 if ((r
= sshpkt_start(ssh
, SSH2_MSG_CHANNEL_OPEN
)) != 0 ||
1877 (r
= sshpkt_put_cstring(ssh
, "tun@openssh.com")) != 0 ||
1878 (r
= sshpkt_put_u32(ssh
, c
->self
)) != 0 ||
1879 (r
= sshpkt_put_u32(ssh
, c
->local_window_max
)) != 0 ||
1880 (r
= sshpkt_put_u32(ssh
, c
->local_maxpacket
)) != 0 ||
1881 (r
= sshpkt_put_u32(ssh
, tun_mode
)) != 0 ||
1882 (r
= sshpkt_put_u32(ssh
, remote_tun
)) != 0 ||
1883 (r
= sshpkt_send(ssh
)) != 0)
1884 sshpkt_fatal(ssh
, r
, "%s: send reply", __func__
);
1889 /* XXXX move to generic input handler */
1891 client_input_channel_open(int type
, u_int32_t seq
, struct ssh
*ssh
)
1898 u_int rmaxpack
, rwindow
;
1900 if ((r
= sshpkt_get_cstring(ssh
, &ctype
, &len
)) != 0 ||
1901 (r
= sshpkt_get_u32(ssh
, &rchan
)) != 0 ||
1902 (r
= sshpkt_get_u32(ssh
, &rwindow
)) != 0 ||
1903 (r
= sshpkt_get_u32(ssh
, &rmaxpack
)) != 0)
1906 debug("client_input_channel_open: ctype %s rchan %d win %d max %d",
1907 ctype
, rchan
, rwindow
, rmaxpack
);
1909 if (strcmp(ctype
, "forwarded-tcpip") == 0) {
1910 c
= client_request_forwarded_tcpip(ssh
, ctype
, rchan
, rwindow
,
1912 } else if (strcmp(ctype
, "forwarded-streamlocal@openssh.com") == 0) {
1913 c
= client_request_forwarded_streamlocal(ssh
, ctype
, rchan
);
1914 } else if (strcmp(ctype
, "x11") == 0) {
1915 c
= client_request_x11(ssh
, ctype
, rchan
);
1916 } else if (strcmp(ctype
, "auth-agent@openssh.com") == 0) {
1917 c
= client_request_agent(ssh
, ctype
, rchan
);
1919 if (c
!= NULL
&& c
->type
== SSH_CHANNEL_MUX_CLIENT
) {
1920 debug3("proxied to downstream: %s", ctype
);
1921 } else if (c
!= NULL
) {
1922 debug("confirm %s", ctype
);
1923 c
->remote_id
= rchan
;
1924 c
->have_remote_id
= 1;
1925 c
->remote_window
= rwindow
;
1926 c
->remote_maxpacket
= rmaxpack
;
1927 if (c
->type
!= SSH_CHANNEL_CONNECTING
) {
1928 if ((r
= sshpkt_start(ssh
, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION
)) != 0 ||
1929 (r
= sshpkt_put_u32(ssh
, c
->remote_id
)) != 0 ||
1930 (r
= sshpkt_put_u32(ssh
, c
->self
)) != 0 ||
1931 (r
= sshpkt_put_u32(ssh
, c
->local_window
)) != 0 ||
1932 (r
= sshpkt_put_u32(ssh
, c
->local_maxpacket
)) != 0 ||
1933 (r
= sshpkt_send(ssh
)) != 0)
1934 sshpkt_fatal(ssh
, r
, "%s: send reply", __func__
);
1937 debug("failure %s", ctype
);
1938 if ((r
= sshpkt_start(ssh
, SSH2_MSG_CHANNEL_OPEN_FAILURE
)) != 0 ||
1939 (r
= sshpkt_put_u32(ssh
, rchan
)) != 0 ||
1940 (r
= sshpkt_put_u32(ssh
, SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED
)) != 0 ||
1941 (r
= sshpkt_put_cstring(ssh
, "open failed")) != 0 ||
1942 (r
= sshpkt_put_cstring(ssh
, "")) != 0 ||
1943 (r
= sshpkt_send(ssh
)) != 0)
1944 sshpkt_fatal(ssh
, r
, "%s: send failure", __func__
);
1953 client_input_channel_req(int type
, u_int32_t seq
, struct ssh
*ssh
)
1961 if ((r
= sshpkt_get_u32(ssh
, &id
)) != 0)
1964 c
= channel_lookup(ssh
, id
);
1965 if (channel_proxy_upstream(c
, type
, seq
, ssh
))
1967 if ((r
= sshpkt_get_cstring(ssh
, &rtype
, NULL
)) != 0 ||
1968 (r
= sshpkt_get_u8(ssh
, &reply
)) != 0)
1971 debug("client_input_channel_req: channel %u rtype %s reply %d",
1975 error("client_input_channel_req: channel %d: "
1976 "unknown channel", id
);
1977 } else if (strcmp(rtype
, "eow@openssh.com") == 0) {
1978 if ((r
= sshpkt_get_end(ssh
)) != 0)
1980 chan_rcvd_eow(ssh
, c
);
1981 } else if (strcmp(rtype
, "exit-status") == 0) {
1982 if ((r
= sshpkt_get_u32(ssh
, &exitval
)) != 0)
1984 if (c
->ctl_chan
!= -1) {
1985 mux_exit_message(ssh
, c
, exitval
);
1987 } else if ((int)id
== session_ident
) {
1988 /* Record exit value of local session */
1990 exit_status
= exitval
;
1992 /* Probably for a mux channel that has already closed */
1993 debug_f("no sink for exit-status on channel %d",
1996 if ((r
= sshpkt_get_end(ssh
)) != 0)
1999 if (reply
&& c
!= NULL
&& !(c
->flags
& CHAN_CLOSE_SENT
)) {
2000 if (!c
->have_remote_id
)
2001 fatal_f("channel %d: no remote_id", c
->self
);
2002 if ((r
= sshpkt_start(ssh
, success
?
2003 SSH2_MSG_CHANNEL_SUCCESS
: SSH2_MSG_CHANNEL_FAILURE
)) != 0 ||
2004 (r
= sshpkt_put_u32(ssh
, c
->remote_id
)) != 0 ||
2005 (r
= sshpkt_send(ssh
)) != 0)
2006 sshpkt_fatal(ssh
, r
, "%s: send failure", __func__
);
2014 struct hostkeys_update_ctx
{
2015 /* The hostname and (optionally) IP address string for the server */
2016 char *host_str
, *ip_str
;
2019 * Keys received from the server and a flag for each indicating
2020 * whether they already exist in known_hosts.
2021 * keys_match is filled in by hostkeys_find() and later (for new
2022 * keys) by client_global_hostkeys_prove_confirm().
2024 struct sshkey
**keys
;
2025 u_int
*keys_match
; /* mask of HKF_MATCH_* from hostfile.h */
2026 int *keys_verified
; /* flag for new keys verified by server */
2027 size_t nkeys
, nnew
, nincomplete
; /* total, new keys, incomplete match */
2030 * Keys that are in known_hosts, but were not present in the update
2031 * from the server (i.e. scheduled to be deleted).
2032 * Filled in by hostkeys_find().
2034 struct sshkey
**old_keys
;
2037 /* Various special cases. */
2038 int complex_hostspec
; /* wildcard or manual pattern-list host name */
2039 int ca_available
; /* saw CA key for this host */
2040 int old_key_seen
; /* saw old key with other name/addr */
2041 int other_name_seen
; /* saw key with other name/addr */
2045 hostkeys_update_ctx_free(struct hostkeys_update_ctx
*ctx
)
2051 for (i
= 0; i
< ctx
->nkeys
; i
++)
2052 sshkey_free(ctx
->keys
[i
]);
2054 free(ctx
->keys_match
);
2055 free(ctx
->keys_verified
);
2056 for (i
= 0; i
< ctx
->nold
; i
++)
2057 sshkey_free(ctx
->old_keys
[i
]);
2058 free(ctx
->old_keys
);
2059 free(ctx
->host_str
);
2065 * Returns non-zero if a known_hosts hostname list is not of a form that
2066 * can be handled by UpdateHostkeys. These include wildcard hostnames and
2067 * hostnames lists that do not follow the form host[,ip].
2070 hostspec_is_complex(const char *hosts
)
2075 if (strchr(hosts
, '*') != NULL
|| strchr(hosts
, '?') != NULL
)
2077 /* single host/ip = ok */
2078 if ((cp
= strchr(hosts
, ',')) == NULL
)
2080 /* more than two entries on the line */
2081 if (strchr(cp
+ 1, ',') != NULL
)
2083 /* XXX maybe parse cp+1 and ensure it is an IP? */
2087 /* callback to search for ctx->keys in known_hosts */
2089 hostkeys_find(struct hostkey_foreach_line
*l
, void *_ctx
)
2091 struct hostkeys_update_ctx
*ctx
= (struct hostkeys_update_ctx
*)_ctx
;
2093 struct sshkey
**tmp
;
2097 if (l
->status
!= HKF_STATUS_MATCHED
) {
2098 /* Record if one of the keys appears on a non-matching line */
2099 for (i
= 0; i
< ctx
->nkeys
; i
++) {
2100 if (sshkey_equal(l
->key
, ctx
->keys
[i
])) {
2101 ctx
->other_name_seen
= 1;
2102 debug3_f("found %s key under different "
2103 "name/addr at %s:%ld",
2104 sshkey_ssh_name(ctx
->keys
[i
]),
2105 l
->path
, l
->linenum
);
2111 /* Don't proceed if revocation or CA markers are present */
2112 /* XXX relax this */
2113 if (l
->marker
!= MRK_NONE
) {
2114 debug3_f("hostkeys file %s:%ld has CA/revocation marker",
2115 l
->path
, l
->linenum
);
2116 ctx
->complex_hostspec
= 1;
2120 /* If CheckHostIP is enabled, then check for mismatched hostname/addr */
2121 if (ctx
->ip_str
!= NULL
&& strchr(l
->hosts
, ',') != NULL
) {
2122 if ((l
->match
& HKF_MATCH_HOST
) == 0) {
2123 /* Record if address matched a different hostname. */
2124 ctx
->other_name_seen
= 1;
2125 debug3_f("found address %s against different hostname "
2126 "at %s:%ld", ctx
->ip_str
, l
->path
, l
->linenum
);
2128 } else if ((l
->match
& HKF_MATCH_IP
) == 0) {
2129 /* Record if hostname matched a different address. */
2130 ctx
->other_name_seen
= 1;
2131 debug3_f("found hostname %s against different address "
2132 "at %s:%ld", ctx
->host_str
, l
->path
, l
->linenum
);
2137 * UpdateHostkeys is skipped for wildcard host names and hostnames
2138 * that contain more than two entries (ssh never writes these).
2140 if (hostspec_is_complex(l
->hosts
)) {
2141 debug3_f("hostkeys file %s:%ld complex host specification",
2142 l
->path
, l
->linenum
);
2143 ctx
->complex_hostspec
= 1;
2147 /* Mark off keys we've already seen for this host */
2148 for (i
= 0; i
< ctx
->nkeys
; i
++) {
2149 if (!sshkey_equal(l
->key
, ctx
->keys
[i
]))
2151 debug3_f("found %s key at %s:%ld",
2152 sshkey_ssh_name(ctx
->keys
[i
]), l
->path
, l
->linenum
);
2153 ctx
->keys_match
[i
] |= l
->match
;
2156 /* This line contained a key that not offered by the server */
2157 debug3_f("deprecated %s key at %s:%ld", sshkey_ssh_name(l
->key
),
2158 l
->path
, l
->linenum
);
2159 if ((tmp
= recallocarray(ctx
->old_keys
, ctx
->nold
, ctx
->nold
+ 1,
2160 sizeof(*ctx
->old_keys
))) == NULL
)
2161 fatal_f("recallocarray failed nold = %zu", ctx
->nold
);
2162 ctx
->old_keys
= tmp
;
2163 ctx
->old_keys
[ctx
->nold
++] = l
->key
;
2169 /* callback to search for ctx->old_keys in known_hosts under other names */
2171 hostkeys_check_old(struct hostkey_foreach_line
*l
, void *_ctx
)
2173 struct hostkeys_update_ctx
*ctx
= (struct hostkeys_update_ctx
*)_ctx
;
2177 /* only care about lines that *don't* match the active host spec */
2178 if (l
->status
== HKF_STATUS_MATCHED
|| l
->key
== NULL
)
2181 hashed
= l
->match
& (HKF_MATCH_HOST_HASHED
|HKF_MATCH_IP_HASHED
);
2182 for (i
= 0; i
< ctx
->nold
; i
++) {
2183 if (!sshkey_equal(l
->key
, ctx
->old_keys
[i
]))
2185 debug3_f("found deprecated %s key at %s:%ld as %s",
2186 sshkey_ssh_name(ctx
->old_keys
[i
]), l
->path
, l
->linenum
,
2187 hashed
? "[HASHED]" : l
->hosts
);
2188 ctx
->old_key_seen
= 1;
2195 * Check known_hosts files for deprecated keys under other names. Returns 0
2196 * on success or -1 on failure. Updates ctx->old_key_seen if deprecated keys
2197 * exist under names other than the active hostname/IP.
2200 check_old_keys_othernames(struct hostkeys_update_ctx
*ctx
)
2205 debug2_f("checking for %zu deprecated keys", ctx
->nold
);
2206 for (i
= 0; i
< options
.num_user_hostfiles
; i
++) {
2207 debug3_f("searching %s for %s / %s",
2208 options
.user_hostfiles
[i
], ctx
->host_str
,
2209 ctx
->ip_str
? ctx
->ip_str
: "(none)");
2210 if ((r
= hostkeys_foreach(options
.user_hostfiles
[i
],
2211 hostkeys_check_old
, ctx
, ctx
->host_str
, ctx
->ip_str
,
2212 HKF_WANT_PARSE_KEY
, 0)) != 0) {
2213 if (r
== SSH_ERR_SYSTEM_ERROR
&& errno
== ENOENT
) {
2214 debug_f("hostkeys file %s does not exist",
2215 options
.user_hostfiles
[i
]);
2218 error_fr(r
, "hostkeys_foreach failed for %s",
2219 options
.user_hostfiles
[i
]);
2227 hostkey_change_preamble(LogLevel loglevel
)
2229 do_log2(loglevel
, "The server has updated its host keys.");
2230 do_log2(loglevel
, "These changes were verified by the server's "
2231 "existing trusted key.");
2235 update_known_hosts(struct hostkeys_update_ctx
*ctx
)
2237 int r
, was_raw
= 0, first
= 1;
2238 int asking
= options
.update_hostkeys
== SSH_UPDATE_HOSTKEYS_ASK
;
2239 LogLevel loglevel
= asking
? SYSLOG_LEVEL_INFO
: SYSLOG_LEVEL_VERBOSE
;
2240 char *fp
, *response
;
2244 for (i
= 0; i
< ctx
->nkeys
; i
++) {
2245 if (!ctx
->keys_verified
[i
])
2247 if ((fp
= sshkey_fingerprint(ctx
->keys
[i
],
2248 options
.fingerprint_hash
, SSH_FP_DEFAULT
)) == NULL
)
2249 fatal_f("sshkey_fingerprint failed");
2250 if (first
&& asking
)
2251 hostkey_change_preamble(loglevel
);
2252 do_log2(loglevel
, "Learned new hostkey: %s %s",
2253 sshkey_type(ctx
->keys
[i
]), fp
);
2257 for (i
= 0; i
< ctx
->nold
; i
++) {
2258 if ((fp
= sshkey_fingerprint(ctx
->old_keys
[i
],
2259 options
.fingerprint_hash
, SSH_FP_DEFAULT
)) == NULL
)
2260 fatal_f("sshkey_fingerprint failed");
2261 if (first
&& asking
)
2262 hostkey_change_preamble(loglevel
);
2263 do_log2(loglevel
, "Deprecating obsolete hostkey: %s %s",
2264 sshkey_type(ctx
->old_keys
[i
]), fp
);
2268 if (options
.update_hostkeys
== SSH_UPDATE_HOSTKEYS_ASK
) {
2269 if (get_saved_tio() != NULL
) {
2274 for (i
= 0; !quit_pending
&& i
< 3; i
++) {
2276 response
= read_passphrase("Accept updated hostkeys? "
2277 "(yes/no): ", RP_ECHO
);
2278 if (response
!= NULL
&& strcasecmp(response
, "yes") == 0)
2280 else if (quit_pending
|| response
== NULL
||
2281 strcasecmp(response
, "no") == 0) {
2282 options
.update_hostkeys
= 0;
2285 do_log2(loglevel
, "Please enter "
2286 "\"yes\" or \"no\"");
2289 if (quit_pending
|| i
>= 3 || response
== NULL
)
2290 options
.update_hostkeys
= 0;
2295 if (options
.update_hostkeys
== 0)
2298 * Now that all the keys are verified, we can go ahead and replace
2299 * them in known_hosts (assuming SSH_UPDATE_HOSTKEYS_ASK didn't
2300 * cancel the operation).
2302 for (i
= 0; i
< options
.num_user_hostfiles
; i
++) {
2304 * NB. keys are only added to hostfiles[0], for the rest we
2305 * just delete the hostname entries.
2307 if (stat(options
.user_hostfiles
[i
], &sb
) != 0) {
2308 if (errno
== ENOENT
) {
2309 debug_f("known hosts file %s does not "
2310 "exist", options
.user_hostfiles
[i
]);
2312 error_f("known hosts file %s "
2314 options
.user_hostfiles
[i
], strerror(errno
));
2318 if ((r
= hostfile_replace_entries(options
.user_hostfiles
[i
],
2319 ctx
->host_str
, ctx
->ip_str
,
2320 i
== 0 ? ctx
->keys
: NULL
, i
== 0 ? ctx
->nkeys
: 0,
2321 options
.hash_known_hosts
, 0,
2322 options
.fingerprint_hash
)) != 0) {
2323 error_fr(r
, "hostfile_replace_entries failed for %s",
2324 options
.user_hostfiles
[i
]);
2330 client_global_hostkeys_prove_confirm(struct ssh
*ssh
, int type
,
2331 u_int32_t seq
, void *_ctx
)
2333 struct hostkeys_update_ctx
*ctx
= (struct hostkeys_update_ctx
*)_ctx
;
2335 struct sshbuf
*signdata
;
2338 const char *rsa_kexalg
= NULL
;
2343 fatal_f("ctx->nnew == 0"); /* sanity */
2344 if (type
!= SSH2_MSG_REQUEST_SUCCESS
) {
2345 error("Server failed to confirm ownership of "
2346 "private host keys");
2347 hostkeys_update_ctx_free(ctx
);
2350 if (sshkey_type_plain(sshkey_type_from_name(
2351 ssh
->kex
->hostkey_alg
)) == KEY_RSA
)
2352 rsa_kexalg
= ssh
->kex
->hostkey_alg
;
2353 if ((signdata
= sshbuf_new()) == NULL
)
2354 fatal_f("sshbuf_new failed");
2356 * Expect a signature for each of the ctx->nnew private keys we
2357 * haven't seen before. They will be in the same order as the
2358 * ctx->keys where the corresponding ctx->keys_match[i] == 0.
2360 for (ndone
= i
= 0; i
< ctx
->nkeys
; i
++) {
2361 if (ctx
->keys_match
[i
])
2363 plaintype
= sshkey_type_plain(ctx
->keys
[i
]->type
);
2364 /* Prepare data to be signed: session ID, unique string, key */
2365 sshbuf_reset(signdata
);
2366 if ( (r
= sshbuf_put_cstring(signdata
,
2367 "hostkeys-prove-00@openssh.com")) != 0 ||
2368 (r
= sshbuf_put_stringb(signdata
,
2369 ssh
->kex
->session_id
)) != 0 ||
2370 (r
= sshkey_puts(ctx
->keys
[i
], signdata
)) != 0)
2371 fatal_fr(r
, "compose signdata");
2372 /* Extract and verify signature */
2373 if ((r
= sshpkt_get_string_direct(ssh
, &sig
, &siglen
)) != 0) {
2374 error_fr(r
, "parse sig");
2377 if ((r
= sshkey_get_sigtype(sig
, siglen
, &alg
)) != 0) {
2378 error_fr(r
, "server gave unintelligible signature "
2379 "for %s key %zu", sshkey_type(ctx
->keys
[i
]), i
);
2383 * Special case for RSA keys: if a RSA hostkey was negotiated,
2384 * then use its signature type for verification of RSA hostkey
2385 * proofs. Otherwise, accept only RSA-SHA256/512 signatures.
2387 if (plaintype
== KEY_RSA
&& rsa_kexalg
== NULL
&&
2388 match_pattern_list(alg
, HOSTKEY_PROOF_RSA_ALGS
, 0) != 1) {
2389 debug_f("server used untrusted RSA signature algorithm "
2390 "%s for key %zu, disregarding", alg
, i
);
2392 /* zap the key from the list */
2393 sshkey_free(ctx
->keys
[i
]);
2394 ctx
->keys
[i
] = NULL
;
2398 debug3_f("verify %s key %zu using sigalg %s",
2399 sshkey_type(ctx
->keys
[i
]), i
, alg
);
2401 if ((r
= sshkey_verify(ctx
->keys
[i
], sig
, siglen
,
2402 sshbuf_ptr(signdata
), sshbuf_len(signdata
),
2403 plaintype
== KEY_RSA
? rsa_kexalg
: NULL
, 0, NULL
)) != 0) {
2404 error_fr(r
, "server gave bad signature for %s key %zu",
2405 sshkey_type(ctx
->keys
[i
]), i
);
2408 /* Key is good. Mark it as 'seen' */
2409 ctx
->keys_verified
[i
] = 1;
2412 /* Shouldn't happen */
2413 if (ndone
!= ctx
->nnew
)
2414 fatal_f("ndone != ctx->nnew (%zu / %zu)", ndone
, ctx
->nnew
);
2415 if ((r
= sshpkt_get_end(ssh
)) != 0) {
2416 error_f("protocol error");
2420 /* Make the edits to known_hosts */
2421 update_known_hosts(ctx
);
2423 hostkeys_update_ctx_free(ctx
);
2424 hostkeys_update_complete
= 1;
2429 * Handle hostkeys-00@openssh.com global request to inform the client of all
2430 * the server's hostkeys. The keys are checked against the user's
2431 * HostkeyAlgorithms preference before they are accepted.
2434 client_input_hostkeys(struct ssh
*ssh
)
2436 const u_char
*blob
= NULL
;
2438 struct sshbuf
*buf
= NULL
;
2439 struct sshkey
*key
= NULL
, **tmp
;
2440 int r
, prove_sent
= 0;
2442 static int hostkeys_seen
= 0; /* XXX use struct ssh */
2443 extern struct sockaddr_storage hostaddr
; /* XXX from ssh.c */
2444 struct hostkeys_update_ctx
*ctx
= NULL
;
2448 fatal_f("server already sent hostkeys");
2449 if (!can_update_hostkeys())
2453 ctx
= xcalloc(1, sizeof(*ctx
));
2454 while (ssh_packet_remaining(ssh
) > 0) {
2457 if ((r
= sshpkt_get_string_direct(ssh
, &blob
, &len
)) != 0) {
2458 error_fr(r
, "parse key");
2461 if ((r
= sshkey_from_blob(blob
, len
, &key
)) != 0) {
2462 do_log2_fr(r
, r
== SSH_ERR_KEY_TYPE_UNKNOWN
?
2463 SYSLOG_LEVEL_DEBUG1
: SYSLOG_LEVEL_ERROR
,
2467 fp
= sshkey_fingerprint(key
, options
.fingerprint_hash
,
2469 debug3_f("received %s key %s", sshkey_type(key
), fp
);
2472 if (!hostkey_accepted_by_hostkeyalgs(key
)) {
2473 debug3_f("%s key not permitted by "
2474 "HostkeyAlgorithms", sshkey_ssh_name(key
));
2478 if (sshkey_is_cert(key
)) {
2479 debug3_f("%s key is a certificate; skipping",
2480 sshkey_ssh_name(key
));
2483 /* Ensure keys are unique */
2484 for (i
= 0; i
< ctx
->nkeys
; i
++) {
2485 if (sshkey_equal(key
, ctx
->keys
[i
])) {
2486 error_f("received duplicated %s host key",
2487 sshkey_ssh_name(key
));
2491 /* Key is good, record it */
2492 if ((tmp
= recallocarray(ctx
->keys
, ctx
->nkeys
, ctx
->nkeys
+ 1,
2493 sizeof(*ctx
->keys
))) == NULL
)
2494 fatal_f("recallocarray failed nkeys = %zu",
2497 ctx
->keys
[ctx
->nkeys
++] = key
;
2501 if (ctx
->nkeys
== 0) {
2502 debug_f("server sent no hostkeys");
2506 if ((ctx
->keys_match
= calloc(ctx
->nkeys
,
2507 sizeof(*ctx
->keys_match
))) == NULL
||
2508 (ctx
->keys_verified
= calloc(ctx
->nkeys
,
2509 sizeof(*ctx
->keys_verified
))) == NULL
)
2510 fatal_f("calloc failed");
2512 get_hostfile_hostname_ipaddr(host
,
2513 options
.check_host_ip
? (struct sockaddr
*)&hostaddr
: NULL
,
2514 options
.port
, &ctx
->host_str
,
2515 options
.check_host_ip
? &ctx
->ip_str
: NULL
);
2517 /* Find which keys we already know about. */
2518 for (i
= 0; i
< options
.num_user_hostfiles
; i
++) {
2519 debug_f("searching %s for %s / %s",
2520 options
.user_hostfiles
[i
], ctx
->host_str
,
2521 ctx
->ip_str
? ctx
->ip_str
: "(none)");
2522 if ((r
= hostkeys_foreach(options
.user_hostfiles
[i
],
2523 hostkeys_find
, ctx
, ctx
->host_str
, ctx
->ip_str
,
2524 HKF_WANT_PARSE_KEY
, 0)) != 0) {
2525 if (r
== SSH_ERR_SYSTEM_ERROR
&& errno
== ENOENT
) {
2526 debug_f("hostkeys file %s does not exist",
2527 options
.user_hostfiles
[i
]);
2530 error_fr(r
, "hostkeys_foreach failed for %s",
2531 options
.user_hostfiles
[i
]);
2536 /* Figure out if we have any new keys to add */
2537 ctx
->nnew
= ctx
->nincomplete
= 0;
2538 want
= HKF_MATCH_HOST
| ( options
.check_host_ip
? HKF_MATCH_IP
: 0);
2539 for (i
= 0; i
< ctx
->nkeys
; i
++) {
2540 if (ctx
->keys_match
[i
] == 0)
2542 if ((ctx
->keys_match
[i
] & want
) != want
)
2546 debug3_f("%zu server keys: %zu new, %zu retained, "
2547 "%zu incomplete match. %zu to remove", ctx
->nkeys
, ctx
->nnew
,
2548 ctx
->nkeys
- ctx
->nnew
- ctx
->nincomplete
,
2549 ctx
->nincomplete
, ctx
->nold
);
2551 if (ctx
->nnew
== 0 && ctx
->nold
== 0) {
2552 debug_f("no new or deprecated keys from server");
2556 /* Various reasons why we cannot proceed with the update */
2557 if (ctx
->complex_hostspec
) {
2558 debug_f("CA/revocation marker, manual host list or wildcard "
2559 "host pattern found, skipping UserKnownHostsFile update");
2562 if (ctx
->other_name_seen
) {
2563 debug_f("host key found matching a different name/address, "
2564 "skipping UserKnownHostsFile update");
2568 * If removing keys, check whether they appear under different
2569 * names/addresses and refuse to proceed if they do. This avoids
2570 * cases such as hosts with multiple names becoming inconsistent
2571 * with regards to CheckHostIP entries.
2572 * XXX UpdateHostkeys=force to override this (and other) checks?
2574 if (ctx
->nold
!= 0) {
2575 if (check_old_keys_othernames(ctx
) != 0)
2576 goto out
; /* error already logged */
2577 if (ctx
->old_key_seen
) {
2578 debug_f("key(s) for %s%s%s exist under other names; "
2579 "skipping UserKnownHostsFile update",
2580 ctx
->host_str
, ctx
->ip_str
== NULL
? "" : ",",
2581 ctx
->ip_str
== NULL
? "" : ctx
->ip_str
);
2586 if (ctx
->nnew
== 0) {
2588 * We have some keys to remove or fix matching for.
2589 * We can proceed to do this without requiring a fresh proof
2592 update_known_hosts(ctx
);
2596 * We have received previously-unseen keys from the server.
2597 * Ask the server to confirm ownership of the private halves.
2599 debug3_f("asking server to prove ownership for %zu keys", ctx
->nnew
);
2600 if ((r
= sshpkt_start(ssh
, SSH2_MSG_GLOBAL_REQUEST
)) != 0 ||
2601 (r
= sshpkt_put_cstring(ssh
,
2602 "hostkeys-prove-00@openssh.com")) != 0 ||
2603 (r
= sshpkt_put_u8(ssh
, 1)) != 0) /* bool: want reply */
2604 fatal_fr(r
, "prepare hostkeys-prove");
2605 if ((buf
= sshbuf_new()) == NULL
)
2606 fatal_f("sshbuf_new");
2607 for (i
= 0; i
< ctx
->nkeys
; i
++) {
2608 if (ctx
->keys_match
[i
])
2611 if ((r
= sshkey_putb(ctx
->keys
[i
], buf
)) != 0 ||
2612 (r
= sshpkt_put_stringb(ssh
, buf
)) != 0)
2613 fatal_fr(r
, "assemble hostkeys-prove");
2615 if ((r
= sshpkt_send(ssh
)) != 0)
2616 fatal_fr(r
, "send hostkeys-prove");
2617 client_register_global_confirm(
2618 client_global_hostkeys_prove_confirm
, ctx
);
2619 ctx
= NULL
; /* will be freed in callback */
2624 hostkeys_update_ctx_free(ctx
);
2628 /* UpdateHostkeys handling completed */
2629 hostkeys_update_complete
= 1;
2633 * NB. Return success for all cases. The server doesn't need to know
2634 * what the client does with its hosts file.
2640 client_input_global_request(int type
, u_int32_t seq
, struct ssh
*ssh
)
2646 if ((r
= sshpkt_get_cstring(ssh
, &rtype
, NULL
)) != 0 ||
2647 (r
= sshpkt_get_u8(ssh
, &want_reply
)) != 0)
2649 debug("client_input_global_request: rtype %s want_reply %d",
2651 if (strcmp(rtype
, "hostkeys-00@openssh.com") == 0)
2652 success
= client_input_hostkeys(ssh
);
2654 if ((r
= sshpkt_start(ssh
, success
? SSH2_MSG_REQUEST_SUCCESS
:
2655 SSH2_MSG_REQUEST_FAILURE
)) != 0 ||
2656 (r
= sshpkt_send(ssh
)) != 0 ||
2657 (r
= ssh_packet_write_wait(ssh
)) != 0)
2667 client_send_env(struct ssh
*ssh
, int id
, const char *name
, const char *val
)
2671 debug("channel %d: setting env %s = \"%s\"", id
, name
, val
);
2672 channel_request_start(ssh
, id
, "env", 0);
2673 if ((r
= sshpkt_put_cstring(ssh
, name
)) != 0 ||
2674 (r
= sshpkt_put_cstring(ssh
, val
)) != 0 ||
2675 (r
= sshpkt_send(ssh
)) != 0)
2676 fatal_fr(r
, "send setenv");
2680 client_session2_setup(struct ssh
*ssh
, int id
, int want_tty
, int want_subsystem
,
2681 const char *term
, struct termios
*tiop
, int in_fd
, struct sshbuf
*cmd
,
2689 debug2_f("id %d", id
);
2691 if ((c
= channel_lookup(ssh
, id
)) == NULL
)
2692 fatal_f("channel %d: unknown channel", id
);
2694 ssh_packet_set_interactive(ssh
, want_tty
,
2695 options
.ip_qos_interactive
, options
.ip_qos_bulk
);
2700 /* Store window size in the packet. */
2701 if (ioctl(in_fd
, TIOCGWINSZ
, &ws
) == -1)
2702 memset(&ws
, 0, sizeof(ws
));
2704 channel_request_start(ssh
, id
, "pty-req", 1);
2705 client_expect_confirm(ssh
, id
, "PTY allocation", CONFIRM_TTY
);
2706 if ((r
= sshpkt_put_cstring(ssh
, term
!= NULL
? term
: ""))
2708 (r
= sshpkt_put_u32(ssh
, (u_int
)ws
.ws_col
)) != 0 ||
2709 (r
= sshpkt_put_u32(ssh
, (u_int
)ws
.ws_row
)) != 0 ||
2710 (r
= sshpkt_put_u32(ssh
, (u_int
)ws
.ws_xpixel
)) != 0 ||
2711 (r
= sshpkt_put_u32(ssh
, (u_int
)ws
.ws_ypixel
)) != 0)
2712 fatal_fr(r
, "build pty-req");
2714 tiop
= get_saved_tio();
2715 ssh_tty_make_modes(ssh
, -1, tiop
);
2716 if ((r
= sshpkt_send(ssh
)) != 0)
2717 fatal_fr(r
, "send pty-req");
2718 /* XXX wait for reply */
2722 /* Transfer any environment variables from client to server */
2723 if (options
.num_send_env
!= 0 && env
!= NULL
) {
2724 debug("Sending environment.");
2725 for (i
= 0; env
[i
] != NULL
; i
++) {
2727 name
= xstrdup(env
[i
]);
2728 if ((val
= strchr(name
, '=')) == NULL
) {
2735 for (j
= 0; j
< options
.num_send_env
; j
++) {
2736 if (match_pattern(name
, options
.send_env
[j
])) {
2742 debug3("Ignored env %s", name
);
2746 client_send_env(ssh
, id
, name
, val
);
2750 for (i
= 0; i
< options
.num_setenv
; i
++) {
2752 name
= xstrdup(options
.setenv
[i
]);
2753 if ((val
= strchr(name
, '=')) == NULL
) {
2758 client_send_env(ssh
, id
, name
, val
);
2762 len
= sshbuf_len(cmd
);
2766 if (want_subsystem
) {
2767 debug("Sending subsystem: %.*s",
2768 (int)len
, (const u_char
*)sshbuf_ptr(cmd
));
2769 channel_request_start(ssh
, id
, "subsystem", 1);
2770 client_expect_confirm(ssh
, id
, "subsystem",
2773 debug("Sending command: %.*s",
2774 (int)len
, (const u_char
*)sshbuf_ptr(cmd
));
2775 channel_request_start(ssh
, id
, "exec", 1);
2776 client_expect_confirm(ssh
, id
, "exec", CONFIRM_CLOSE
);
2778 if ((r
= sshpkt_put_stringb(ssh
, cmd
)) != 0 ||
2779 (r
= sshpkt_send(ssh
)) != 0)
2780 fatal_fr(r
, "send command");
2782 channel_request_start(ssh
, id
, "shell", 1);
2783 client_expect_confirm(ssh
, id
, "shell", CONFIRM_CLOSE
);
2784 if ((r
= sshpkt_send(ssh
)) != 0)
2785 fatal_fr(r
, "send shell");
2788 session_setup_complete
= 1;
2793 client_init_dispatch(struct ssh
*ssh
)
2795 ssh_dispatch_init(ssh
, &dispatch_protocol_error
);
2797 ssh_dispatch_set(ssh
, SSH2_MSG_CHANNEL_CLOSE
, &channel_input_oclose
);
2798 ssh_dispatch_set(ssh
, SSH2_MSG_CHANNEL_DATA
, &channel_input_data
);
2799 ssh_dispatch_set(ssh
, SSH2_MSG_CHANNEL_EOF
, &channel_input_ieof
);
2800 ssh_dispatch_set(ssh
, SSH2_MSG_CHANNEL_EXTENDED_DATA
, &channel_input_extended_data
);
2801 ssh_dispatch_set(ssh
, SSH2_MSG_CHANNEL_OPEN
, &client_input_channel_open
);
2802 ssh_dispatch_set(ssh
, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION
, &channel_input_open_confirmation
);
2803 ssh_dispatch_set(ssh
, SSH2_MSG_CHANNEL_OPEN_FAILURE
, &channel_input_open_failure
);
2804 ssh_dispatch_set(ssh
, SSH2_MSG_CHANNEL_REQUEST
, &client_input_channel_req
);
2805 ssh_dispatch_set(ssh
, SSH2_MSG_CHANNEL_WINDOW_ADJUST
, &channel_input_window_adjust
);
2806 ssh_dispatch_set(ssh
, SSH2_MSG_CHANNEL_SUCCESS
, &channel_input_status_confirm
);
2807 ssh_dispatch_set(ssh
, SSH2_MSG_CHANNEL_FAILURE
, &channel_input_status_confirm
);
2808 ssh_dispatch_set(ssh
, SSH2_MSG_GLOBAL_REQUEST
, &client_input_global_request
);
2811 ssh_dispatch_set(ssh
, SSH2_MSG_KEXINIT
, &kex_input_kexinit
);
2813 /* global request reply messages */
2814 ssh_dispatch_set(ssh
, SSH2_MSG_REQUEST_FAILURE
, &client_global_request_reply
);
2815 ssh_dispatch_set(ssh
, SSH2_MSG_REQUEST_SUCCESS
, &client_global_request_reply
);
2819 client_stop_mux(void)
2821 if (options
.control_path
!= NULL
&& muxserver_sock
!= -1)
2822 unlink(options
.control_path
);
2824 * If we are in persist mode, or don't have a shell, signal that we
2825 * should close when all active channels are closed.
2827 if (options
.control_persist
|| options
.session_type
== SESSION_TYPE_NONE
) {
2829 setproctitle("[stopped mux]");
2833 /* client specific fatal cleanup */
2837 leave_raw_mode(options
.request_tty
== REQUEST_TTY_FORCE
);
2838 if (options
.control_path
!= NULL
&& muxserver_sock
!= -1)
2839 unlink(options
.control_path
);
2840 ssh_kill_proxy_command();