Bug Summary

File:src/usr.bin/ssh/ssh/../clientloop.c
Warning:line 2182, column 7
Although the value stored to 'r' is used in the enclosing expression, the value is never actually read from 'r'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name clientloop.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/ssh/ssh/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.bin/ssh/ssh/.. -D WITH_OPENSSL -D WITH_ZLIB -D ENABLE_PKCS11 -D HAVE_DLOPEN -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/usr/src/usr.bin/ssh/ssh/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/ssh/ssh/../clientloop.c
1/* $OpenBSD: clientloop.c,v 1.376 2022/01/11 01:26:47 djm Exp $ */
2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 * All rights reserved
6 * The main loop for the interactive session (client side).
7 *
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".
13 *
14 *
15 * Copyright (c) 1999 Theo de Raadt. All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
19 * are met:
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.
25 *
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.
36 *
37 *
38 * SSH2 support added by Markus Friedl.
39 * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved.
40 *
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
43 * are met:
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.
49 *
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.
60 */
61
62
63#include <sys/types.h>
64#include <sys/ioctl.h>
65#include <sys/stat.h>
66#include <sys/socket.h>
67#include <sys/time.h>
68#include <sys/queue.h>
69
70#include <ctype.h>
71#include <errno(*__errno()).h>
72#include <paths.h>
73#include <poll.h>
74#include <signal.h>
75#include <stdio.h>
76#include <stdlib.h>
77#include <string.h>
78#include <stdarg.h>
79#include <termios.h>
80#include <pwd.h>
81#include <unistd.h>
82#include <limits.h>
83
84#include "xmalloc.h"
85#include "ssh.h"
86#include "ssh2.h"
87#include "packet.h"
88#include "sshbuf.h"
89#include "compat.h"
90#include "channels.h"
91#include "dispatch.h"
92#include "sshkey.h"
93#include "cipher.h"
94#include "kex.h"
95#include "myproposal.h"
96#include "log.h"
97#include "misc.h"
98#include "readconf.h"
99#include "clientloop.h"
100#include "sshconnect.h"
101#include "authfd.h"
102#include "atomicio.h"
103#include "sshpty.h"
104#include "match.h"
105#include "msg.h"
106#include "ssherr.h"
107#include "hostfile.h"
108
109/* Permitted RSA signature algorithms for UpdateHostkeys proofs */
110#define HOSTKEY_PROOF_RSA_ALGS"rsa-sha2-512,rsa-sha2-256" "rsa-sha2-512,rsa-sha2-256"
111
112/* import options */
113extern Options options;
114
115/* Control socket */
116extern int muxserver_sock; /* XXX use mux_client_cleanup() instead */
117
118/*
119 * Name of the host we are connecting to. This is the name given on the
120 * command line, or the Hostname specified for the user-supplied name in a
121 * configuration file.
122 */
123extern char *host;
124
125/*
126 * If this field is not NULL, the ForwardAgent socket is this path and different
127 * instead of SSH_AUTH_SOCK.
128 */
129extern char *forward_agent_sock_path;
130
131/*
132 * Flag to indicate that we have received a window change signal which has
133 * not yet been processed. This will cause a message indicating the new
134 * window size to be sent to the server a little later. This is volatile
135 * because this is updated in a signal handler.
136 */
137static volatile sig_atomic_t received_window_change_signal = 0;
138static volatile sig_atomic_t received_signal = 0;
139
140/* Time when backgrounded control master using ControlPersist should exit */
141static time_t control_persist_exit_time = 0;
142
143/* Common data for the client loop code. */
144volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */
145static int last_was_cr; /* Last character was a newline. */
146static int exit_status; /* Used to store the command exit status. */
147static struct sshbuf *stderr_buffer; /* Used for final exit message. */
148static int connection_in; /* Connection to server (input). */
149static int connection_out; /* Connection to server (output). */
150static int need_rekeying; /* Set to non-zero if rekeying is requested. */
151static int session_closed; /* In SSH2: login session closed. */
152static u_int x11_refuse_time; /* If >0, refuse x11 opens after this time. */
153static time_t server_alive_time; /* Time to do server_alive_check */
154
155static void client_init_dispatch(struct ssh *ssh);
156int session_ident = -1;
157
158/* Track escape per proto2 channel */
159struct escape_filter_ctx {
160 int escape_pending;
161 int escape_char;
162};
163
164/* Context for channel confirmation replies */
165struct channel_reply_ctx {
166 const char *request_type;
167 int id;
168 enum confirm_action action;
169};
170
171/* Global request success/failure callbacks */
172/* XXX move to struct ssh? */
173struct global_confirm {
174 TAILQ_ENTRY(global_confirm)struct { struct global_confirm *tqe_next; struct global_confirm
**tqe_prev; }
entry;
175 global_confirm_cb *cb;
176 void *ctx;
177 int ref_count;
178};
179TAILQ_HEAD(global_confirms, global_confirm)struct global_confirms { struct global_confirm *tqh_first; struct
global_confirm **tqh_last; }
;
180static struct global_confirms global_confirms =
181 TAILQ_HEAD_INITIALIZER(global_confirms){ ((void *)0), &(global_confirms).tqh_first };
182
183void ssh_process_session2_setup(int, int, int, struct sshbuf *);
184
185/*
186 * Signal handler for the window change signal (SIGWINCH). This just sets a
187 * flag indicating that the window has changed.
188 */
189/*ARGSUSED */
190static void
191window_change_handler(int sig)
192{
193 received_window_change_signal = 1;
194}
195
196/*
197 * Signal handler for signals that cause the program to terminate. These
198 * signals must be trapped to restore terminal modes.
199 */
200/*ARGSUSED */
201static void
202signal_handler(int sig)
203{
204 received_signal = sig;
205 quit_pending = 1;
206}
207
208/*
209 * Sets control_persist_exit_time to the absolute time when the
210 * backgrounded control master should exit due to expiry of the
211 * ControlPersist timeout. Sets it to 0 if we are not a backgrounded
212 * control master process, or if there is no ControlPersist timeout.
213 */
214static void
215set_control_persist_exit_time(struct ssh *ssh)
216{
217 if (muxserver_sock == -1 || !options.control_persist
218 || options.control_persist_timeout == 0) {
219 /* not using a ControlPersist timeout */
220 control_persist_exit_time = 0;
221 } else if (channel_still_open(ssh)) {
222 /* some client connections are still open */
223 if (control_persist_exit_time > 0)
224 debug2_f("cancel scheduled exit")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 224
, 1, SYSLOG_LEVEL_DEBUG2, ((void *)0), "cancel scheduled exit"
)
;
225 control_persist_exit_time = 0;
226 } else if (control_persist_exit_time <= 0) {
227 /* a client connection has recently closed */
228 control_persist_exit_time = monotime() +
229 (time_t)options.control_persist_timeout;
230 debug2_f("schedule exit in %d seconds",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 231
, 1, SYSLOG_LEVEL_DEBUG2, ((void *)0), "schedule exit in %d seconds"
, options.control_persist_timeout)
231 options.control_persist_timeout)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 231
, 1, SYSLOG_LEVEL_DEBUG2, ((void *)0), "schedule exit in %d seconds"
, options.control_persist_timeout)
;
232 }
233 /* else we are already counting down to the timeout */
234}
235
236#define SSH_X11_VALID_DISPLAY_CHARS":/.-_" ":/.-_"
237static int
238client_x11_display_valid(const char *display)
239{
240 size_t i, dlen;
241
242 if (display == NULL((void *)0))
243 return 0;
244
245 dlen = strlen(display);
246 for (i = 0; i < dlen; i++) {
247 if (!isalnum((u_char)display[i]) &&
248 strchr(SSH_X11_VALID_DISPLAY_CHARS":/.-_", display[i]) == NULL((void *)0)) {
249 debug("Invalid character '%c' in DISPLAY", display[i])sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 249
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "Invalid character '%c' in DISPLAY"
, display[i])
;
250 return 0;
251 }
252 }
253 return 1;
254}
255
256#define SSH_X11_PROTO"MIT-MAGIC-COOKIE-1" "MIT-MAGIC-COOKIE-1"
257#define X11_TIMEOUT_SLACK60 60
258int
259client_x11_get_proto(struct ssh *ssh, const char *display,
260 const char *xauth_path, u_int trusted, u_int timeout,
261 char **_proto, char **_data)
262{
263 char *cmd, line[512], xdisplay[512];
264 char xauthfile[PATH_MAX1024], xauthdir[PATH_MAX1024];
265 static char proto[512], data[512];
266 FILE *f;
267 int got_data = 0, generated = 0, do_unlink = 0, r;
268 struct stat st;
269 u_int now, x11_timeout_real;
270
271 *_proto = proto;
272 *_data = data;
273 proto[0] = data[0] = xauthfile[0] = xauthdir[0] = '\0';
274
275 if (!client_x11_display_valid(display)) {
276 if (display != NULL((void *)0))
277 logit("DISPLAY \"%s\" invalid; disabling X11 forwarding",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 278
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "DISPLAY \"%s\" invalid; disabling X11 forwarding"
, display)
278 display)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 278
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "DISPLAY \"%s\" invalid; disabling X11 forwarding"
, display)
;
279 return -1;
280 }
281 if (xauth_path != NULL((void *)0) && stat(xauth_path, &st) == -1) {
282 debug("No xauth program.")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 282
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "No xauth program.")
;
283 xauth_path = NULL((void *)0);
284 }
285
286 if (xauth_path != NULL((void *)0)) {
287 /*
288 * Handle FamilyLocal case where $DISPLAY does
289 * not match an authorization entry. For this we
290 * just try "xauth list unix:displaynum.screennum".
291 * XXX: "localhost" match to determine FamilyLocal
292 * is not perfect.
293 */
294 if (strncmp(display, "localhost:", 10) == 0) {
295 if ((r = snprintf(xdisplay, sizeof(xdisplay), "unix:%s",
296 display + 10)) < 0 ||
297 (size_t)r >= sizeof(xdisplay)) {
298 error_f("display name too long")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 298
, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "display name too long"
)
;
299 return -1;
300 }
301 display = xdisplay;
302 }
303 if (trusted == 0) {
304 /*
305 * Generate an untrusted X11 auth cookie.
306 *
307 * The authentication cookie should briefly outlive
308 * ssh's willingness to forward X11 connections to
309 * avoid nasty fail-open behaviour in the X server.
310 */
311 mktemp_proto(xauthdir, sizeof(xauthdir));
312 if (mkdtemp(xauthdir) == NULL((void *)0)) {
313 error_f("mkdtemp: %s", strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 313
, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "mkdtemp: %s", strerror
((*__errno())))
;
314 return -1;
315 }
316 do_unlink = 1;
317 if ((r = snprintf(xauthfile, sizeof(xauthfile),
318 "%s/xauthfile", xauthdir)) < 0 ||
319 (size_t)r >= sizeof(xauthfile)) {
320 error_f("xauthfile path too long")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 320
, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "xauthfile path too long"
)
;
321 rmdir(xauthdir);
322 return -1;
323 }
324
325 if (timeout == 0) {
326 /* auth doesn't time out */
327 xasprintf(&cmd, "%s -f %s generate %s %s "
328 "untrusted 2>%s",
329 xauth_path, xauthfile, display,
330 SSH_X11_PROTO"MIT-MAGIC-COOKIE-1", _PATH_DEVNULL"/dev/null");
331 } else {
332 /* Add some slack to requested expiry */
333 if (timeout < UINT_MAX(2147483647 *2U +1U) - X11_TIMEOUT_SLACK60)
334 x11_timeout_real = timeout +
335 X11_TIMEOUT_SLACK60;
336 else {
337 /* Don't overflow on long timeouts */
338 x11_timeout_real = UINT_MAX(2147483647 *2U +1U);
339 }
340 xasprintf(&cmd, "%s -f %s generate %s %s "
341 "untrusted timeout %u 2>%s",
342 xauth_path, xauthfile, display,
343 SSH_X11_PROTO"MIT-MAGIC-COOKIE-1", x11_timeout_real,
344 _PATH_DEVNULL"/dev/null");
345 }
346 debug2_f("xauth command: %s", cmd)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 346
, 1, SYSLOG_LEVEL_DEBUG2, ((void *)0), "xauth command: %s", cmd
)
;
347
348 if (timeout != 0 && x11_refuse_time == 0) {
349 now = monotime() + 1;
350 if (UINT_MAX(2147483647 *2U +1U) - timeout < now)
351 x11_refuse_time = UINT_MAX(2147483647 *2U +1U);
352 else
353 x11_refuse_time = now + timeout;
354 channel_set_x11_refuse_time(ssh,
355 x11_refuse_time);
356 }
357 if (system(cmd) == 0)
358 generated = 1;
359 free(cmd);
360 }
361
362 /*
363 * When in untrusted mode, we read the cookie only if it was
364 * successfully generated as an untrusted one in the step
365 * above.
366 */
367 if (trusted || generated) {
368 xasprintf(&cmd,
369 "%s %s%s list %s 2>" _PATH_DEVNULL"/dev/null",
370 xauth_path,
371 generated ? "-f " : "" ,
372 generated ? xauthfile : "",
373 display);
374 debug2("x11_get_proto: %s", cmd)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 374
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "x11_get_proto: %s", cmd
)
;
375 f = popen(cmd, "r");
376 if (f && fgets(line, sizeof(line), f) &&
377 sscanf(line, "%*s %511s %511s", proto, data) == 2)
378 got_data = 1;
379 if (f)
380 pclose(f);
381 free(cmd);
382 }
383 }
384
385 if (do_unlink) {
386 unlink(xauthfile);
387 rmdir(xauthdir);
388 }
389
390 /* Don't fall back to fake X11 data for untrusted forwarding */
391 if (!trusted && !got_data) {
392 error("Warning: untrusted X11 forwarding setup failed: "sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 393
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Warning: untrusted X11 forwarding setup failed: "
"xauth key data not generated")
393 "xauth key data not generated")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 393
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Warning: untrusted X11 forwarding setup failed: "
"xauth key data not generated")
;
394 return -1;
395 }
396
397 /*
398 * If we didn't get authentication data, just make up some
399 * data. The forwarding code will check the validity of the
400 * response anyway, and substitute this data. The X11
401 * server, however, will ignore this fake data and use
402 * whatever authentication mechanisms it was using otherwise
403 * for the local connection.
404 */
405 if (!got_data) {
406 u_int8_t rnd[16];
407 u_int i;
408
409 logit("Warning: No xauth data; "sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 410
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Warning: No xauth data; "
"using fake authentication data for X11 forwarding.")
410 "using fake authentication data for X11 forwarding.")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 410
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Warning: No xauth data; "
"using fake authentication data for X11 forwarding.")
;
411 strlcpy(proto, SSH_X11_PROTO"MIT-MAGIC-COOKIE-1", sizeof proto);
412 arc4random_buf(rnd, sizeof(rnd));
413 for (i = 0; i < sizeof(rnd); i++) {
414 snprintf(data + 2 * i, sizeof data - 2 * i, "%02x",
415 rnd[i]);
416 }
417 }
418
419 return 0;
420}
421
422/*
423 * Checks if the client window has changed, and sends a packet about it to
424 * the server if so. The actual change is detected elsewhere (by a software
425 * interrupt on Unix); this just checks the flag and sends a message if
426 * appropriate.
427 */
428
429static void
430client_check_window_change(struct ssh *ssh)
431{
432 if (!received_window_change_signal)
433 return;
434 received_window_change_signal = 0;
435 debug2_f("changed")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 435
, 1, SYSLOG_LEVEL_DEBUG2, ((void *)0), "changed")
;
436 channel_send_window_changes(ssh);
437}
438
439static int
440client_global_request_reply(int type, u_int32_t seq, struct ssh *ssh)
441{
442 struct global_confirm *gc;
443
444 if ((gc = TAILQ_FIRST(&global_confirms)((&global_confirms)->tqh_first)) == NULL((void *)0))
445 return 0;
446 if (gc->cb != NULL((void *)0))
447 gc->cb(ssh, type, seq, gc->ctx);
448 if (--gc->ref_count <= 0) {
449 TAILQ_REMOVE(&global_confirms, gc, entry)do { if (((gc)->entry.tqe_next) != ((void *)0)) (gc)->entry
.tqe_next->entry.tqe_prev = (gc)->entry.tqe_prev; else (
&global_confirms)->tqh_last = (gc)->entry.tqe_prev;
*(gc)->entry.tqe_prev = (gc)->entry.tqe_next; ; ; } while
(0)
;
450 freezero(gc, sizeof(*gc));
451 }
452
453 ssh_packet_set_alive_timeouts(ssh, 0);
454 return 0;
455}
456
457static void
458schedule_server_alive_check(void)
459{
460 if (options.server_alive_interval > 0)
461 server_alive_time = monotime() + options.server_alive_interval;
462}
463
464static void
465server_alive_check(struct ssh *ssh)
466{
467 int r;
468
469 if (ssh_packet_inc_alive_timeouts(ssh) > options.server_alive_count_max) {
470 logit("Timeout, server %s not responding.", host)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 470
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Timeout, server %s not responding."
, host)
;
471 cleanup_exit(255);
472 }
473 if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST80)) != 0 ||
474 (r = sshpkt_put_cstring(ssh, "keepalive@openssh.com")) != 0 ||
475 (r = sshpkt_put_u8(ssh, 1)) != 0 || /* boolean: want reply */
476 (r = sshpkt_send(ssh)) != 0)
477 fatal_fr(r, "send packet")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 477, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "send packet")
;
478 /* Insert an empty placeholder to maintain ordering */
479 client_register_global_confirm(NULL((void *)0), NULL((void *)0));
480 schedule_server_alive_check();
481}
482
483/*
484 * Waits until the client can do something (some data becomes available on
485 * one of the file descriptors).
486 */
487static void
488client_wait_until_can_do_something(struct ssh *ssh, struct pollfd **pfdp,
489 u_int *npfd_allocp, u_int *npfd_activep, int rekeying,
490 int *conn_in_readyp, int *conn_out_readyp)
491{
492 int timeout_secs, pollwait;
493 time_t minwait_secs = 0, now = monotime();
494 int r, ret;
495 u_int p;
496
497 *conn_in_readyp = *conn_out_readyp = 0;
498
499 /* Prepare channel poll. First two pollfd entries are reserved */
500 channel_prepare_poll(ssh, pfdp, npfd_allocp, npfd_activep, 2,
501 &minwait_secs);
502 if (*npfd_activep < 2)
503 fatal_f("bad npfd %u", *npfd_activep)sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 503, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "bad npfd %u", *npfd_activep
)
; /* shouldn't happen */
504
505 /* channel_prepare_poll could have closed the last channel */
506 if (session_closed && !channel_still_open(ssh) &&
507 !ssh_packet_have_data_to_write(ssh)) {
508 /* clear events since we did not call poll() */
509 for (p = 0; p < *npfd_activep; p++)
510 (*pfdp)[p].revents = 0;
511 return;
512 }
513
514 /* Monitor server connection on reserved pollfd entries */
515 (*pfdp)[0].fd = connection_in;
516 (*pfdp)[0].events = POLLIN0x0001;
517 (*pfdp)[1].fd = connection_out;
518 (*pfdp)[1].events = ssh_packet_have_data_to_write(ssh) ? POLLOUT0x0004 : 0;
519
520 /*
521 * Wait for something to happen. This will suspend the process until
522 * some polled descriptor can be read, written, or has some other
523 * event pending, or a timeout expires.
524 */
525
526 timeout_secs = INT_MAX2147483647; /* we use INT_MAX to mean no timeout */
527 if (options.server_alive_interval > 0)
528 timeout_secs = MAXIMUM(server_alive_time - now, 0)(((server_alive_time - now) > (0)) ? (server_alive_time - now
) : (0))
;
529 if (options.rekey_interval > 0 && !rekeying)
530 timeout_secs = MINIMUM(timeout_secs,(((timeout_secs) < (ssh_packet_get_rekey_timeout(ssh))) ? (
timeout_secs) : (ssh_packet_get_rekey_timeout(ssh)))
531 ssh_packet_get_rekey_timeout(ssh))(((timeout_secs) < (ssh_packet_get_rekey_timeout(ssh))) ? (
timeout_secs) : (ssh_packet_get_rekey_timeout(ssh)))
;
532 set_control_persist_exit_time(ssh);
533 if (control_persist_exit_time > 0) {
534 timeout_secs = MINIMUM(timeout_secs,(((timeout_secs) < (control_persist_exit_time - now)) ? (timeout_secs
) : (control_persist_exit_time - now))
535 control_persist_exit_time - now)(((timeout_secs) < (control_persist_exit_time - now)) ? (timeout_secs
) : (control_persist_exit_time - now))
;
536 if (timeout_secs < 0)
537 timeout_secs = 0;
538 }
539 if (minwait_secs != 0)
540 timeout_secs = MINIMUM(timeout_secs, (int)minwait_secs)(((timeout_secs) < ((int)minwait_secs)) ? (timeout_secs) :
((int)minwait_secs))
;
541 if (timeout_secs == INT_MAX2147483647)
542 pollwait = -1;
543 else if (timeout_secs >= INT_MAX2147483647 / 1000)
544 pollwait = INT_MAX2147483647;
545 else
546 pollwait = timeout_secs * 1000;
547
548 ret = poll(*pfdp, *npfd_activep, pollwait);
549
550 if (ret == -1) {
551 /*
552 * We have to clear the events because we return.
553 * We have to return, because the mainloop checks for the flags
554 * set by the signal handlers.
555 */
556 for (p = 0; p < *npfd_activep; p++)
557 (*pfdp)[p].revents = 0;
558 if (errno(*__errno()) == EINTR4)
559 return;
560 /* Note: we might still have data in the buffers. */
561 if ((r = sshbuf_putf(stderr_buffer,
562 "poll: %s\r\n", strerror(errno(*__errno())))) != 0)
563 fatal_fr(r, "sshbuf_putf")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 563, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "sshbuf_putf")
;
564 quit_pending = 1;
565 return;
566 }
567
568 *conn_in_readyp = (*pfdp)[0].revents != 0;
569 *conn_out_readyp = (*pfdp)[1].revents != 0;
570
571 if (options.server_alive_interval > 0 && !*conn_in_readyp &&
572 monotime() >= server_alive_time) {
573 /*
574 * ServerAlive check is needed. We can't rely on the poll
575 * timing out since traffic on the client side such as port
576 * forwards can keep waking it up.
577 */
578 server_alive_check(ssh);
579 }
580}
581
582static void
583client_suspend_self(struct sshbuf *bin, struct sshbuf *bout, struct sshbuf *berr)
584{
585 /* Flush stdout and stderr buffers. */
586 if (sshbuf_len(bout) > 0)
587 atomicio(vwrite(ssize_t (*)(int, void *, size_t))write, fileno(stdout)(!__isthreaded ? (((&__sF[1]))->_file) : (fileno)((&
__sF[1])))
, sshbuf_mutable_ptr(bout),
588 sshbuf_len(bout));
589 if (sshbuf_len(berr) > 0)
590 atomicio(vwrite(ssize_t (*)(int, void *, size_t))write, fileno(stderr)(!__isthreaded ? (((&__sF[2]))->_file) : (fileno)((&
__sF[2])))
, sshbuf_mutable_ptr(berr),
591 sshbuf_len(berr));
592
593 leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE3);
594
595 sshbuf_reset(bin);
596 sshbuf_reset(bout);
597 sshbuf_reset(berr);
598
599 /* Send the suspend signal to the program itself. */
600 kill(getpid(), SIGTSTP18);
601
602 /* Reset window sizes in case they have changed */
603 received_window_change_signal = 1;
604
605 enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE3);
606}
607
608static void
609client_process_net_input(struct ssh *ssh)
610{
611 char buf[8192];
612 int r, len;
613
614 /*
615 * Read input from the server, and add any such data to the buffer of
616 * the packet subsystem.
617 */
618 schedule_server_alive_check();
619 /* Read as much as possible. */
620 len = read(connection_in, buf, sizeof(buf));
621 if (len == 0) {
622 /* Received EOF. The remote host has closed the connection. */
623 if ((r = sshbuf_putf(stderr_buffer,
624 "Connection to %.300s closed by remote host.\r\n",
625 host)) != 0)
626 fatal_fr(r, "sshbuf_putf")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 626, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "sshbuf_putf")
;
627 quit_pending = 1;
628 return;
629 }
630 /*
631 * There is a kernel bug on Solaris that causes poll to
632 * sometimes wake up even though there is no data available.
633 */
634 if (len == -1 && (errno(*__errno()) == EAGAIN35 || errno(*__errno()) == EINTR4))
635 len = 0;
636
637 if (len == -1) {
638 /*
639 * An error has encountered. Perhaps there is a
640 * network problem.
641 */
642 if ((r = sshbuf_putf(stderr_buffer,
643 "Read from remote host %.300s: %.100s\r\n",
644 host, strerror(errno(*__errno())))) != 0)
645 fatal_fr(r, "sshbuf_putf")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 645, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "sshbuf_putf")
;
646 quit_pending = 1;
647 return;
648 }
649 ssh_packet_process_incoming(ssh, buf, len);
650}
651
652static void
653client_status_confirm(struct ssh *ssh, int type, Channel *c, void *ctx)
654{
655 struct channel_reply_ctx *cr = (struct channel_reply_ctx *)ctx;
656 char errmsg[256];
657 int r, tochan;
658
659 /*
660 * If a TTY was explicitly requested, then a failure to allocate
661 * one is fatal.
662 */
663 if (cr->action == CONFIRM_TTY &&
664 (options.request_tty == REQUEST_TTY_FORCE3 ||
665 options.request_tty == REQUEST_TTY_YES2))
666 cr->action = CONFIRM_CLOSE;
667
668 /* XXX suppress on mux _client_ quietmode */
669 tochan = options.log_level >= SYSLOG_LEVEL_ERROR &&
670 c->ctl_chan != -1 && c->extended_usage == CHAN_EXTENDED_WRITE2;
671
672 if (type == SSH2_MSG_CHANNEL_SUCCESS99) {
673 debug2("%s request accepted on channel %d",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 674
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "%s request accepted on channel %d"
, cr->request_type, c->self)
674 cr->request_type, c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 674
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "%s request accepted on channel %d"
, cr->request_type, c->self)
;
675 } else if (type == SSH2_MSG_CHANNEL_FAILURE100) {
676 if (tochan) {
677 snprintf(errmsg, sizeof(errmsg),
678 "%s request failed\r\n", cr->request_type);
679 } else {
680 snprintf(errmsg, sizeof(errmsg),
681 "%s request failed on channel %d",
682 cr->request_type, c->self);
683 }
684 /* If error occurred on primary session channel, then exit */
685 if (cr->action == CONFIRM_CLOSE && c->self == session_ident)
686 fatal("%s", errmsg)sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 686, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "%s", errmsg)
;
687 /*
688 * If error occurred on mux client, append to
689 * their stderr.
690 */
691 if (tochan) {
692 debug3_f("channel %d: mux request: %s", c->self,sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 693
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "channel %d: mux request: %s"
, c->self, cr->request_type)
693 cr->request_type)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 693
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "channel %d: mux request: %s"
, c->self, cr->request_type)
;
694 if ((r = sshbuf_put(c->extended, errmsg,
695 strlen(errmsg))) != 0)
696 fatal_fr(r, "sshbuf_put")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 696, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "sshbuf_put")
;
697 } else
698 error("%s", errmsg)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 698
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%s", errmsg)
;
699 if (cr->action == CONFIRM_TTY) {
700 /*
701 * If a TTY allocation error occurred, then arrange
702 * for the correct TTY to leave raw mode.
703 */
704 if (c->self == session_ident)
705 leave_raw_mode(0);
706 else
707 mux_tty_alloc_failed(ssh, c);
708 } else if (cr->action == CONFIRM_CLOSE) {
709 chan_read_failed(ssh, c);
710 chan_write_failed(ssh, c);
711 }
712 }
713 free(cr);
714}
715
716static void
717client_abandon_status_confirm(struct ssh *ssh, Channel *c, void *ctx)
718{
719 free(ctx);
720}
721
722void
723client_expect_confirm(struct ssh *ssh, int id, const char *request,
724 enum confirm_action action)
725{
726 struct channel_reply_ctx *cr = xcalloc(1, sizeof(*cr));
727
728 cr->request_type = request;
729 cr->action = action;
730
731 channel_register_status_confirm(ssh, id, client_status_confirm,
732 client_abandon_status_confirm, cr);
733}
734
735void
736client_register_global_confirm(global_confirm_cb *cb, void *ctx)
737{
738 struct global_confirm *gc, *last_gc;
739
740 /* Coalesce identical callbacks */
741 last_gc = TAILQ_LAST(&global_confirms, global_confirms)(*(((struct global_confirms *)((&global_confirms)->tqh_last
))->tqh_last))
;
742 if (last_gc && last_gc->cb == cb && last_gc->ctx == ctx) {
743 if (++last_gc->ref_count >= INT_MAX2147483647)
744 fatal_f("last_gc->ref_count = %d",sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 745, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "last_gc->ref_count = %d"
, last_gc->ref_count)
745 last_gc->ref_count)sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 745, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "last_gc->ref_count = %d"
, last_gc->ref_count)
;
746 return;
747 }
748
749 gc = xcalloc(1, sizeof(*gc));
750 gc->cb = cb;
751 gc->ctx = ctx;
752 gc->ref_count = 1;
753 TAILQ_INSERT_TAIL(&global_confirms, gc, entry)do { (gc)->entry.tqe_next = ((void *)0); (gc)->entry.tqe_prev
= (&global_confirms)->tqh_last; *(&global_confirms
)->tqh_last = (gc); (&global_confirms)->tqh_last = &
(gc)->entry.tqe_next; } while (0)
;
754}
755
756static void
757process_cmdline(struct ssh *ssh)
758{
759 void (*handler)(int);
760 char *s, *cmd;
761 int ok, delete = 0, local = 0, remote = 0, dynamic = 0;
762 struct Forward fwd;
763
764 memset(&fwd, 0, sizeof(fwd));
765
766 leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE3);
767 handler = ssh_signal(SIGINT2, SIG_IGN(void (*)(int))1);
768 cmd = s = read_passphrase("\r\nssh> ", RP_ECHO0x0001);
769 if (s == NULL((void *)0))
770 goto out;
771 while (isspace((u_char)*s))
772 s++;
773 if (*s == '-')
774 s++; /* Skip cmdline '-', if any */
775 if (*s == '\0')
776 goto out;
777
778 if (*s == 'h' || *s == 'H' || *s == '?') {
779 logit("Commands:")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 779
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Commands:")
;
780 logit(" -L[bind_address:]port:host:hostport "sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 781
, 0, SYSLOG_LEVEL_INFO, ((void *)0), " -L[bind_address:]port:host:hostport "
"Request local forward")
781 "Request local forward")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 781
, 0, SYSLOG_LEVEL_INFO, ((void *)0), " -L[bind_address:]port:host:hostport "
"Request local forward")
;
782 logit(" -R[bind_address:]port:host:hostport "sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 783
, 0, SYSLOG_LEVEL_INFO, ((void *)0), " -R[bind_address:]port:host:hostport "
"Request remote forward")
783 "Request remote forward")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 783
, 0, SYSLOG_LEVEL_INFO, ((void *)0), " -R[bind_address:]port:host:hostport "
"Request remote forward")
;
784 logit(" -D[bind_address:]port "sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 785
, 0, SYSLOG_LEVEL_INFO, ((void *)0), " -D[bind_address:]port "
"Request dynamic forward")
785 "Request dynamic forward")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 785
, 0, SYSLOG_LEVEL_INFO, ((void *)0), " -D[bind_address:]port "
"Request dynamic forward")
;
786 logit(" -KL[bind_address:]port "sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 787
, 0, SYSLOG_LEVEL_INFO, ((void *)0), " -KL[bind_address:]port "
"Cancel local forward")
787 "Cancel local forward")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 787
, 0, SYSLOG_LEVEL_INFO, ((void *)0), " -KL[bind_address:]port "
"Cancel local forward")
;
788 logit(" -KR[bind_address:]port "sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 789
, 0, SYSLOG_LEVEL_INFO, ((void *)0), " -KR[bind_address:]port "
"Cancel remote forward")
789 "Cancel remote forward")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 789
, 0, SYSLOG_LEVEL_INFO, ((void *)0), " -KR[bind_address:]port "
"Cancel remote forward")
;
790 logit(" -KD[bind_address:]port "sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 791
, 0, SYSLOG_LEVEL_INFO, ((void *)0), " -KD[bind_address:]port "
"Cancel dynamic forward")
791 "Cancel dynamic forward")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 791
, 0, SYSLOG_LEVEL_INFO, ((void *)0), " -KD[bind_address:]port "
"Cancel dynamic forward")
;
792 if (!options.permit_local_command)
793 goto out;
794 logit(" !args "sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 795
, 0, SYSLOG_LEVEL_INFO, ((void *)0), " !args "
"Execute local command")
795 "Execute local command")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 795
, 0, SYSLOG_LEVEL_INFO, ((void *)0), " !args "
"Execute local command")
;
796 goto out;
797 }
798
799 if (*s == '!' && options.permit_local_command) {
800 s++;
801 ssh_local_cmd(s);
802 goto out;
803 }
804
805 if (*s == 'K') {
806 delete = 1;
807 s++;
808 }
809 if (*s == 'L')
810 local = 1;
811 else if (*s == 'R')
812 remote = 1;
813 else if (*s == 'D')
814 dynamic = 1;
815 else {
816 logit("Invalid command.")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 816
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Invalid command.")
;
817 goto out;
818 }
819
820 while (isspace((u_char)*++s))
821 ;
822
823 /* XXX update list of forwards in options */
824 if (delete) {
825 /* We pass 1 for dynamicfwd to restrict to 1 or 2 fields. */
826 if (!parse_forward(&fwd, s, 1, 0)) {
827 logit("Bad forwarding close specification.")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 827
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Bad forwarding close specification."
)
;
828 goto out;
829 }
830 if (remote)
831 ok = channel_request_rforward_cancel(ssh, &fwd) == 0;
832 else if (dynamic)
833 ok = channel_cancel_lport_listener(ssh, &fwd,
834 0, &options.fwd_opts) > 0;
835 else
836 ok = channel_cancel_lport_listener(ssh, &fwd,
837 CHANNEL_CANCEL_PORT_STATIC-1,
838 &options.fwd_opts) > 0;
839 if (!ok) {
840 logit("Unknown port forwarding.")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 840
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Unknown port forwarding."
)
;
841 goto out;
842 }
843 logit("Canceled forwarding.")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 843
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Canceled forwarding.")
;
844 } else {
845 if (!parse_forward(&fwd, s, dynamic, remote)) {
846 logit("Bad forwarding specification.")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 846
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Bad forwarding specification."
)
;
847 goto out;
848 }
849 if (local || dynamic) {
850 if (!channel_setup_local_fwd_listener(ssh, &fwd,
851 &options.fwd_opts)) {
852 logit("Port forwarding failed.")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 852
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Port forwarding failed."
)
;
853 goto out;
854 }
855 } else {
856 if (channel_request_remote_forwarding(ssh, &fwd) < 0) {
857 logit("Port forwarding failed.")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 857
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Port forwarding failed."
)
;
858 goto out;
859 }
860 }
861 logit("Forwarding port.")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 861
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Forwarding port.")
;
862 }
863
864out:
865 ssh_signal(SIGINT2, handler);
866 enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE3);
867 free(cmd);
868 free(fwd.listen_host);
869 free(fwd.listen_path);
870 free(fwd.connect_host);
871 free(fwd.connect_path);
872}
873
874/* reasons to suppress output of an escape command in help output */
875#define SUPPRESS_NEVER0 0 /* never suppress, always show */
876#define SUPPRESS_MUXCLIENT1 1 /* don't show in mux client sessions */
877#define SUPPRESS_MUXMASTER2 2 /* don't show in mux master sessions */
878#define SUPPRESS_SYSLOG4 4 /* don't show when logging to syslog */
879struct escape_help_text {
880 const char *cmd;
881 const char *text;
882 unsigned int flags;
883};
884static struct escape_help_text esc_txt[] = {
885 {".", "terminate session", SUPPRESS_MUXMASTER2},
886 {".", "terminate connection (and any multiplexed sessions)",
887 SUPPRESS_MUXCLIENT1},
888 {"B", "send a BREAK to the remote system", SUPPRESS_NEVER0},
889 {"C", "open a command line", SUPPRESS_MUXCLIENT1},
890 {"R", "request rekey", SUPPRESS_NEVER0},
891 {"V/v", "decrease/increase verbosity (LogLevel)", SUPPRESS_MUXCLIENT1},
892 {"^Z", "suspend ssh", SUPPRESS_MUXCLIENT1},
893 {"#", "list forwarded connections", SUPPRESS_NEVER0},
894 {"&", "background ssh (when waiting for connections to terminate)",
895 SUPPRESS_MUXCLIENT1},
896 {"?", "this message", SUPPRESS_NEVER0},
897};
898
899static void
900print_escape_help(struct sshbuf *b, int escape_char, int mux_client,
901 int using_stderr)
902{
903 unsigned int i, suppress_flags;
904 int r;
905
906 if ((r = sshbuf_putf(b,
907 "%c?\r\nSupported escape sequences:\r\n", escape_char)) != 0)
908 fatal_fr(r, "sshbuf_putf")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 908, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "sshbuf_putf")
;
909
910 suppress_flags =
911 (mux_client ? SUPPRESS_MUXCLIENT1 : 0) |
912 (mux_client ? 0 : SUPPRESS_MUXMASTER2) |
913 (using_stderr ? 0 : SUPPRESS_SYSLOG4);
914
915 for (i = 0; i < sizeof(esc_txt)/sizeof(esc_txt[0]); i++) {
916 if (esc_txt[i].flags & suppress_flags)
917 continue;
918 if ((r = sshbuf_putf(b, " %c%-3s - %s\r\n",
919 escape_char, esc_txt[i].cmd, esc_txt[i].text)) != 0)
920 fatal_fr(r, "sshbuf_putf")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 920, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "sshbuf_putf")
;
921 }
922
923 if ((r = sshbuf_putf(b,
924 " %c%c - send the escape character by typing it twice\r\n"
925 "(Note that escapes are only recognized immediately after "
926 "newline.)\r\n", escape_char, escape_char)) != 0)
927 fatal_fr(r, "sshbuf_putf")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 927, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "sshbuf_putf")
;
928}
929
930/*
931 * Process the characters one by one.
932 */
933static int
934process_escapes(struct ssh *ssh, Channel *c,
935 struct sshbuf *bin, struct sshbuf *bout, struct sshbuf *berr,
936 char *buf, int len)
937{
938 pid_t pid;
939 int r, bytes = 0;
940 u_int i;
941 u_char ch;
942 char *s;
943 struct escape_filter_ctx *efc = c->filter_ctx == NULL((void *)0) ?
944 NULL((void *)0) : (struct escape_filter_ctx *)c->filter_ctx;
945
946 if (c->filter_ctx == NULL((void *)0))
947 return 0;
948
949 if (len <= 0)
950 return (0);
951
952 for (i = 0; i < (u_int)len; i++) {
953 /* Get one character at a time. */
954 ch = buf[i];
955
956 if (efc->escape_pending) {
957 /* We have previously seen an escape character. */
958 /* Clear the flag now. */
959 efc->escape_pending = 0;
960
961 /* Process the escaped character. */
962 switch (ch) {
963 case '.':
964 /* Terminate the connection. */
965 if ((r = sshbuf_putf(berr, "%c.\r\n",
966 efc->escape_char)) != 0)
967 fatal_fr(r, "sshbuf_putf")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 967, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "sshbuf_putf")
;
968 if (c && c->ctl_chan != -1) {
969 chan_read_failed(ssh, c);
970 chan_write_failed(ssh, c);
971 if (c->detach_user) {
972 c->detach_user(ssh,
973 c->self, NULL((void *)0));
974 }
975 c->type = SSH_CHANNEL_ABANDONED17;
976 sshbuf_reset(c->input);
977 chan_ibuf_empty(ssh, c);
978 return 0;
979 } else
980 quit_pending = 1;
981 return -1;
982
983 case 'Z' - 64:
984 /* XXX support this for mux clients */
985 if (c && c->ctl_chan != -1) {
986 char b[16];
987 noescape:
988 if (ch == 'Z' - 64)
989 snprintf(b, sizeof b, "^Z");
990 else
991 snprintf(b, sizeof b, "%c", ch);
992 if ((r = sshbuf_putf(berr,
993 "%c%s escape not available to "
994 "multiplexed sessions\r\n",
995 efc->escape_char, b)) != 0)
996 fatal_fr(r, "sshbuf_putf")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 996, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "sshbuf_putf")
;
997 continue;
998 }
999 /* Suspend the program. Inform the user */
1000 if ((r = sshbuf_putf(berr,
1001 "%c^Z [suspend ssh]\r\n",
1002 efc->escape_char)) != 0)
1003 fatal_fr(r, "sshbuf_putf")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 1003, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "sshbuf_putf")
;
1004
1005 /* Restore terminal modes and suspend. */
1006 client_suspend_self(bin, bout, berr);
1007
1008 /* We have been continued. */
1009 continue;
1010
1011 case 'B':
1012 if ((r = sshbuf_putf(berr,
1013 "%cB\r\n", efc->escape_char)) != 0)
1014 fatal_fr(r, "sshbuf_putf")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 1014, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "sshbuf_putf")
;
1015 channel_request_start(ssh, c->self, "break", 0);
1016 if ((r = sshpkt_put_u32(ssh, 1000)) != 0 ||
1017 (r = sshpkt_send(ssh)) != 0)
1018 fatal_fr(r, "send packet")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 1018, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "send packet")
;
1019 continue;
1020
1021 case 'R':
1022 if (ssh->compat & SSH_BUG_NOREKEY0x00008000)
1023 logit("Server does not "sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1024
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Server does not " "support re-keying"
)
1024 "support re-keying")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1024
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Server does not " "support re-keying"
)
;
1025 else
1026 need_rekeying = 1;
1027 continue;
1028
1029 case 'V':
1030 /* FALLTHROUGH */
1031 case 'v':
1032 if (c && c->ctl_chan != -1)
1033 goto noescape;
1034 if (!log_is_on_stderr()) {
1035 if ((r = sshbuf_putf(berr,
1036 "%c%c [Logging to syslog]\r\n",
1037 efc->escape_char, ch)) != 0)
1038 fatal_fr(r, "sshbuf_putf")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 1038, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "sshbuf_putf")
;
1039 continue;
1040 }
1041 if (ch == 'V' && options.log_level >
1042 SYSLOG_LEVEL_QUIET)
1043 log_change_level(--options.log_level);
1044 if (ch == 'v' && options.log_level <
1045 SYSLOG_LEVEL_DEBUG3)
1046 log_change_level(++options.log_level);
1047 if ((r = sshbuf_putf(berr,
1048 "%c%c [LogLevel %s]\r\n",
1049 efc->escape_char, ch,
1050 log_level_name(options.log_level))) != 0)
1051 fatal_fr(r, "sshbuf_putf")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 1051, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "sshbuf_putf")
;
1052 continue;
1053
1054 case '&':
1055 if (c && c->ctl_chan != -1)
1056 goto noescape;
1057 /*
1058 * Detach the program (continue to serve
1059 * connections, but put in background and no
1060 * more new connections).
1061 */
1062 /* Restore tty modes. */
1063 leave_raw_mode(
1064 options.request_tty == REQUEST_TTY_FORCE3);
1065
1066 /* Stop listening for new connections. */
1067 channel_stop_listening(ssh);
1068
1069 if ((r = sshbuf_putf(berr, "%c& "
1070 "[backgrounded]\n", efc->escape_char)) != 0)
1071 fatal_fr(r, "sshbuf_putf")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 1071, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "sshbuf_putf")
;
1072
1073 /* Fork into background. */
1074 pid = fork();
1075 if (pid == -1) {
1076 error("fork: %.100s", strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1076
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "fork: %.100s", strerror
((*__errno())))
;
1077 continue;
1078 }
1079 if (pid != 0) { /* This is the parent. */
1080 /* The parent just exits. */
1081 exit(0);
1082 }
1083 /* The child continues serving connections. */
1084 /* fake EOF on stdin */
1085 if ((r = sshbuf_put_u8(bin, 4)) != 0)
1086 fatal_fr(r, "sshbuf_put_u8")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 1086, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "sshbuf_put_u8")
;
1087 return -1;
1088 case '?':
1089 print_escape_help(berr, efc->escape_char,
1090 (c && c->ctl_chan != -1),
1091 log_is_on_stderr());
1092 continue;
1093
1094 case '#':
1095 if ((r = sshbuf_putf(berr, "%c#\r\n",
1096 efc->escape_char)) != 0)
1097 fatal_fr(r, "sshbuf_putf")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 1097, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "sshbuf_putf")
;
1098 s = channel_open_message(ssh);
1099 if ((r = sshbuf_put(berr, s, strlen(s))) != 0)
1100 fatal_fr(r, "sshbuf_put")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 1100, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "sshbuf_put")
;
1101 free(s);
1102 continue;
1103
1104 case 'C':
1105 if (c && c->ctl_chan != -1)
1106 goto noescape;
1107 process_cmdline(ssh);
1108 continue;
1109
1110 default:
1111 if (ch != efc->escape_char) {
1112 if ((r = sshbuf_put_u8(bin,
1113 efc->escape_char)) != 0)
1114 fatal_fr(r, "sshbuf_put_u8")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 1114, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "sshbuf_put_u8")
;
1115 bytes++;
1116 }
1117 /* Escaped characters fall through here */
1118 break;
1119 }
1120 } else {
1121 /*
1122 * The previous character was not an escape char.
1123 * Check if this is an escape.
1124 */
1125 if (last_was_cr && ch == efc->escape_char) {
1126 /*
1127 * It is. Set the flag and continue to
1128 * next character.
1129 */
1130 efc->escape_pending = 1;
1131 continue;
1132 }
1133 }
1134
1135 /*
1136 * Normal character. Record whether it was a newline,
1137 * and append it to the buffer.
1138 */
1139 last_was_cr = (ch == '\r' || ch == '\n');
1140 if ((r = sshbuf_put_u8(bin, ch)) != 0)
1141 fatal_fr(r, "sshbuf_put_u8")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 1141, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "sshbuf_put_u8")
;
1142 bytes++;
1143 }
1144 return bytes;
1145}
1146
1147/*
1148 * Get packets from the connection input buffer, and process them as long as
1149 * there are packets available.
1150 *
1151 * Any unknown packets received during the actual
1152 * session cause the session to terminate. This is
1153 * intended to make debugging easier since no
1154 * confirmations are sent. Any compatible protocol
1155 * extensions must be negotiated during the
1156 * preparatory phase.
1157 */
1158
1159static void
1160client_process_buffered_input_packets(struct ssh *ssh)
1161{
1162 ssh_dispatch_run_fatal(ssh, DISPATCH_NONBLOCK, &quit_pending);
1163}
1164
1165/* scan buf[] for '~' before sending data to the peer */
1166
1167/* Helper: allocate a new escape_filter_ctx and fill in its escape char */
1168void *
1169client_new_escape_filter_ctx(int escape_char)
1170{
1171 struct escape_filter_ctx *ret;
1172
1173 ret = xcalloc(1, sizeof(*ret));
1174 ret->escape_pending = 0;
1175 ret->escape_char = escape_char;
1176 return (void *)ret;
1177}
1178
1179/* Free the escape filter context on channel free */
1180void
1181client_filter_cleanup(struct ssh *ssh, int cid, void *ctx)
1182{
1183 free(ctx);
1184}
1185
1186int
1187client_simple_escape_filter(struct ssh *ssh, Channel *c, char *buf, int len)
1188{
1189 if (c->extended_usage != CHAN_EXTENDED_WRITE2)
1190 return 0;
1191
1192 return process_escapes(ssh, c, c->input, c->output, c->extended,
1193 buf, len);
1194}
1195
1196static void
1197client_channel_closed(struct ssh *ssh, int id, void *arg)
1198{
1199 channel_cancel_cleanup(ssh, id);
1200 session_closed = 1;
1201 leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE3);
1202}
1203
1204/*
1205 * Implements the interactive session with the server. This is called after
1206 * the user has been authenticated, and a command has been started on the
1207 * remote host. If escape_char != SSH_ESCAPECHAR_NONE, it is the character
1208 * used as an escape character for terminating or suspending the session.
1209 */
1210int
1211client_loop(struct ssh *ssh, int have_pty, int escape_char_arg,
1212 int ssh2_chan_id)
1213{
1214 struct pollfd *pfd = NULL((void *)0);
1215 u_int npfd_alloc = 0, npfd_active = 0;
1216 double start_time, total_time;
1217 int r, len;
1218 u_int64_t ibytes, obytes;
1219 int conn_in_ready, conn_out_ready;
1220
1221 debug("Entering interactive session.")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1221
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "Entering interactive session."
)
;
1222
1223 if (options.control_master &&
1224 !option_clear_or_none(options.control_path)) {
1225 debug("pledge: id")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1225
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "pledge: id")
;
1226 if (pledge("stdio rpath wpath cpath unix inet dns recvfd sendfd proc exec id tty",
1227 NULL((void *)0)) == -1)
1228 fatal_f("pledge(): %s", strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 1228, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "pledge(): %s", strerror
((*__errno())))
;
1229
1230 } else if (options.forward_x11 || options.permit_local_command) {
1231 debug("pledge: exec")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1231
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "pledge: exec")
;
1232 if (pledge("stdio rpath wpath cpath unix inet dns proc exec tty",
1233 NULL((void *)0)) == -1)
1234 fatal_f("pledge(): %s", strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 1234, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "pledge(): %s", strerror
((*__errno())))
;
1235
1236 } else if (options.update_hostkeys) {
1237 debug("pledge: filesystem")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1237
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "pledge: filesystem")
;
1238 if (pledge("stdio rpath wpath cpath unix inet dns proc tty",
1239 NULL((void *)0)) == -1)
1240 fatal_f("pledge(): %s", strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 1240, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "pledge(): %s", strerror
((*__errno())))
;
1241
1242 } else if (!option_clear_or_none(options.proxy_command) ||
1243 options.fork_after_authentication) {
1244 debug("pledge: proc")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1244
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "pledge: proc")
;
1245 if (pledge("stdio cpath unix inet dns proc tty", NULL((void *)0)) == -1)
1246 fatal_f("pledge(): %s", strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 1246, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "pledge(): %s", strerror
((*__errno())))
;
1247
1248 } else {
1249 debug("pledge: network")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1249
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "pledge: network")
;
1250 if (pledge("stdio unix inet dns proc tty", NULL((void *)0)) == -1)
1251 fatal_f("pledge(): %s", strerror(errno))sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 1251, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "pledge(): %s", strerror
((*__errno())))
;
1252 }
1253
1254 start_time = monotime_double();
1255
1256 /* Initialize variables. */
1257 last_was_cr = 1;
1258 exit_status = -1;
1259 connection_in = ssh_packet_get_connection_in(ssh);
1260 connection_out = ssh_packet_get_connection_out(ssh);
1261
1262 quit_pending = 0;
1263
1264 /* Initialize buffer. */
1265 if ((stderr_buffer = sshbuf_new()) == NULL((void *)0))
1266 fatal_f("sshbuf_new failed")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 1266, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "sshbuf_new failed"
)
;
1267
1268 client_init_dispatch(ssh);
1269
1270 /*
1271 * Set signal handlers, (e.g. to restore non-blocking mode)
1272 * but don't overwrite SIG_IGN, matches behaviour from rsh(1)
1273 */
1274 if (ssh_signal(SIGHUP1, SIG_IGN(void (*)(int))1) != SIG_IGN(void (*)(int))1)
1275 ssh_signal(SIGHUP1, signal_handler);
1276 if (ssh_signal(SIGINT2, SIG_IGN(void (*)(int))1) != SIG_IGN(void (*)(int))1)
1277 ssh_signal(SIGINT2, signal_handler);
1278 if (ssh_signal(SIGQUIT3, SIG_IGN(void (*)(int))1) != SIG_IGN(void (*)(int))1)
1279 ssh_signal(SIGQUIT3, signal_handler);
1280 if (ssh_signal(SIGTERM15, SIG_IGN(void (*)(int))1) != SIG_IGN(void (*)(int))1)
1281 ssh_signal(SIGTERM15, signal_handler);
1282 ssh_signal(SIGWINCH28, window_change_handler);
1283
1284 if (have_pty)
1285 enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE3);
1286
1287 session_ident = ssh2_chan_id;
1288 if (session_ident != -1) {
1289 if (escape_char_arg != SSH_ESCAPECHAR_NONE-2) {
1290 channel_register_filter(ssh, session_ident,
1291 client_simple_escape_filter, NULL((void *)0),
1292 client_filter_cleanup,
1293 client_new_escape_filter_ctx(
1294 escape_char_arg));
1295 }
1296 channel_register_cleanup(ssh, session_ident,
1297 client_channel_closed, 0);
1298 }
1299
1300 schedule_server_alive_check();
1301
1302 /* Main loop of the client for the interactive session mode. */
1303 while (!quit_pending) {
1304
1305 /* Process buffered packets sent by the server. */
1306 client_process_buffered_input_packets(ssh);
1307
1308 if (session_closed && !channel_still_open(ssh))
1309 break;
1310
1311 if (ssh_packet_is_rekeying(ssh)) {
1312 debug("rekeying in progress")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1312
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "rekeying in progress"
)
;
1313 } else if (need_rekeying) {
1314 /* manual rekey request */
1315 debug("need rekeying")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1315
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "need rekeying")
;
1316 if ((r = kex_start_rekex(ssh)) != 0)
1317 fatal_fr(r, "kex_start_rekex")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 1317, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "kex_start_rekex")
;
1318 need_rekeying = 0;
1319 } else {
1320 /*
1321 * Make packets from buffered channel data, and
1322 * enqueue them for sending to the server.
1323 */
1324 if (ssh_packet_not_very_much_data_to_write(ssh))
1325 channel_output_poll(ssh);
1326
1327 /*
1328 * Check if the window size has changed, and buffer a
1329 * message about it to the server if so.
1330 */
1331 client_check_window_change(ssh);
1332
1333 if (quit_pending)
1334 break;
1335 }
1336 /*
1337 * Wait until we have something to do (something becomes
1338 * available on one of the descriptors).
1339 */
1340 client_wait_until_can_do_something(ssh, &pfd, &npfd_alloc,
1341 &npfd_active, ssh_packet_is_rekeying(ssh),
1342 &conn_in_ready, &conn_out_ready);
1343
1344 if (quit_pending)
1345 break;
1346
1347 /* Do channel operations unless rekeying in progress. */
1348 if (!ssh_packet_is_rekeying(ssh))
1349 channel_after_poll(ssh, pfd, npfd_active);
1350
1351 /* Buffer input from the connection. */
1352 if (conn_in_ready)
1353 client_process_net_input(ssh);
1354
1355 if (quit_pending)
1356 break;
1357
1358 /* A timeout may have triggered rekeying */
1359 if ((r = ssh_packet_check_rekey(ssh)) != 0)
1360 fatal_fr(r, "cannot start rekeying")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 1360, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "cannot start rekeying"
)
;
1361
1362 /*
1363 * Send as much buffered packet data as possible to the
1364 * sender.
1365 */
1366 if (conn_out_ready) {
1367 if ((r = ssh_packet_write_poll(ssh)) != 0) {
1368 sshpkt_fatal(ssh, r,
1369 "%s: ssh_packet_write_poll", __func__);
1370 }
1371 }
1372
1373 /*
1374 * If we are a backgrounded control master, and the
1375 * timeout has expired without any active client
1376 * connections, then quit.
1377 */
1378 if (control_persist_exit_time > 0) {
1379 if (monotime() >= control_persist_exit_time) {
1380 debug("ControlPersist timeout expired")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1380
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "ControlPersist timeout expired"
)
;
1381 break;
1382 }
1383 }
1384 }
1385 free(pfd);
1386
1387 /* Terminate the session. */
1388
1389 /* Stop watching for window change. */
1390 ssh_signal(SIGWINCH28, SIG_DFL(void (*)(int))0);
1391
1392 if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT1)) != 0 ||
1393 (r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_BY_APPLICATION11)) != 0 ||
1394 (r = sshpkt_put_cstring(ssh, "disconnected by user")) != 0 ||
1395 (r = sshpkt_put_cstring(ssh, "")) != 0 || /* language tag */
1396 (r = sshpkt_send(ssh)) != 0 ||
1397 (r = ssh_packet_write_wait(ssh)) != 0)
1398 fatal_fr(r, "send disconnect")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 1398, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "send disconnect")
;
1399
1400 channel_free_all(ssh);
1401
1402 if (have_pty)
1403 leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE3);
1404
1405 /*
1406 * If there was no shell or command requested, there will be no remote
1407 * exit status to be returned. In that case, clear error code if the
1408 * connection was deliberately terminated at this end.
1409 */
1410 if (options.session_type == SESSION_TYPE_NONE0 &&
1411 received_signal == SIGTERM15) {
1412 received_signal = 0;
1413 exit_status = 0;
1414 }
1415
1416 if (received_signal) {
1417 verbose("Killed by signal %d.", (int) received_signal)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1417
, 0, SYSLOG_LEVEL_VERBOSE, ((void *)0), "Killed by signal %d."
, (int) received_signal)
;
1418 cleanup_exit(255);
1419 }
1420
1421 /*
1422 * In interactive mode (with pseudo tty) display a message indicating
1423 * that the connection has been closed.
1424 */
1425 if (have_pty && options.log_level >= SYSLOG_LEVEL_INFO) {
1426 if ((r = sshbuf_putf(stderr_buffer,
1427 "Connection to %.64s closed.\r\n", host)) != 0)
1428 fatal_fr(r, "sshbuf_putf")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 1428, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "sshbuf_putf")
;
1429 }
1430
1431 /* Output any buffered data for stderr. */
1432 if (sshbuf_len(stderr_buffer) > 0) {
1433 len = atomicio(vwrite(ssize_t (*)(int, void *, size_t))write, fileno(stderr)(!__isthreaded ? (((&__sF[2]))->_file) : (fileno)((&
__sF[2])))
,
1434 (u_char *)sshbuf_ptr(stderr_buffer),
1435 sshbuf_len(stderr_buffer));
1436 if (len < 0 || (u_int)len != sshbuf_len(stderr_buffer))
1437 error("Write failed flushing stderr buffer.")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1437
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Write failed flushing stderr buffer."
)
;
1438 else if ((r = sshbuf_consume(stderr_buffer, len)) != 0)
1439 fatal_fr(r, "sshbuf_consume")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 1439, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "sshbuf_consume")
;
1440 }
1441
1442 /* Clear and free any buffers. */
1443 sshbuf_free(stderr_buffer);
1444
1445 /* Report bytes transferred, and transfer rates. */
1446 total_time = monotime_double() - start_time;
1447 ssh_packet_get_bytes(ssh, &ibytes, &obytes);
1448 verbose("Transferred: sent %llu, received %llu bytes, in %.1f seconds",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1449
, 0, SYSLOG_LEVEL_VERBOSE, ((void *)0), "Transferred: sent %llu, received %llu bytes, in %.1f seconds"
, (unsigned long long)obytes, (unsigned long long)ibytes, total_time
)
1449 (unsigned long long)obytes, (unsigned long long)ibytes, total_time)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1449
, 0, SYSLOG_LEVEL_VERBOSE, ((void *)0), "Transferred: sent %llu, received %llu bytes, in %.1f seconds"
, (unsigned long long)obytes, (unsigned long long)ibytes, total_time
)
;
1450 if (total_time > 0)
1451 verbose("Bytes per second: sent %.1f, received %.1f",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1452
, 0, SYSLOG_LEVEL_VERBOSE, ((void *)0), "Bytes per second: sent %.1f, received %.1f"
, obytes / total_time, ibytes / total_time)
1452 obytes / total_time, ibytes / total_time)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1452
, 0, SYSLOG_LEVEL_VERBOSE, ((void *)0), "Bytes per second: sent %.1f, received %.1f"
, obytes / total_time, ibytes / total_time)
;
1453 /* Return the exit status of the program. */
1454 debug("Exit status %d", exit_status)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1454
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "Exit status %d", exit_status
)
;
1455 return exit_status;
1456}
1457
1458/*********/
1459
1460static Channel *
1461client_request_forwarded_tcpip(struct ssh *ssh, const char *request_type,
1462 int rchan, u_int rwindow, u_int rmaxpack)
1463{
1464 Channel *c = NULL((void *)0);
1465 struct sshbuf *b = NULL((void *)0);
1466 char *listen_address, *originator_address;
1467 u_int listen_port, originator_port;
1468 int r;
1469
1470 /* Get rest of the packet */
1471 if ((r = sshpkt_get_cstring(ssh, &listen_address, NULL((void *)0))) != 0 ||
1472 (r = sshpkt_get_u32(ssh, &listen_port)) != 0 ||
1473 (r = sshpkt_get_cstring(ssh, &originator_address, NULL((void *)0))) != 0 ||
1474 (r = sshpkt_get_u32(ssh, &originator_port)) != 0 ||
1475 (r = sshpkt_get_end(ssh)) != 0)
1476 fatal_fr(r, "parse packet")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 1476, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "parse packet")
;
1477
1478 debug_f("listen %s port %d, originator %s port %d",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1479
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "listen %s port %d, originator %s port %d"
, listen_address, listen_port, originator_address, originator_port
)
1479 listen_address, listen_port, originator_address, originator_port)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1479
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "listen %s port %d, originator %s port %d"
, listen_address, listen_port, originator_address, originator_port
)
;
1480
1481 if (listen_port > 0xffff)
1482 error_f("invalid listen port")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1482
, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "invalid listen port")
;
1483 else if (originator_port > 0xffff)
1484 error_f("invalid originator port")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1484
, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "invalid originator port"
)
;
1485 else {
1486 c = channel_connect_by_listen_address(ssh,
1487 listen_address, listen_port, "forwarded-tcpip",
1488 originator_address);
1489 }
1490
1491 if (c != NULL((void *)0) && c->type == SSH_CHANNEL_MUX_CLIENT16) {
1492 if ((b = sshbuf_new()) == NULL((void *)0)) {
1493 error_f("alloc reply")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1493
, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "alloc reply")
;
1494 goto out;
1495 }
1496 /* reconstruct and send to muxclient */
1497 if ((r = sshbuf_put_u8(b, 0)) != 0 || /* padlen */
1498 (r = sshbuf_put_u8(b, SSH2_MSG_CHANNEL_OPEN90)) != 0 ||
1499 (r = sshbuf_put_cstring(b, request_type)) != 0 ||
1500 (r = sshbuf_put_u32(b, rchan)) != 0 ||
1501 (r = sshbuf_put_u32(b, rwindow)) != 0 ||
1502 (r = sshbuf_put_u32(b, rmaxpack)) != 0 ||
1503 (r = sshbuf_put_cstring(b, listen_address)) != 0 ||
1504 (r = sshbuf_put_u32(b, listen_port)) != 0 ||
1505 (r = sshbuf_put_cstring(b, originator_address)) != 0 ||
1506 (r = sshbuf_put_u32(b, originator_port)) != 0 ||
1507 (r = sshbuf_put_stringb(c->output, b)) != 0) {
1508 error_fr(r, "compose for muxclient")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1508
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "compose for muxclient")
;
1509 goto out;
1510 }
1511 }
1512
1513 out:
1514 sshbuf_free(b);
1515 free(originator_address);
1516 free(listen_address);
1517 return c;
1518}
1519
1520static Channel *
1521client_request_forwarded_streamlocal(struct ssh *ssh,
1522 const char *request_type, int rchan)
1523{
1524 Channel *c = NULL((void *)0);
1525 char *listen_path;
1526 int r;
1527
1528 /* Get the remote path. */
1529 if ((r = sshpkt_get_cstring(ssh, &listen_path, NULL((void *)0))) != 0 ||
1530 (r = sshpkt_get_string(ssh, NULL((void *)0), NULL((void *)0))) != 0 || /* reserved */
1531 (r = sshpkt_get_end(ssh)) != 0)
1532 fatal_fr(r, "parse packet")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 1532, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "parse packet")
;
1533
1534 debug_f("request: %s", listen_path)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1534
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "request: %s", listen_path
)
;
1535
1536 c = channel_connect_by_listen_path(ssh, listen_path,
1537 "forwarded-streamlocal@openssh.com", "forwarded-streamlocal");
1538 free(listen_path);
1539 return c;
1540}
1541
1542static Channel *
1543client_request_x11(struct ssh *ssh, const char *request_type, int rchan)
1544{
1545 Channel *c = NULL((void *)0);
1546 char *originator;
1547 u_int originator_port;
1548 int r, sock;
1549
1550 if (!options.forward_x11) {
1551 error("Warning: ssh server tried X11 forwarding.")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1551
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Warning: ssh server tried X11 forwarding."
)
;
1552 error("Warning: this is probably a break-in attempt by a "sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1553
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Warning: this is probably a break-in attempt by a "
"malicious server.")
1553 "malicious server.")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1553
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Warning: this is probably a break-in attempt by a "
"malicious server.")
;
1554 return NULL((void *)0);
1555 }
1556 if (x11_refuse_time != 0 && (u_int)monotime() >= x11_refuse_time) {
1557 verbose("Rejected X11 connection after ForwardX11Timeout "sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1558
, 0, SYSLOG_LEVEL_VERBOSE, ((void *)0), "Rejected X11 connection after ForwardX11Timeout "
"expired")
1558 "expired")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1558
, 0, SYSLOG_LEVEL_VERBOSE, ((void *)0), "Rejected X11 connection after ForwardX11Timeout "
"expired")
;
1559 return NULL((void *)0);
1560 }
1561 if ((r = sshpkt_get_cstring(ssh, &originator, NULL((void *)0))) != 0 ||
1562 (r = sshpkt_get_u32(ssh, &originator_port)) != 0 ||
1563 (r = sshpkt_get_end(ssh)) != 0)
1564 fatal_fr(r, "parse packet")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 1564, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "parse packet")
;
1565 /* XXX check permission */
1566 /* XXX range check originator port? */
1567 debug("client_request_x11: request from %s %u", originator,sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1568
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "client_request_x11: request from %s %u"
, originator, originator_port)
1568 originator_port)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1568
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "client_request_x11: request from %s %u"
, originator, originator_port)
;
1569 free(originator);
1570 sock = x11_connect_display(ssh);
1571 if (sock < 0)
1572 return NULL((void *)0);
1573 c = channel_new(ssh, "x11",
1574 SSH_CHANNEL_X11_OPEN7, sock, sock, -1,
1575 CHAN_TCP_WINDOW_DEFAULT(64*(32*1024)), CHAN_X11_PACKET_DEFAULT(16*1024), 0, "x11", 1);
1576 c->force_drain = 1;
1577 return c;
1578}
1579
1580static Channel *
1581client_request_agent(struct ssh *ssh, const char *request_type, int rchan)
1582{
1583 Channel *c = NULL((void *)0);
1584 int r, sock;
1585
1586 if (!options.forward_agent) {
1587 error("Warning: ssh server tried agent forwarding.")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1587
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Warning: ssh server tried agent forwarding."
)
;
1588 error("Warning: this is probably a break-in attempt by a "sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1589
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Warning: this is probably a break-in attempt by a "
"malicious server.")
1589 "malicious server.")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1589
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Warning: this is probably a break-in attempt by a "
"malicious server.")
;
1590 return NULL((void *)0);
1591 }
1592 if (forward_agent_sock_path == NULL((void *)0)) {
1593 r = ssh_get_authentication_socket(&sock);
1594 } else {
1595 r = ssh_get_authentication_socket_path(forward_agent_sock_path, &sock);
1596 }
1597 if (r != 0) {
1598 if (r != SSH_ERR_AGENT_NOT_PRESENT-47)
1599 debug_fr(r, "ssh_get_authentication_socket")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1599
, 1, SYSLOG_LEVEL_DEBUG1, ssh_err(r), "ssh_get_authentication_socket"
)
;
1600 return NULL((void *)0);
1601 }
1602 if ((r = ssh_agent_bind_hostkey(sock, ssh->kex->initial_hostkey,
1603 ssh->kex->session_id, ssh->kex->initial_sig, 1)) == 0)
1604 debug_f("bound agent to hostkey")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1604
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "bound agent to hostkey"
)
;
1605 else
1606 debug2_fr(r, "ssh_agent_bind_hostkey")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1606
, 1, SYSLOG_LEVEL_DEBUG2, ssh_err(r), "ssh_agent_bind_hostkey"
)
;
1607
1608 c = channel_new(ssh, "authentication agent connection",
1609 SSH_CHANNEL_OPEN4, sock, sock, -1,
1610 CHAN_X11_WINDOW_DEFAULT(4*(16*1024)), CHAN_TCP_PACKET_DEFAULT(32*1024), 0,
1611 "authentication agent connection", 1);
1612 c->force_drain = 1;
1613 return c;
1614}
1615
1616char *
1617client_request_tun_fwd(struct ssh *ssh, int tun_mode,
1618 int local_tun, int remote_tun, channel_open_fn *cb, void *cbctx)
1619{
1620 Channel *c;
1621 int r, fd;
1622 char *ifname = NULL((void *)0);
1623
1624 if (tun_mode == SSH_TUNMODE_NO0x00)
1625 return 0;
1626
1627 debug("Requesting tun unit %d in mode %d", local_tun, tun_mode)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1627
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "Requesting tun unit %d in mode %d"
, local_tun, tun_mode)
;
1628
1629 /* Open local tunnel device */
1630 if ((fd = tun_open(local_tun, tun_mode, &ifname)) == -1) {
1631 error("Tunnel device open failed.")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1631
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Tunnel device open failed."
)
;
1632 return NULL((void *)0);
1633 }
1634 debug("Tunnel forwarding using interface %s", ifname)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1634
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "Tunnel forwarding using interface %s"
, ifname)
;
1635
1636 c = channel_new(ssh, "tun", SSH_CHANNEL_OPENING3, fd, fd, -1,
1637 CHAN_TCP_WINDOW_DEFAULT(64*(32*1024)), CHAN_TCP_PACKET_DEFAULT(32*1024), 0, "tun", 1);
1638 c->datagram = 1;
1639
1640 if (cb != NULL((void *)0))
1641 channel_register_open_confirm(ssh, c->self, cb, cbctx);
1642
1643 if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN90)) != 0 ||
1644 (r = sshpkt_put_cstring(ssh, "tun@openssh.com")) != 0 ||
1645 (r = sshpkt_put_u32(ssh, c->self)) != 0 ||
1646 (r = sshpkt_put_u32(ssh, c->local_window_max)) != 0 ||
1647 (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0 ||
1648 (r = sshpkt_put_u32(ssh, tun_mode)) != 0 ||
1649 (r = sshpkt_put_u32(ssh, remote_tun)) != 0 ||
1650 (r = sshpkt_send(ssh)) != 0)
1651 sshpkt_fatal(ssh, r, "%s: send reply", __func__);
1652
1653 return ifname;
1654}
1655
1656/* XXXX move to generic input handler */
1657static int
1658client_input_channel_open(int type, u_int32_t seq, struct ssh *ssh)
1659{
1660 Channel *c = NULL((void *)0);
1661 char *ctype = NULL((void *)0);
1662 int r;
1663 u_int rchan;
1664 size_t len;
1665 u_int rmaxpack, rwindow;
1666
1667 if ((r = sshpkt_get_cstring(ssh, &ctype, &len)) != 0 ||
1668 (r = sshpkt_get_u32(ssh, &rchan)) != 0 ||
1669 (r = sshpkt_get_u32(ssh, &rwindow)) != 0 ||
1670 (r = sshpkt_get_u32(ssh, &rmaxpack)) != 0)
1671 goto out;
1672
1673 debug("client_input_channel_open: ctype %s rchan %d win %d max %d",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1674
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "client_input_channel_open: ctype %s rchan %d win %d max %d"
, ctype, rchan, rwindow, rmaxpack)
1674 ctype, rchan, rwindow, rmaxpack)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1674
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "client_input_channel_open: ctype %s rchan %d win %d max %d"
, ctype, rchan, rwindow, rmaxpack)
;
1675
1676 if (strcmp(ctype, "forwarded-tcpip") == 0) {
1677 c = client_request_forwarded_tcpip(ssh, ctype, rchan, rwindow,
1678 rmaxpack);
1679 } else if (strcmp(ctype, "forwarded-streamlocal@openssh.com") == 0) {
1680 c = client_request_forwarded_streamlocal(ssh, ctype, rchan);
1681 } else if (strcmp(ctype, "x11") == 0) {
1682 c = client_request_x11(ssh, ctype, rchan);
1683 } else if (strcmp(ctype, "auth-agent@openssh.com") == 0) {
1684 c = client_request_agent(ssh, ctype, rchan);
1685 }
1686 if (c != NULL((void *)0) && c->type == SSH_CHANNEL_MUX_CLIENT16) {
1687 debug3("proxied to downstream: %s", ctype)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1687
, 0, SYSLOG_LEVEL_DEBUG3, ((void *)0), "proxied to downstream: %s"
, ctype)
;
1688 } else if (c != NULL((void *)0)) {
1689 debug("confirm %s", ctype)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1689
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "confirm %s", ctype)
;
1690 c->remote_id = rchan;
1691 c->have_remote_id = 1;
1692 c->remote_window = rwindow;
1693 c->remote_maxpacket = rmaxpack;
1694 if (c->type != SSH_CHANNEL_CONNECTING12) {
1695 if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION91)) != 0 ||
1696 (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
1697 (r = sshpkt_put_u32(ssh, c->self)) != 0 ||
1698 (r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||
1699 (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0 ||
1700 (r = sshpkt_send(ssh)) != 0)
1701 sshpkt_fatal(ssh, r, "%s: send reply", __func__);
1702 }
1703 } else {
1704 debug("failure %s", ctype)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1704
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "failure %s", ctype)
;
1705 if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_FAILURE92)) != 0 ||
1706 (r = sshpkt_put_u32(ssh, rchan)) != 0 ||
1707 (r = sshpkt_put_u32(ssh, SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED1)) != 0 ||
1708 (r = sshpkt_put_cstring(ssh, "open failed")) != 0 ||
1709 (r = sshpkt_put_cstring(ssh, "")) != 0 ||
1710 (r = sshpkt_send(ssh)) != 0)
1711 sshpkt_fatal(ssh, r, "%s: send failure", __func__);
1712 }
1713 r = 0;
1714 out:
1715 free(ctype);
1716 return r;
1717}
1718
1719static int
1720client_input_channel_req(int type, u_int32_t seq, struct ssh *ssh)
1721{
1722 Channel *c = NULL((void *)0);
1723 char *rtype = NULL((void *)0);
1724 u_char reply;
1725 u_int id, exitval;
1726 int r, success = 0;
1727
1728 if ((r = sshpkt_get_u32(ssh, &id)) != 0)
1729 return r;
1730 if (id <= INT_MAX2147483647)
1731 c = channel_lookup(ssh, id);
1732 if (channel_proxy_upstream(c, type, seq, ssh))
1733 return 0;
1734 if ((r = sshpkt_get_cstring(ssh, &rtype, NULL((void *)0))) != 0 ||
1735 (r = sshpkt_get_u8(ssh, &reply)) != 0)
1736 goto out;
1737
1738 debug("client_input_channel_req: channel %u rtype %s reply %d",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1739
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "client_input_channel_req: channel %u rtype %s reply %d"
, id, rtype, reply)
1739 id, rtype, reply)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1739
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "client_input_channel_req: channel %u rtype %s reply %d"
, id, rtype, reply)
;
1740
1741 if (c == NULL((void *)0)) {
1742 error("client_input_channel_req: channel %d: "sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1743
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "client_input_channel_req: channel %d: "
"unknown channel", id)
1743 "unknown channel", id)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1743
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "client_input_channel_req: channel %d: "
"unknown channel", id)
;
1744 } else if (strcmp(rtype, "eow@openssh.com") == 0) {
1745 if ((r = sshpkt_get_end(ssh)) != 0)
1746 goto out;
1747 chan_rcvd_eow(ssh, c);
1748 } else if (strcmp(rtype, "exit-status") == 0) {
1749 if ((r = sshpkt_get_u32(ssh, &exitval)) != 0)
1750 goto out;
1751 if (c->ctl_chan != -1) {
1752 mux_exit_message(ssh, c, exitval);
1753 success = 1;
1754 } else if ((int)id == session_ident) {
1755 /* Record exit value of local session */
1756 success = 1;
1757 exit_status = exitval;
1758 } else {
1759 /* Probably for a mux channel that has already closed */
1760 debug_f("no sink for exit-status on channel %d",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1761
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "no sink for exit-status on channel %d"
, id)
1761 id)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1761
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "no sink for exit-status on channel %d"
, id)
;
1762 }
1763 if ((r = sshpkt_get_end(ssh)) != 0)
1764 goto out;
1765 }
1766 if (reply && c != NULL((void *)0) && !(c->flags & CHAN_CLOSE_SENT0x01)) {
1767 if (!c->have_remote_id)
1768 fatal_f("channel %d: no remote_id", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 1768, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "channel %d: no remote_id"
, c->self)
;
1769 if ((r = sshpkt_start(ssh, success ?
1770 SSH2_MSG_CHANNEL_SUCCESS99 : SSH2_MSG_CHANNEL_FAILURE100)) != 0 ||
1771 (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
1772 (r = sshpkt_send(ssh)) != 0)
1773 sshpkt_fatal(ssh, r, "%s: send failure", __func__);
1774 }
1775 r = 0;
1776 out:
1777 free(rtype);
1778 return r;
1779}
1780
1781struct hostkeys_update_ctx {
1782 /* The hostname and (optionally) IP address string for the server */
1783 char *host_str, *ip_str;
1784
1785 /*
1786 * Keys received from the server and a flag for each indicating
1787 * whether they already exist in known_hosts.
1788 * keys_match is filled in by hostkeys_find() and later (for new
1789 * keys) by client_global_hostkeys_private_confirm().
1790 */
1791 struct sshkey **keys;
1792 u_int *keys_match; /* mask of HKF_MATCH_* from hostfile.h */
1793 int *keys_verified; /* flag for new keys verified by server */
1794 size_t nkeys, nnew, nincomplete; /* total, new keys, incomplete match */
1795
1796 /*
1797 * Keys that are in known_hosts, but were not present in the update
1798 * from the server (i.e. scheduled to be deleted).
1799 * Filled in by hostkeys_find().
1800 */
1801 struct sshkey **old_keys;
1802 size_t nold;
1803
1804 /* Various special cases. */
1805 int complex_hostspec; /* wildcard or manual pattern-list host name */
1806 int ca_available; /* saw CA key for this host */
1807 int old_key_seen; /* saw old key with other name/addr */
1808 int other_name_seen; /* saw key with other name/addr */
1809};
1810
1811static void
1812hostkeys_update_ctx_free(struct hostkeys_update_ctx *ctx)
1813{
1814 size_t i;
1815
1816 if (ctx == NULL((void *)0))
1817 return;
1818 for (i = 0; i < ctx->nkeys; i++)
1819 sshkey_free(ctx->keys[i]);
1820 free(ctx->keys);
1821 free(ctx->keys_match);
1822 free(ctx->keys_verified);
1823 for (i = 0; i < ctx->nold; i++)
1824 sshkey_free(ctx->old_keys[i]);
1825 free(ctx->old_keys);
1826 free(ctx->host_str);
1827 free(ctx->ip_str);
1828 free(ctx);
1829}
1830
1831/*
1832 * Returns non-zero if a known_hosts hostname list is not of a form that
1833 * can be handled by UpdateHostkeys. These include wildcard hostnames and
1834 * hostnames lists that do not follow the form host[,ip].
1835 */
1836static int
1837hostspec_is_complex(const char *hosts)
1838{
1839 char *cp;
1840
1841 /* wildcard */
1842 if (strchr(hosts, '*') != NULL((void *)0) || strchr(hosts, '?') != NULL((void *)0))
1843 return 1;
1844 /* single host/ip = ok */
1845 if ((cp = strchr(hosts, ',')) == NULL((void *)0))
1846 return 0;
1847 /* more than two entries on the line */
1848 if (strchr(cp + 1, ',') != NULL((void *)0))
1849 return 1;
1850 /* XXX maybe parse cp+1 and ensure it is an IP? */
1851 return 0;
1852}
1853
1854/* callback to search for ctx->keys in known_hosts */
1855static int
1856hostkeys_find(struct hostkey_foreach_line *l, void *_ctx)
1857{
1858 struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx;
1859 size_t i;
1860 struct sshkey **tmp;
1861
1862 if (l->key == NULL((void *)0))
1863 return 0;
1864 if (l->status != HKF_STATUS_MATCHED3) {
1865 /* Record if one of the keys appears on a non-matching line */
1866 for (i = 0; i < ctx->nkeys; i++) {
1867 if (sshkey_equal(l->key, ctx->keys[i])) {
1868 ctx->other_name_seen = 1;
1869 debug3_f("found %s key under different "sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1872
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "found %s key under different "
"name/addr at %s:%ld", sshkey_ssh_name(ctx->keys[i]), l->
path, l->linenum)
1870 "name/addr at %s:%ld",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1872
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "found %s key under different "
"name/addr at %s:%ld", sshkey_ssh_name(ctx->keys[i]), l->
path, l->linenum)
1871 sshkey_ssh_name(ctx->keys[i]),sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1872
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "found %s key under different "
"name/addr at %s:%ld", sshkey_ssh_name(ctx->keys[i]), l->
path, l->linenum)
1872 l->path, l->linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1872
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "found %s key under different "
"name/addr at %s:%ld", sshkey_ssh_name(ctx->keys[i]), l->
path, l->linenum)
;
1873 return 0;
1874 }
1875 }
1876 return 0;
1877 }
1878 /* Don't proceed if revocation or CA markers are present */
1879 /* XXX relax this */
1880 if (l->marker != MRK_NONE) {
1881 debug3_f("hostkeys file %s:%ld has CA/revocation marker",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1882
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "hostkeys file %s:%ld has CA/revocation marker"
, l->path, l->linenum)
1882 l->path, l->linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1882
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "hostkeys file %s:%ld has CA/revocation marker"
, l->path, l->linenum)
;
1883 ctx->complex_hostspec = 1;
1884 return 0;
1885 }
1886
1887 /* If CheckHostIP is enabled, then check for mismatched hostname/addr */
1888 if (ctx->ip_str != NULL((void *)0) && strchr(l->hosts, ',') != NULL((void *)0)) {
1889 if ((l->match & HKF_MATCH_HOST(1)) == 0) {
1890 /* Record if address matched a different hostname. */
1891 ctx->other_name_seen = 1;
1892 debug3_f("found address %s against different hostname "sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1893
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "found address %s against different hostname "
"at %s:%ld", ctx->ip_str, l->path, l->linenum)
1893 "at %s:%ld", ctx->ip_str, l->path, l->linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1893
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "found address %s against different hostname "
"at %s:%ld", ctx->ip_str, l->path, l->linenum)
;
1894 return 0;
1895 } else if ((l->match & HKF_MATCH_IP(1<<1)) == 0) {
1896 /* Record if hostname matched a different address. */
1897 ctx->other_name_seen = 1;
1898 debug3_f("found hostname %s against different address "sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1899
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "found hostname %s against different address "
"at %s:%ld", ctx->host_str, l->path, l->linenum)
1899 "at %s:%ld", ctx->host_str, l->path, l->linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1899
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "found hostname %s against different address "
"at %s:%ld", ctx->host_str, l->path, l->linenum)
;
1900 }
1901 }
1902
1903 /*
1904 * UpdateHostkeys is skipped for wildcard host names and hostnames
1905 * that contain more than two entries (ssh never writes these).
1906 */
1907 if (hostspec_is_complex(l->hosts)) {
1908 debug3_f("hostkeys file %s:%ld complex host specification",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1909
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "hostkeys file %s:%ld complex host specification"
, l->path, l->linenum)
1909 l->path, l->linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1909
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "hostkeys file %s:%ld complex host specification"
, l->path, l->linenum)
;
1910 ctx->complex_hostspec = 1;
1911 return 0;
1912 }
1913
1914 /* Mark off keys we've already seen for this host */
1915 for (i = 0; i < ctx->nkeys; i++) {
1916 if (!sshkey_equal(l->key, ctx->keys[i]))
1917 continue;
1918 debug3_f("found %s key at %s:%ld",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1919
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "found %s key at %s:%ld"
, sshkey_ssh_name(ctx->keys[i]), l->path, l->linenum
)
1919 sshkey_ssh_name(ctx->keys[i]), l->path, l->linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1919
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "found %s key at %s:%ld"
, sshkey_ssh_name(ctx->keys[i]), l->path, l->linenum
)
;
1920 ctx->keys_match[i] |= l->match;
1921 return 0;
1922 }
1923 /* This line contained a key that not offered by the server */
1924 debug3_f("deprecated %s key at %s:%ld", sshkey_ssh_name(l->key),sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1925
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "deprecated %s key at %s:%ld"
, sshkey_ssh_name(l->key), l->path, l->linenum)
1925 l->path, l->linenum)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1925
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "deprecated %s key at %s:%ld"
, sshkey_ssh_name(l->key), l->path, l->linenum)
;
1926 if ((tmp = recallocarray(ctx->old_keys, ctx->nold, ctx->nold + 1,
1927 sizeof(*ctx->old_keys))) == NULL((void *)0))
1928 fatal_f("recallocarray failed nold = %zu", ctx->nold)sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 1928, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "recallocarray failed nold = %zu"
, ctx->nold)
;
1929 ctx->old_keys = tmp;
1930 ctx->old_keys[ctx->nold++] = l->key;
1931 l->key = NULL((void *)0);
1932
1933 return 0;
1934}
1935
1936/* callback to search for ctx->old_keys in known_hosts under other names */
1937static int
1938hostkeys_check_old(struct hostkey_foreach_line *l, void *_ctx)
1939{
1940 struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx;
1941 size_t i;
1942 int hashed;
1943
1944 /* only care about lines that *don't* match the active host spec */
1945 if (l->status == HKF_STATUS_MATCHED3 || l->key == NULL((void *)0))
1946 return 0;
1947
1948 hashed = l->match & (HKF_MATCH_HOST_HASHED(1<<2)|HKF_MATCH_IP_HASHED(1<<3));
1949 for (i = 0; i < ctx->nold; i++) {
1950 if (!sshkey_equal(l->key, ctx->old_keys[i]))
1951 continue;
1952 debug3_f("found deprecated %s key at %s:%ld as %s",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1954
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "found deprecated %s key at %s:%ld as %s"
, sshkey_ssh_name(ctx->old_keys[i]), l->path, l->linenum
, hashed ? "[HASHED]" : l->hosts)
1953 sshkey_ssh_name(ctx->old_keys[i]), l->path, l->linenum,sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1954
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "found deprecated %s key at %s:%ld as %s"
, sshkey_ssh_name(ctx->old_keys[i]), l->path, l->linenum
, hashed ? "[HASHED]" : l->hosts)
1954 hashed ? "[HASHED]" : l->hosts)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1954
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "found deprecated %s key at %s:%ld as %s"
, sshkey_ssh_name(ctx->old_keys[i]), l->path, l->linenum
, hashed ? "[HASHED]" : l->hosts)
;
1955 ctx->old_key_seen = 1;
1956 break;
1957 }
1958 return 0;
1959}
1960
1961/*
1962 * Check known_hosts files for deprecated keys under other names. Returns 0
1963 * on success or -1 on failure. Updates ctx->old_key_seen if deprecated keys
1964 * exist under names other than the active hostname/IP.
1965 */
1966static int
1967check_old_keys_othernames(struct hostkeys_update_ctx *ctx)
1968{
1969 size_t i;
1970 int r;
1971
1972 debug2_f("checking for %zu deprecated keys", ctx->nold)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1972
, 1, SYSLOG_LEVEL_DEBUG2, ((void *)0), "checking for %zu deprecated keys"
, ctx->nold)
;
1973 for (i = 0; i < options.num_user_hostfiles; i++) {
1974 debug3_f("searching %s for %s / %s",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1976
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "searching %s for %s / %s"
, options.user_hostfiles[i], ctx->host_str, ctx->ip_str
? ctx->ip_str : "(none)")
1975 options.user_hostfiles[i], ctx->host_str,sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1976
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "searching %s for %s / %s"
, options.user_hostfiles[i], ctx->host_str, ctx->ip_str
? ctx->ip_str : "(none)")
1976 ctx->ip_str ? ctx->ip_str : "(none)")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1976
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "searching %s for %s / %s"
, options.user_hostfiles[i], ctx->host_str, ctx->ip_str
? ctx->ip_str : "(none)")
;
1977 if ((r = hostkeys_foreach(options.user_hostfiles[i],
1978 hostkeys_check_old, ctx, ctx->host_str, ctx->ip_str,
1979 HKF_WANT_PARSE_KEY(1<<1), 0)) != 0) {
1980 if (r == SSH_ERR_SYSTEM_ERROR-24 && errno(*__errno()) == ENOENT2) {
1981 debug_f("hostkeys file %s does not exist",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1982
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "hostkeys file %s does not exist"
, options.user_hostfiles[i])
1982 options.user_hostfiles[i])sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1982
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "hostkeys file %s does not exist"
, options.user_hostfiles[i])
;
1983 continue;
1984 }
1985 error_fr(r, "hostkeys_foreach failed for %s",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1986
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "hostkeys_foreach failed for %s"
, options.user_hostfiles[i])
1986 options.user_hostfiles[i])sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1986
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "hostkeys_foreach failed for %s"
, options.user_hostfiles[i])
;
1987 return -1;
1988 }
1989 }
1990 return 0;
1991}
1992
1993static void
1994hostkey_change_preamble(LogLevel loglevel)
1995{
1996 do_log2(loglevel, "The server has updated its host keys.")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1996
, 0, loglevel, ((void *)0), "The server has updated its host keys."
)
;
1997 do_log2(loglevel, "These changes were verified by the server's "sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1998
, 0, loglevel, ((void *)0), "These changes were verified by the server's "
"existing trusted key.")
1998 "existing trusted key.")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 1998
, 0, loglevel, ((void *)0), "These changes were verified by the server's "
"existing trusted key.")
;
1999}
2000
2001static void
2002update_known_hosts(struct hostkeys_update_ctx *ctx)
2003{
2004 int r, was_raw = 0, first = 1;
2005 int asking = options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK2;
2006 LogLevel loglevel = asking ? SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_VERBOSE;
2007 char *fp, *response;
2008 size_t i;
2009 struct stat sb;
2010
2011 for (i = 0; i < ctx->nkeys; i++) {
2012 if (!ctx->keys_verified[i])
2013 continue;
2014 if ((fp = sshkey_fingerprint(ctx->keys[i],
2015 options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL((void *)0))
2016 fatal_f("sshkey_fingerprint failed")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 2016, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "sshkey_fingerprint failed"
)
;
2017 if (first && asking)
2018 hostkey_change_preamble(loglevel);
2019 do_log2(loglevel, "Learned new hostkey: %s %s",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2020
, 0, loglevel, ((void *)0), "Learned new hostkey: %s %s", sshkey_type
(ctx->keys[i]), fp)
2020 sshkey_type(ctx->keys[i]), fp)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2020
, 0, loglevel, ((void *)0), "Learned new hostkey: %s %s", sshkey_type
(ctx->keys[i]), fp)
;
2021 first = 0;
2022 free(fp);
2023 }
2024 for (i = 0; i < ctx->nold; i++) {
2025 if ((fp = sshkey_fingerprint(ctx->old_keys[i],
2026 options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL((void *)0))
2027 fatal_f("sshkey_fingerprint failed")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 2027, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "sshkey_fingerprint failed"
)
;
2028 if (first && asking)
2029 hostkey_change_preamble(loglevel);
2030 do_log2(loglevel, "Deprecating obsolete hostkey: %s %s",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2031
, 0, loglevel, ((void *)0), "Deprecating obsolete hostkey: %s %s"
, sshkey_type(ctx->old_keys[i]), fp)
2031 sshkey_type(ctx->old_keys[i]), fp)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2031
, 0, loglevel, ((void *)0), "Deprecating obsolete hostkey: %s %s"
, sshkey_type(ctx->old_keys[i]), fp)
;
2032 first = 0;
2033 free(fp);
2034 }
2035 if (options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK2) {
2036 if (get_saved_tio() != NULL((void *)0)) {
2037 leave_raw_mode(1);
2038 was_raw = 1;
2039 }
2040 response = NULL((void *)0);
2041 for (i = 0; !quit_pending && i < 3; i++) {
2042 free(response);
2043 response = read_passphrase("Accept updated hostkeys? "
2044 "(yes/no): ", RP_ECHO0x0001);
2045 if (strcasecmp(response, "yes") == 0)
2046 break;
2047 else if (quit_pending || response == NULL((void *)0) ||
2048 strcasecmp(response, "no") == 0) {
2049 options.update_hostkeys = 0;
2050 break;
2051 } else {
2052 do_log2(loglevel, "Please enter "sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2053
, 0, loglevel, ((void *)0), "Please enter " "\"yes\" or \"no\""
)
2053 "\"yes\" or \"no\"")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2053
, 0, loglevel, ((void *)0), "Please enter " "\"yes\" or \"no\""
)
;
2054 }
2055 }
2056 if (quit_pending || i >= 3 || response == NULL((void *)0))
2057 options.update_hostkeys = 0;
2058 free(response);
2059 if (was_raw)
2060 enter_raw_mode(1);
2061 }
2062 if (options.update_hostkeys == 0)
2063 return;
2064 /*
2065 * Now that all the keys are verified, we can go ahead and replace
2066 * them in known_hosts (assuming SSH_UPDATE_HOSTKEYS_ASK didn't
2067 * cancel the operation).
2068 */
2069 for (i = 0; i < options.num_user_hostfiles; i++) {
2070 /*
2071 * NB. keys are only added to hostfiles[0], for the rest we
2072 * just delete the hostname entries.
2073 */
2074 if (stat(options.user_hostfiles[i], &sb) != 0) {
2075 if (errno(*__errno()) == ENOENT2) {
2076 debug_f("known hosts file %s does not "sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2077
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "known hosts file %s does not "
"exist", options.user_hostfiles[i])
2077 "exist", options.user_hostfiles[i])sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2077
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "known hosts file %s does not "
"exist", options.user_hostfiles[i])
;
2078 } else {
2079 error_f("known hosts file %s "sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2081
, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "known hosts file %s " "inaccessible: %s"
, options.user_hostfiles[i], strerror((*__errno())))
2080 "inaccessible: %s",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2081
, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "known hosts file %s " "inaccessible: %s"
, options.user_hostfiles[i], strerror((*__errno())))
2081 options.user_hostfiles[i], strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2081
, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "known hosts file %s " "inaccessible: %s"
, options.user_hostfiles[i], strerror((*__errno())))
;
2082 }
2083 continue;
2084 }
2085 if ((r = hostfile_replace_entries(options.user_hostfiles[i],
2086 ctx->host_str, ctx->ip_str,
2087 i == 0 ? ctx->keys : NULL((void *)0), i == 0 ? ctx->nkeys : 0,
2088 options.hash_known_hosts, 0,
2089 options.fingerprint_hash)) != 0) {
2090 error_fr(r, "hostfile_replace_entries failed for %s",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2091
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "hostfile_replace_entries failed for %s"
, options.user_hostfiles[i])
2091 options.user_hostfiles[i])sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2091
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "hostfile_replace_entries failed for %s"
, options.user_hostfiles[i])
;
2092 }
2093 }
2094}
2095
2096static void
2097client_global_hostkeys_private_confirm(struct ssh *ssh, int type,
2098 u_int32_t seq, void *_ctx)
2099{
2100 struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx;
2101 size_t i, ndone;
2102 struct sshbuf *signdata;
2103 int r, plaintype;
2104 const u_char *sig;
2105 const char *rsa_kexalg = NULL((void *)0);
2106 char *alg = NULL((void *)0);
2107 size_t siglen;
2108
2109 if (ctx->nnew == 0)
2110 fatal_f("ctx->nnew == 0")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 2110, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "ctx->nnew == 0"
)
; /* sanity */
2111 if (type != SSH2_MSG_REQUEST_SUCCESS81) {
2112 error("Server failed to confirm ownership of "sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2113
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Server failed to confirm ownership of "
"private host keys")
2113 "private host keys")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2113
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Server failed to confirm ownership of "
"private host keys")
;
2114 hostkeys_update_ctx_free(ctx);
2115 return;
2116 }
2117 if (sshkey_type_plain(sshkey_type_from_name(
2118 ssh->kex->hostkey_alg)) == KEY_RSA)
2119 rsa_kexalg = ssh->kex->hostkey_alg;
2120 if ((signdata = sshbuf_new()) == NULL((void *)0))
2121 fatal_f("sshbuf_new failed")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 2121, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "sshbuf_new failed"
)
;
2122 /*
2123 * Expect a signature for each of the ctx->nnew private keys we
2124 * haven't seen before. They will be in the same order as the
2125 * ctx->keys where the corresponding ctx->keys_match[i] == 0.
2126 */
2127 for (ndone = i = 0; i < ctx->nkeys; i++) {
2128 if (ctx->keys_match[i])
2129 continue;
2130 plaintype = sshkey_type_plain(ctx->keys[i]->type);
2131 /* Prepare data to be signed: session ID, unique string, key */
2132 sshbuf_reset(signdata);
2133 if ( (r = sshbuf_put_cstring(signdata,
2134 "hostkeys-prove-00@openssh.com")) != 0 ||
2135 (r = sshbuf_put_stringb(signdata,
2136 ssh->kex->session_id)) != 0 ||
2137 (r = sshkey_puts(ctx->keys[i], signdata)) != 0)
2138 fatal_fr(r, "compose signdata")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 2138, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "compose signdata"
)
;
2139 /* Extract and verify signature */
2140 if ((r = sshpkt_get_string_direct(ssh, &sig, &siglen)) != 0) {
2141 error_fr(r, "parse sig")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2141
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse sig")
;
2142 goto out;
2143 }
2144 if ((r = sshkey_get_sigtype(sig, siglen, &alg)) != 0) {
2145 error_fr(r, "server gave unintelligible signature "sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2146
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "server gave unintelligible signature "
"for %s key %zu", sshkey_type(ctx->keys[i]), i)
2146 "for %s key %zu", sshkey_type(ctx->keys[i]), i)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2146
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "server gave unintelligible signature "
"for %s key %zu", sshkey_type(ctx->keys[i]), i)
;
2147 goto out;
2148 }
2149 /*
2150 * Special case for RSA keys: if a RSA hostkey was negotiated,
2151 * then use its signature type for verification of RSA hostkey
2152 * proofs. Otherwise, accept only RSA-SHA256/512 signatures.
2153 */
2154 if (plaintype == KEY_RSA && rsa_kexalg == NULL((void *)0) &&
2155 match_pattern_list(alg, HOSTKEY_PROOF_RSA_ALGS"rsa-sha2-512,rsa-sha2-256", 0) != 1) {
2156 debug_f("server used untrusted RSA signature algorithm "sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2157
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "server used untrusted RSA signature algorithm "
"%s for key %zu, disregarding", alg, i)
2157 "%s for key %zu, disregarding", alg, i)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2157
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "server used untrusted RSA signature algorithm "
"%s for key %zu, disregarding", alg, i)
;
2158 free(alg);
2159 /* zap the key from the list */
2160 sshkey_free(ctx->keys[i]);
2161 ctx->keys[i] = NULL((void *)0);
2162 ndone++;
2163 continue;
2164 }
2165 debug3_f("verify %s key %zu using sigalg %s",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2166
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "verify %s key %zu using sigalg %s"
, sshkey_type(ctx->keys[i]), i, alg)
2166 sshkey_type(ctx->keys[i]), i, alg)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2166
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "verify %s key %zu using sigalg %s"
, sshkey_type(ctx->keys[i]), i, alg)
;
2167 free(alg);
2168 if ((r = sshkey_verify(ctx->keys[i], sig, siglen,
2169 sshbuf_ptr(signdata), sshbuf_len(signdata),
2170 plaintype == KEY_RSA ? rsa_kexalg : NULL((void *)0), 0, NULL((void *)0))) != 0) {
2171 error_fr(r, "server gave bad signature for %s key %zu",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2172
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "server gave bad signature for %s key %zu"
, sshkey_type(ctx->keys[i]), i)
2172 sshkey_type(ctx->keys[i]), i)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2172
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "server gave bad signature for %s key %zu"
, sshkey_type(ctx->keys[i]), i)
;
2173 goto out;
2174 }
2175 /* Key is good. Mark it as 'seen' */
2176 ctx->keys_verified[i] = 1;
2177 ndone++;
2178 }
2179 /* Shouldn't happen */
2180 if (ndone != ctx->nnew)
2181 fatal_f("ndone != ctx->nnew (%zu / %zu)", ndone, ctx->nnew)sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 2181, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "ndone != ctx->nnew (%zu / %zu)"
, ndone, ctx->nnew)
;
2182 if ((r = sshpkt_get_end(ssh)) != 0) {
Although the value stored to 'r' is used in the enclosing expression, the value is never actually read from 'r'
2183 error_f("protocol error")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2183
, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "protocol error")
;
2184 goto out;
2185 }
2186
2187 /* Make the edits to known_hosts */
2188 update_known_hosts(ctx);
2189 out:
2190 hostkeys_update_ctx_free(ctx);
2191}
2192
2193/*
2194 * Returns non-zero if the key is accepted by HostkeyAlgorithms.
2195 * Made slightly less trivial by the multiple RSA signature algorithm names.
2196 */
2197static int
2198key_accepted_by_hostkeyalgs(const struct sshkey *key)
2199{
2200 const char *ktype = sshkey_ssh_name(key);
2201 const char *hostkeyalgs = options.hostkeyalgorithms;
2202
2203 if (key == NULL((void *)0) || key->type == KEY_UNSPEC)
2204 return 0;
2205 if (key->type == KEY_RSA &&
2206 (match_pattern_list("rsa-sha2-256", hostkeyalgs, 0) == 1 ||
2207 match_pattern_list("rsa-sha2-512", hostkeyalgs, 0) == 1))
2208 return 1;
2209 return match_pattern_list(ktype, hostkeyalgs, 0) == 1;
2210}
2211
2212/*
2213 * Handle hostkeys-00@openssh.com global request to inform the client of all
2214 * the server's hostkeys. The keys are checked against the user's
2215 * HostkeyAlgorithms preference before they are accepted.
2216 */
2217static int
2218client_input_hostkeys(struct ssh *ssh)
2219{
2220 const u_char *blob = NULL((void *)0);
2221 size_t i, len = 0;
2222 struct sshbuf *buf = NULL((void *)0);
2223 struct sshkey *key = NULL((void *)0), **tmp;
2224 int r;
2225 char *fp;
2226 static int hostkeys_seen = 0; /* XXX use struct ssh */
2227 extern struct sockaddr_storage hostaddr; /* XXX from ssh.c */
2228 struct hostkeys_update_ctx *ctx = NULL((void *)0);
2229 u_int want;
2230
2231 if (hostkeys_seen)
2232 fatal_f("server already sent hostkeys")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 2232, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "server already sent hostkeys"
)
;
2233 if (options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK2 &&
2234 options.batch_mode)
2235 return 1; /* won't ask in batchmode, so don't even try */
2236 if (!options.update_hostkeys || options.num_user_hostfiles <= 0)
2237 return 1;
2238
2239 ctx = xcalloc(1, sizeof(*ctx));
2240 while (ssh_packet_remaining(ssh) > 0) {
2241 sshkey_free(key);
2242 key = NULL((void *)0);
2243 if ((r = sshpkt_get_string_direct(ssh, &blob, &len)) != 0) {
2244 error_fr(r, "parse key")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2244
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse key")
;
2245 goto out;
2246 }
2247 if ((r = sshkey_from_blob(blob, len, &key)) != 0) {
2248 do_log2_fr(r, r == SSH_ERR_KEY_TYPE_UNKNOWN ?sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2250
, 1, r == -14 ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_ERROR, ssh_err
(r), "convert key")
2249 SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_ERROR,sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2250
, 1, r == -14 ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_ERROR, ssh_err
(r), "convert key")
2250 "convert key")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2250
, 1, r == -14 ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_ERROR, ssh_err
(r), "convert key")
;
2251 continue;
2252 }
2253 fp = sshkey_fingerprint(key, options.fingerprint_hash,
2254 SSH_FP_DEFAULT);
2255 debug3_f("received %s key %s", sshkey_type(key), fp)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2255
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "received %s key %s", sshkey_type
(key), fp)
;
2256 free(fp);
2257
2258 if (!key_accepted_by_hostkeyalgs(key)) {
2259 debug3_f("%s key not permitted by "sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2260
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "%s key not permitted by "
"HostkeyAlgorithms", sshkey_ssh_name(key))
2260 "HostkeyAlgorithms", sshkey_ssh_name(key))sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2260
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "%s key not permitted by "
"HostkeyAlgorithms", sshkey_ssh_name(key))
;
2261 continue;
2262 }
2263 /* Skip certs */
2264 if (sshkey_is_cert(key)) {
2265 debug3_f("%s key is a certificate; skipping",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2266
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "%s key is a certificate; skipping"
, sshkey_ssh_name(key))
2266 sshkey_ssh_name(key))sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2266
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "%s key is a certificate; skipping"
, sshkey_ssh_name(key))
;
2267 continue;
2268 }
2269 /* Ensure keys are unique */
2270 for (i = 0; i < ctx->nkeys; i++) {
2271 if (sshkey_equal(key, ctx->keys[i])) {
2272 error_f("received duplicated %s host key",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2273
, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "received duplicated %s host key"
, sshkey_ssh_name(key))
2273 sshkey_ssh_name(key))sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2273
, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "received duplicated %s host key"
, sshkey_ssh_name(key))
;
2274 goto out;
2275 }
2276 }
2277 /* Key is good, record it */
2278 if ((tmp = recallocarray(ctx->keys, ctx->nkeys, ctx->nkeys + 1,
2279 sizeof(*ctx->keys))) == NULL((void *)0))
2280 fatal_f("recallocarray failed nkeys = %zu",sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 2281, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "recallocarray failed nkeys = %zu"
, ctx->nkeys)
2281 ctx->nkeys)sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 2281, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "recallocarray failed nkeys = %zu"
, ctx->nkeys)
;
2282 ctx->keys = tmp;
2283 ctx->keys[ctx->nkeys++] = key;
2284 key = NULL((void *)0);
2285 }
2286
2287 if (ctx->nkeys == 0) {
2288 debug_f("server sent no hostkeys")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2288
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "server sent no hostkeys"
)
;
2289 goto out;
2290 }
2291
2292 if ((ctx->keys_match = calloc(ctx->nkeys,
2293 sizeof(*ctx->keys_match))) == NULL((void *)0) ||
2294 (ctx->keys_verified = calloc(ctx->nkeys,
2295 sizeof(*ctx->keys_verified))) == NULL((void *)0))
2296 fatal_f("calloc failed")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 2296, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "calloc failed")
;
2297
2298 get_hostfile_hostname_ipaddr(host,
2299 options.check_host_ip ? (struct sockaddr *)&hostaddr : NULL((void *)0),
2300 options.port, &ctx->host_str,
2301 options.check_host_ip ? &ctx->ip_str : NULL((void *)0));
2302
2303 /* Find which keys we already know about. */
2304 for (i = 0; i < options.num_user_hostfiles; i++) {
2305 debug_f("searching %s for %s / %s",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2307
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "searching %s for %s / %s"
, options.user_hostfiles[i], ctx->host_str, ctx->ip_str
? ctx->ip_str : "(none)")
2306 options.user_hostfiles[i], ctx->host_str,sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2307
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "searching %s for %s / %s"
, options.user_hostfiles[i], ctx->host_str, ctx->ip_str
? ctx->ip_str : "(none)")
2307 ctx->ip_str ? ctx->ip_str : "(none)")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2307
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "searching %s for %s / %s"
, options.user_hostfiles[i], ctx->host_str, ctx->ip_str
? ctx->ip_str : "(none)")
;
2308 if ((r = hostkeys_foreach(options.user_hostfiles[i],
2309 hostkeys_find, ctx, ctx->host_str, ctx->ip_str,
2310 HKF_WANT_PARSE_KEY(1<<1), 0)) != 0) {
2311 if (r == SSH_ERR_SYSTEM_ERROR-24 && errno(*__errno()) == ENOENT2) {
2312 debug_f("hostkeys file %s does not exist",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2313
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "hostkeys file %s does not exist"
, options.user_hostfiles[i])
2313 options.user_hostfiles[i])sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2313
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "hostkeys file %s does not exist"
, options.user_hostfiles[i])
;
2314 continue;
2315 }
2316 error_fr(r, "hostkeys_foreach failed for %s",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2317
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "hostkeys_foreach failed for %s"
, options.user_hostfiles[i])
2317 options.user_hostfiles[i])sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2317
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "hostkeys_foreach failed for %s"
, options.user_hostfiles[i])
;
2318 goto out;
2319 }
2320 }
2321
2322 /* Figure out if we have any new keys to add */
2323 ctx->nnew = ctx->nincomplete = 0;
2324 want = HKF_MATCH_HOST(1) | ( options.check_host_ip ? HKF_MATCH_IP(1<<1) : 0);
2325 for (i = 0; i < ctx->nkeys; i++) {
2326 if (ctx->keys_match[i] == 0)
2327 ctx->nnew++;
2328 if ((ctx->keys_match[i] & want) != want)
2329 ctx->nincomplete++;
2330 }
2331
2332 debug3_f("%zu server keys: %zu new, %zu retained, "sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2335
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "%zu server keys: %zu new, %zu retained, "
"%zu incomplete match. %zu to remove", ctx->nkeys, ctx->
nnew, ctx->nkeys - ctx->nnew - ctx->nincomplete, ctx
->nincomplete, ctx->nold)
2333 "%zu incomplete match. %zu to remove", ctx->nkeys, ctx->nnew,sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2335
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "%zu server keys: %zu new, %zu retained, "
"%zu incomplete match. %zu to remove", ctx->nkeys, ctx->
nnew, ctx->nkeys - ctx->nnew - ctx->nincomplete, ctx
->nincomplete, ctx->nold)
2334 ctx->nkeys - ctx->nnew - ctx->nincomplete,sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2335
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "%zu server keys: %zu new, %zu retained, "
"%zu incomplete match. %zu to remove", ctx->nkeys, ctx->
nnew, ctx->nkeys - ctx->nnew - ctx->nincomplete, ctx
->nincomplete, ctx->nold)
2335 ctx->nincomplete, ctx->nold)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2335
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "%zu server keys: %zu new, %zu retained, "
"%zu incomplete match. %zu to remove", ctx->nkeys, ctx->
nnew, ctx->nkeys - ctx->nnew - ctx->nincomplete, ctx
->nincomplete, ctx->nold)
;
2336
2337 if (ctx->nnew == 0 && ctx->nold == 0) {
2338 debug_f("no new or deprecated keys from server")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2338
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "no new or deprecated keys from server"
)
;
2339 goto out;
2340 }
2341
2342 /* Various reasons why we cannot proceed with the update */
2343 if (ctx->complex_hostspec) {
2344 debug_f("CA/revocation marker, manual host list or wildcard "sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2345
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "CA/revocation marker, manual host list or wildcard "
"host pattern found, skipping UserKnownHostsFile update")
2345 "host pattern found, skipping UserKnownHostsFile update")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2345
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "CA/revocation marker, manual host list or wildcard "
"host pattern found, skipping UserKnownHostsFile update")
;
2346 goto out;
2347 }
2348 if (ctx->other_name_seen) {
2349 debug_f("host key found matching a different name/address, "sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2350
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "host key found matching a different name/address, "
"skipping UserKnownHostsFile update")
2350 "skipping UserKnownHostsFile update")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2350
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "host key found matching a different name/address, "
"skipping UserKnownHostsFile update")
;
2351 goto out;
2352 }
2353 /*
2354 * If removing keys, check whether they appear under different
2355 * names/addresses and refuse to proceed if they do. This avoids
2356 * cases such as hosts with multiple names becoming inconsistent
2357 * with regards to CheckHostIP entries.
2358 * XXX UpdateHostkeys=force to override this (and other) checks?
2359 */
2360 if (ctx->nold != 0) {
2361 if (check_old_keys_othernames(ctx) != 0)
2362 goto out; /* error already logged */
2363 if (ctx->old_key_seen) {
2364 debug_f("key(s) for %s%s%s exist under other names; "sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2367
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "key(s) for %s%s%s exist under other names; "
"skipping UserKnownHostsFile update", ctx->host_str, ctx->
ip_str == ((void *)0) ? "" : ",", ctx->ip_str == ((void *)
0) ? "" : ctx->ip_str)
2365 "skipping UserKnownHostsFile update",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2367
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "key(s) for %s%s%s exist under other names; "
"skipping UserKnownHostsFile update", ctx->host_str, ctx->
ip_str == ((void *)0) ? "" : ",", ctx->ip_str == ((void *)
0) ? "" : ctx->ip_str)
2366 ctx->host_str, ctx->ip_str == NULL ? "" : ",",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2367
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "key(s) for %s%s%s exist under other names; "
"skipping UserKnownHostsFile update", ctx->host_str, ctx->
ip_str == ((void *)0) ? "" : ",", ctx->ip_str == ((void *)
0) ? "" : ctx->ip_str)
2367 ctx->ip_str == NULL ? "" : ctx->ip_str)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2367
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "key(s) for %s%s%s exist under other names; "
"skipping UserKnownHostsFile update", ctx->host_str, ctx->
ip_str == ((void *)0) ? "" : ",", ctx->ip_str == ((void *)
0) ? "" : ctx->ip_str)
;
2368 goto out;
2369 }
2370 }
2371
2372 if (ctx->nnew == 0) {
2373 /*
2374 * We have some keys to remove or fix matching for.
2375 * We can proceed to do this without requiring a fresh proof
2376 * from the server.
2377 */
2378 update_known_hosts(ctx);
2379 goto out;
2380 }
2381 /*
2382 * We have received previously-unseen keys from the server.
2383 * Ask the server to confirm ownership of the private halves.
2384 */
2385 debug3_f("asking server to prove ownership for %zu keys", ctx->nnew)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2385
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "asking server to prove ownership for %zu keys"
, ctx->nnew)
;
2386 if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST80)) != 0 ||
2387 (r = sshpkt_put_cstring(ssh,
2388 "hostkeys-prove-00@openssh.com")) != 0 ||
2389 (r = sshpkt_put_u8(ssh, 1)) != 0) /* bool: want reply */
2390 fatal_fr(r, "prepare hostkeys-prove")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 2390, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "prepare hostkeys-prove"
)
;
2391 if ((buf = sshbuf_new()) == NULL((void *)0))
2392 fatal_f("sshbuf_new")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 2392, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "sshbuf_new")
;
2393 for (i = 0; i < ctx->nkeys; i++) {
2394 if (ctx->keys_match[i])
2395 continue;
2396 sshbuf_reset(buf);
2397 if ((r = sshkey_putb(ctx->keys[i], buf)) != 0 ||
2398 (r = sshpkt_put_stringb(ssh, buf)) != 0)
2399 fatal_fr(r, "assemble hostkeys-prove")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 2399, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "assemble hostkeys-prove"
)
;
2400 }
2401 if ((r = sshpkt_send(ssh)) != 0)
2402 fatal_fr(r, "send hostkeys-prove")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 2402, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "send hostkeys-prove"
)
;
2403 client_register_global_confirm(
2404 client_global_hostkeys_private_confirm, ctx);
2405 ctx = NULL((void *)0); /* will be freed in callback */
2406
2407 /* Success */
2408 out:
2409 hostkeys_update_ctx_free(ctx);
2410 sshkey_free(key);
2411 sshbuf_free(buf);
2412 /*
2413 * NB. Return success for all cases. The server doesn't need to know
2414 * what the client does with its hosts file.
2415 */
2416 return 1;
2417}
2418
2419static int
2420client_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
2421{
2422 char *rtype;
2423 u_char want_reply;
2424 int r, success = 0;
2425
2426 if ((r = sshpkt_get_cstring(ssh, &rtype, NULL((void *)0))) != 0 ||
2427 (r = sshpkt_get_u8(ssh, &want_reply)) != 0)
2428 goto out;
2429 debug("client_input_global_request: rtype %s want_reply %d",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2430
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "client_input_global_request: rtype %s want_reply %d"
, rtype, want_reply)
2430 rtype, want_reply)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2430
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "client_input_global_request: rtype %s want_reply %d"
, rtype, want_reply)
;
2431 if (strcmp(rtype, "hostkeys-00@openssh.com") == 0)
2432 success = client_input_hostkeys(ssh);
2433 if (want_reply) {
2434 if ((r = sshpkt_start(ssh, success ? SSH2_MSG_REQUEST_SUCCESS81 :
2435 SSH2_MSG_REQUEST_FAILURE82)) != 0 ||
2436 (r = sshpkt_send(ssh)) != 0 ||
2437 (r = ssh_packet_write_wait(ssh)) != 0)
2438 goto out;
2439 }
2440 r = 0;
2441 out:
2442 free(rtype);
2443 return r;
2444}
2445
2446static void
2447client_send_env(struct ssh *ssh, int id, const char *name, const char *val)
2448{
2449 int r;
2450
2451 debug("channel %d: setting env %s = \"%s\"", id, name, val)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2451
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "channel %d: setting env %s = \"%s\""
, id, name, val)
;
2452 channel_request_start(ssh, id, "env", 0);
2453 if ((r = sshpkt_put_cstring(ssh, name)) != 0 ||
2454 (r = sshpkt_put_cstring(ssh, val)) != 0 ||
2455 (r = sshpkt_send(ssh)) != 0)
2456 fatal_fr(r, "send setenv")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 2456, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "send setenv")
;
2457}
2458
2459void
2460client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem,
2461 const char *term, struct termios *tiop, int in_fd, struct sshbuf *cmd,
2462 char **env)
2463{
2464 int i, j, matched, len, r;
2465 char *name, *val;
2466 Channel *c = NULL((void *)0);
2467
2468 debug2_f("id %d", id)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2468
, 1, SYSLOG_LEVEL_DEBUG2, ((void *)0), "id %d", id)
;
2469
2470 if ((c = channel_lookup(ssh, id)) == NULL((void *)0))
2471 fatal_f("channel %d: unknown channel", id)sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 2471, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "channel %d: unknown channel"
, id)
;
2472
2473 ssh_packet_set_interactive(ssh, want_tty,
2474 options.ip_qos_interactive, options.ip_qos_bulk);
2475
2476 if (want_tty) {
2477 struct winsize ws;
2478
2479 /* Store window size in the packet. */
2480 if (ioctl(in_fd, TIOCGWINSZ((unsigned long)0x40000000 | ((sizeof(struct winsize) & 0x1fff
) << 16) | ((('t')) << 8) | ((104)))
, &ws) == -1)
2481 memset(&ws, 0, sizeof(ws));
2482
2483 channel_request_start(ssh, id, "pty-req", 1);
2484 client_expect_confirm(ssh, id, "PTY allocation", CONFIRM_TTY);
2485 if ((r = sshpkt_put_cstring(ssh, term != NULL((void *)0) ? term : ""))
2486 != 0 ||
2487 (r = sshpkt_put_u32(ssh, (u_int)ws.ws_col)) != 0 ||
2488 (r = sshpkt_put_u32(ssh, (u_int)ws.ws_row)) != 0 ||
2489 (r = sshpkt_put_u32(ssh, (u_int)ws.ws_xpixel)) != 0 ||
2490 (r = sshpkt_put_u32(ssh, (u_int)ws.ws_ypixel)) != 0)
2491 fatal_fr(r, "build pty-req")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 2491, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "build pty-req")
;
2492 if (tiop == NULL((void *)0))
2493 tiop = get_saved_tio();
2494 ssh_tty_make_modes(ssh, -1, tiop);
2495 if ((r = sshpkt_send(ssh)) != 0)
2496 fatal_fr(r, "send pty-req")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 2496, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "send pty-req")
;
2497 /* XXX wait for reply */
2498 c->client_tty = 1;
2499 }
2500
2501 /* Transfer any environment variables from client to server */
2502 if (options.num_send_env != 0 && env != NULL((void *)0)) {
2503 debug("Sending environment.")sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2503
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "Sending environment."
)
;
2504 for (i = 0; env[i] != NULL((void *)0); i++) {
2505 /* Split */
2506 name = xstrdup(env[i]);
2507 if ((val = strchr(name, '=')) == NULL((void *)0)) {
2508 free(name);
2509 continue;
2510 }
2511 *val++ = '\0';
2512
2513 matched = 0;
2514 for (j = 0; j < options.num_send_env; j++) {
2515 if (match_pattern(name, options.send_env[j])) {
2516 matched = 1;
2517 break;
2518 }
2519 }
2520 if (!matched) {
2521 debug3("Ignored env %s", name)sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2521
, 0, SYSLOG_LEVEL_DEBUG3, ((void *)0), "Ignored env %s", name
)
;
2522 free(name);
2523 continue;
2524 }
2525 client_send_env(ssh, id, name, val);
2526 free(name);
2527 }
2528 }
2529 for (i = 0; i < options.num_setenv; i++) {
2530 /* Split */
2531 name = xstrdup(options.setenv[i]);
2532 if ((val = strchr(name, '=')) == NULL((void *)0)) {
2533 free(name);
2534 continue;
2535 }
2536 *val++ = '\0';
2537 client_send_env(ssh, id, name, val);
2538 free(name);
2539 }
2540
2541 len = sshbuf_len(cmd);
2542 if (len > 0) {
2543 if (len > 900)
2544 len = 900;
2545 if (want_subsystem) {
2546 debug("Sending subsystem: %.*s",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2547
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "Sending subsystem: %.*s"
, len, (const u_char*)sshbuf_ptr(cmd))
2547 len, (const u_char*)sshbuf_ptr(cmd))sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2547
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "Sending subsystem: %.*s"
, len, (const u_char*)sshbuf_ptr(cmd))
;
2548 channel_request_start(ssh, id, "subsystem", 1);
2549 client_expect_confirm(ssh, id, "subsystem",
2550 CONFIRM_CLOSE);
2551 } else {
2552 debug("Sending command: %.*s",sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2553
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "Sending command: %.*s"
, len, (const u_char*)sshbuf_ptr(cmd))
2553 len, (const u_char*)sshbuf_ptr(cmd))sshlog("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__, 2553
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "Sending command: %.*s"
, len, (const u_char*)sshbuf_ptr(cmd))
;
2554 channel_request_start(ssh, id, "exec", 1);
2555 client_expect_confirm(ssh, id, "exec", CONFIRM_CLOSE);
2556 }
2557 if ((r = sshpkt_put_stringb(ssh, cmd)) != 0 ||
2558 (r = sshpkt_send(ssh)) != 0)
2559 fatal_fr(r, "send command")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 2559, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "send command")
;
2560 } else {
2561 channel_request_start(ssh, id, "shell", 1);
2562 client_expect_confirm(ssh, id, "shell", CONFIRM_CLOSE);
2563 if ((r = sshpkt_send(ssh)) != 0)
2564 fatal_fr(r, "send shell")sshfatal("/usr/src/usr.bin/ssh/ssh/../clientloop.c", __func__
, 2564, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "send shell")
;
2565 }
2566}
2567
2568static void
2569client_init_dispatch(struct ssh *ssh)
2570{
2571 ssh_dispatch_init(ssh, &dispatch_protocol_error);
2572
2573 ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_CLOSE97, &channel_input_oclose);
2574 ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_DATA94, &channel_input_data);
2575 ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_EOF96, &channel_input_ieof);
2576 ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_EXTENDED_DATA95, &channel_input_extended_data);
2577 ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN90, &client_input_channel_open);
2578 ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION91, &channel_input_open_confirmation);
2579 ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN_FAILURE92, &channel_input_open_failure);
2580 ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_REQUEST98, &client_input_channel_req);
2581 ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_WINDOW_ADJUST93, &channel_input_window_adjust);
2582 ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_SUCCESS99, &channel_input_status_confirm);
2583 ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_FAILURE100, &channel_input_status_confirm);
2584 ssh_dispatch_set(ssh, SSH2_MSG_GLOBAL_REQUEST80, &client_input_global_request);
2585
2586 /* rekeying */
2587 ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT20, &kex_input_kexinit);
2588
2589 /* global request reply messages */
2590 ssh_dispatch_set(ssh, SSH2_MSG_REQUEST_FAILURE82, &client_global_request_reply);
2591 ssh_dispatch_set(ssh, SSH2_MSG_REQUEST_SUCCESS81, &client_global_request_reply);
2592}
2593
2594void
2595client_stop_mux(void)
2596{
2597 if (options.control_path != NULL((void *)0) && muxserver_sock != -1)
2598 unlink(options.control_path);
2599 /*
2600 * If we are in persist mode, or don't have a shell, signal that we
2601 * should close when all active channels are closed.
2602 */
2603 if (options.control_persist || options.session_type == SESSION_TYPE_NONE0) {
2604 session_closed = 1;
2605 setproctitle("[stopped mux]");
2606 }
2607}
2608
2609/* client specific fatal cleanup */
2610void
2611cleanup_exit(int i)
2612{
2613 leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE3);
2614 if (options.control_path != NULL((void *)0) && muxserver_sock != -1)
2615 unlink(options.control_path);
2616 ssh_kill_proxy_command();
2617 _exit(i);
2618}