Bug Summary

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