Bug Summary

File:src/usr.bin/ssh/ssh/../channels.c
Warning:line 4013, column 3
Value stored to 'port_to_connect' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name channels.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/ssh/ssh/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.bin/ssh/ssh/.. -D WITH_OPENSSL -D WITH_ZLIB -D ENABLE_PKCS11 -D HAVE_DLOPEN -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/usr/src/usr.bin/ssh/ssh/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/ssh/ssh/../channels.c
1/* $OpenBSD: channels.c,v 1.411 2022/01/06 21:48:38 djm Exp $ */
2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 * All rights reserved
6 * This file contains functions for generic socket connection forwarding.
7 * There is also code for initiating connection forwarding for X11 connections,
8 * arbitrary tcp/ip connections, and the authentication agent connection.
9 *
10 * As far as I am concerned, the code I have written for this software
11 * can be used freely for any purpose. Any derived versions of this
12 * software must be clearly marked as such, and if the derived work is
13 * incompatible with the protocol description in the RFC file, it must be
14 * called by a name other than "ssh" or "Secure Shell".
15 *
16 * SSH2 support added by Markus Friedl.
17 * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
18 * Copyright (c) 1999 Dug Song. All rights reserved.
19 * Copyright (c) 1999 Theo de Raadt. All rights reserved.
20 *
21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions
23 * are met:
24 * 1. Redistributions of source code must retain the above copyright
25 * notice, this list of conditions and the following disclaimer.
26 * 2. Redistributions in binary form must reproduce the above copyright
27 * notice, this list of conditions and the following disclaimer in the
28 * documentation and/or other materials provided with the distribution.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
31 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
32 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
33 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
34 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
35 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
39 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 */
41
42#include <sys/types.h>
43#include <sys/stat.h>
44#include <sys/ioctl.h>
45#include <sys/un.h>
46#include <sys/socket.h>
47#include <sys/time.h>
48#include <sys/queue.h>
49
50#include <netinet/in.h>
51#include <arpa/inet.h>
52
53#include <errno(*__errno()).h>
54#include <fcntl.h>
55#include <limits.h>
56#include <netdb.h>
57#include <poll.h>
58#include <stdarg.h>
59#include <stdint.h>
60#include <stdio.h>
61#include <stdlib.h>
62#include <string.h>
63#include <termios.h>
64#include <unistd.h>
65
66#include "xmalloc.h"
67#include "ssh.h"
68#include "ssh2.h"
69#include "ssherr.h"
70#include "sshbuf.h"
71#include "packet.h"
72#include "log.h"
73#include "misc.h"
74#include "channels.h"
75#include "compat.h"
76#include "canohost.h"
77#include "sshkey.h"
78#include "authfd.h"
79#include "pathnames.h"
80#include "match.h"
81
82/* XXX remove once we're satisfied there's no lurking bugs */
83/* #define DEBUG_CHANNEL_POLL 1 */
84
85/* -- agent forwarding */
86#define NUM_SOCKS10 10
87
88/* -- tcp forwarding */
89/* special-case port number meaning allow any port */
90#define FWD_PERMIT_ANY_PORT0 0
91
92/* special-case wildcard meaning allow any host */
93#define FWD_PERMIT_ANY_HOST"*" "*"
94
95/* -- X11 forwarding */
96/* Maximum number of fake X11 displays to try. */
97#define MAX_DISPLAYS1000 1000
98
99/* Per-channel callback for pre/post IO actions */
100typedef void chan_fn(struct ssh *, Channel *c);
101
102/*
103 * Data structure for storing which hosts are permitted for forward requests.
104 * The local sides of any remote forwards are stored in this array to prevent
105 * a corrupt remote server from accessing arbitrary TCP/IP ports on our local
106 * network (which might be behind a firewall).
107 */
108/* XXX: streamlocal wants a path instead of host:port */
109/* Overload host_to_connect; we could just make this match Forward */
110/* XXX - can we use listen_host instead of listen_path? */
111struct permission {
112 char *host_to_connect; /* Connect to 'host'. */
113 int port_to_connect; /* Connect to 'port'. */
114 char *listen_host; /* Remote side should listen address. */
115 char *listen_path; /* Remote side should listen path. */
116 int listen_port; /* Remote side should listen port. */
117 Channel *downstream; /* Downstream mux*/
118};
119
120/*
121 * Stores the forwarding permission state for a single direction (local or
122 * remote).
123 */
124struct permission_set {
125 /*
126 * List of all local permitted host/port pairs to allow for the
127 * user.
128 */
129 u_int num_permitted_user;
130 struct permission *permitted_user;
131
132 /*
133 * List of all permitted host/port pairs to allow for the admin.
134 */
135 u_int num_permitted_admin;
136 struct permission *permitted_admin;
137
138 /*
139 * If this is true, all opens/listens are permitted. This is the
140 * case on the server on which we have to trust the client anyway,
141 * and the user could do anything after logging in.
142 */
143 int all_permitted;
144};
145
146/* Master structure for channels state */
147struct ssh_channels {
148 /*
149 * Pointer to an array containing all allocated channels. The array
150 * is dynamically extended as needed.
151 */
152 Channel **channels;
153
154 /*
155 * Size of the channel array. All slots of the array must always be
156 * initialized (at least the type field); unused slots set to NULL
157 */
158 u_int channels_alloc;
159
160 /*
161 * 'channel_pre*' are called just before IO to add any bits
162 * relevant to channels in the c->io_want bitmasks.
163 *
164 * 'channel_post*': perform any appropriate operations for
165 * channels which have c->io_ready events pending.
166 */
167 chan_fn **channel_pre;
168 chan_fn **channel_post;
169
170 /* -- tcp forwarding */
171 struct permission_set local_perms;
172 struct permission_set remote_perms;
173
174 /* -- X11 forwarding */
175
176 /* Saved X11 local (client) display. */
177 char *x11_saved_display;
178
179 /* Saved X11 authentication protocol name. */
180 char *x11_saved_proto;
181
182 /* Saved X11 authentication data. This is the real data. */
183 char *x11_saved_data;
184 u_int x11_saved_data_len;
185
186 /* Deadline after which all X11 connections are refused */
187 u_int x11_refuse_time;
188
189 /*
190 * Fake X11 authentication data. This is what the server will be
191 * sending us; we should replace any occurrences of this by the
192 * real data.
193 */
194 u_char *x11_fake_data;
195 u_int x11_fake_data_len;
196
197 /* AF_UNSPEC or AF_INET or AF_INET6 */
198 int IPv4or6;
199};
200
201/* helper */
202static void port_open_helper(struct ssh *ssh, Channel *c, char *rtype);
203static const char *channel_rfwd_bind_host(const char *listen_host);
204
205/* non-blocking connect helpers */
206static int connect_next(struct channel_connect *);
207static void channel_connect_ctx_free(struct channel_connect *);
208static Channel *rdynamic_connect_prepare(struct ssh *, char *, char *);
209static int rdynamic_connect_finish(struct ssh *, Channel *);
210
211/* Setup helper */
212static void channel_handler_init(struct ssh_channels *sc);
213
214/* -- channel core */
215
216void
217channel_init_channels(struct ssh *ssh)
218{
219 struct ssh_channels *sc;
220
221 if ((sc = calloc(1, sizeof(*sc))) == NULL((void *)0))
222 fatal_f("allocation failed")sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 222
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "allocation failed")
;
223 sc->channels_alloc = 10;
224 sc->channels = xcalloc(sc->channels_alloc, sizeof(*sc->channels));
225 sc->IPv4or6 = AF_UNSPEC0;
226 channel_handler_init(sc);
227
228 ssh->chanctxt = sc;
229}
230
231Channel *
232channel_by_id(struct ssh *ssh, int id)
233{
234 Channel *c;
235
236 if (id < 0 || (u_int)id >= ssh->chanctxt->channels_alloc) {
237 logit_f("%d: bad id", id)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 237
, 1, SYSLOG_LEVEL_INFO, ((void *)0), "%d: bad id", id)
;
238 return NULL((void *)0);
239 }
240 c = ssh->chanctxt->channels[id];
241 if (c == NULL((void *)0)) {
242 logit_f("%d: bad id: channel free", id)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 242
, 1, SYSLOG_LEVEL_INFO, ((void *)0), "%d: bad id: channel free"
, id)
;
243 return NULL((void *)0);
244 }
245 return c;
246}
247
248Channel *
249channel_by_remote_id(struct ssh *ssh, u_int remote_id)
250{
251 Channel *c;
252 u_int i;
253
254 for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
255 c = ssh->chanctxt->channels[i];
256 if (c != NULL((void *)0) && c->have_remote_id && c->remote_id == remote_id)
257 return c;
258 }
259 return NULL((void *)0);
260}
261
262/*
263 * Returns the channel if it is allowed to receive protocol messages.
264 * Private channels, like listening sockets, may not receive messages.
265 */
266Channel *
267channel_lookup(struct ssh *ssh, int id)
268{
269 Channel *c;
270
271 if ((c = channel_by_id(ssh, id)) == NULL((void *)0))
272 return NULL((void *)0);
273
274 switch (c->type) {
275 case SSH_CHANNEL_X11_OPEN7:
276 case SSH_CHANNEL_LARVAL10:
277 case SSH_CHANNEL_CONNECTING12:
278 case SSH_CHANNEL_DYNAMIC13:
279 case SSH_CHANNEL_RDYNAMIC_OPEN21:
280 case SSH_CHANNEL_RDYNAMIC_FINISH22:
281 case SSH_CHANNEL_OPENING3:
282 case SSH_CHANNEL_OPEN4:
283 case SSH_CHANNEL_ABANDONED17:
284 case SSH_CHANNEL_MUX_PROXY20:
285 return c;
286 }
287 logit("Non-public channel %d, type %d.", id, c->type)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 287
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Non-public channel %d, type %d."
, id, c->type)
;
288 return NULL((void *)0);
289}
290
291/*
292 * Register filedescriptors for a channel, used when allocating a channel or
293 * when the channel consumer/producer is ready, e.g. shell exec'd
294 */
295static void
296channel_register_fds(struct ssh *ssh, Channel *c, int rfd, int wfd, int efd,
297 int extusage, int nonblock, int is_tty)
298{
299 if (rfd != -1)
300 fcntl(rfd, F_SETFD2, FD_CLOEXEC1);
301 if (wfd != -1 && wfd != rfd)
302 fcntl(wfd, F_SETFD2, FD_CLOEXEC1);
303 if (efd != -1 && efd != rfd && efd != wfd)
304 fcntl(efd, F_SETFD2, FD_CLOEXEC1);
305
306 c->rfd = rfd;
307 c->wfd = wfd;
308 c->sock = (rfd == wfd) ? rfd : -1;
309 c->efd = efd;
310 c->extended_usage = extusage;
311
312 if ((c->isatty = is_tty) != 0)
313 debug2("channel %d: rfd %d isatty", c->self, c->rfd)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 313
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: rfd %d isatty"
, c->self, c->rfd)
;
314
315 /* enable nonblocking mode */
316 c->restore_block = 0;
317 if (nonblock == CHANNEL_NONBLOCK_STDIO2) {
318 /*
319 * Special handling for stdio file descriptors: do not set
320 * non-blocking mode if they are TTYs. Otherwise prepare to
321 * restore their blocking state on exit to avoid interfering
322 * with other programs that follow.
323 */
324 if (rfd != -1 && !isatty(rfd) && fcntl(rfd, F_GETFL3) == 0) {
325 c->restore_block |= CHANNEL_RESTORE_RFD0x01;
326 set_nonblock(rfd);
327 }
328 if (wfd != -1 && !isatty(wfd) && fcntl(wfd, F_GETFL3) == 0) {
329 c->restore_block |= CHANNEL_RESTORE_WFD0x02;
330 set_nonblock(wfd);
331 }
332 if (efd != -1 && !isatty(efd) && fcntl(efd, F_GETFL3) == 0) {
333 c->restore_block |= CHANNEL_RESTORE_EFD0x04;
334 set_nonblock(efd);
335 }
336 } else if (nonblock) {
337 if (rfd != -1)
338 set_nonblock(rfd);
339 if (wfd != -1)
340 set_nonblock(wfd);
341 if (efd != -1)
342 set_nonblock(efd);
343 }
344}
345
346/*
347 * Allocate a new channel object and set its type and socket. This will cause
348 * remote_name to be freed.
349 */
350Channel *
351channel_new(struct ssh *ssh, char *ctype, int type, int rfd, int wfd, int efd,
352 u_int window, u_int maxpack, int extusage, char *remote_name, int nonblock)
353{
354 struct ssh_channels *sc = ssh->chanctxt;
355 u_int i, found;
356 Channel *c;
357 int r;
358
359 /* Try to find a free slot where to put the new channel. */
360 for (i = 0; i < sc->channels_alloc; i++) {
361 if (sc->channels[i] == NULL((void *)0)) {
362 /* Found a free slot. */
363 found = i;
364 break;
365 }
366 }
367 if (i >= sc->channels_alloc) {
368 /*
369 * There are no free slots. Take last+1 slot and expand
370 * the array.
371 */
372 found = sc->channels_alloc;
373 if (sc->channels_alloc > CHANNELS_MAX_CHANNELS(16*1024))
374 fatal_f("internal error: channels_alloc %d too big",sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 375
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "internal error: channels_alloc %d too big"
, sc->channels_alloc)
375 sc->channels_alloc)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 375
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "internal error: channels_alloc %d too big"
, sc->channels_alloc)
;
376 sc->channels = xrecallocarray(sc->channels, sc->channels_alloc,
377 sc->channels_alloc + 10, sizeof(*sc->channels));
378 sc->channels_alloc += 10;
379 debug2("channel: expanding %d", sc->channels_alloc)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 379
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel: expanding %d"
, sc->channels_alloc)
;
380 }
381 /* Initialize and return new channel. */
382 c = sc->channels[found] = xcalloc(1, sizeof(Channel));
383 if ((c->input = sshbuf_new()) == NULL((void *)0) ||
384 (c->output = sshbuf_new()) == NULL((void *)0) ||
385 (c->extended = sshbuf_new()) == NULL((void *)0))
386 fatal_f("sshbuf_new failed")sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 386
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "sshbuf_new failed")
;
387 if ((r = sshbuf_set_max_size(c->input, CHAN_INPUT_MAX(16*1024*1024))) != 0)
388 fatal_fr(r, "sshbuf_set_max_size")sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 388
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "sshbuf_set_max_size")
;
389 c->ostate = CHAN_OUTPUT_OPEN0;
390 c->istate = CHAN_INPUT_OPEN0;
391 channel_register_fds(ssh, c, rfd, wfd, efd, extusage, nonblock, 0);
392 c->self = found;
393 c->type = type;
394 c->ctype = ctype;
395 c->local_window = window;
396 c->local_window_max = window;
397 c->local_maxpacket = maxpack;
398 c->remote_name = xstrdup(remote_name);
399 c->ctl_chan = -1;
400 c->delayed = 1; /* prevent call to channel_post handler */
401 TAILQ_INIT(&c->status_confirms)do { (&c->status_confirms)->tqh_first = ((void *)0)
; (&c->status_confirms)->tqh_last = &(&c->
status_confirms)->tqh_first; } while (0)
;
402 debug("channel %d: new [%s]", found, remote_name)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 402
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "channel %d: new [%s]"
, found, remote_name)
;
403 return c;
404}
405
406int
407channel_close_fd(struct ssh *ssh, Channel *c, int *fdp)
408{
409 int ret, fd = *fdp;
410
411 if (fd == -1)
412 return 0;
413
414 if ((*fdp == c->rfd && (c->restore_block & CHANNEL_RESTORE_RFD0x01) != 0) ||
415 (*fdp == c->wfd && (c->restore_block & CHANNEL_RESTORE_WFD0x02) != 0) ||
416 (*fdp == c->efd && (c->restore_block & CHANNEL_RESTORE_EFD0x04) != 0))
417 (void)fcntl(*fdp, F_SETFL4, 0); /* restore blocking */
418
419 if (*fdp == c->rfd) {
420 c->io_want &= ~SSH_CHAN_IO_RFD0x01;
421 c->io_ready &= ~SSH_CHAN_IO_RFD0x01;
422 c->rfd = -1;
423 }
424 if (*fdp == c->wfd) {
425 c->io_want &= ~SSH_CHAN_IO_WFD0x02;
426 c->io_ready &= ~SSH_CHAN_IO_WFD0x02;
427 c->wfd = -1;
428 }
429 if (*fdp == c->efd) {
430 c->io_want &= ~SSH_CHAN_IO_EFD(0x04|0x08);
431 c->io_ready &= ~SSH_CHAN_IO_EFD(0x04|0x08);
432 c->efd = -1;
433 }
434 if (*fdp == c->sock) {
435 c->io_want &= ~SSH_CHAN_IO_SOCK(0x10|0x20);
436 c->io_ready &= ~SSH_CHAN_IO_SOCK(0x10|0x20);
437 c->sock = -1;
438 }
439
440 ret = close(fd);
441 *fdp = -1; /* probably redundant */
442 return ret;
443}
444
445/* Close all channel fd/socket. */
446static void
447channel_close_fds(struct ssh *ssh, Channel *c)
448{
449 int sock = c->sock, rfd = c->rfd, wfd = c->wfd, efd = c->efd;
450
451 channel_close_fd(ssh, c, &c->sock);
452 if (rfd != sock)
453 channel_close_fd(ssh, c, &c->rfd);
454 if (wfd != sock && wfd != rfd)
455 channel_close_fd(ssh, c, &c->wfd);
456 if (efd != sock && efd != rfd && efd != wfd)
457 channel_close_fd(ssh, c, &c->efd);
458}
459
460static void
461fwd_perm_clear(struct permission *perm)
462{
463 free(perm->host_to_connect);
464 free(perm->listen_host);
465 free(perm->listen_path);
466 memset(perm, 0, sizeof(*perm));
467}
468
469/* Returns an printable name for the specified forwarding permission list */
470static const char *
471fwd_ident(int who, int where)
472{
473 if (who == FORWARD_ADM0x100) {
474 if (where == FORWARD_LOCAL(1<<1))
475 return "admin local";
476 else if (where == FORWARD_REMOTE(1))
477 return "admin remote";
478 } else if (who == FORWARD_USER0x101) {
479 if (where == FORWARD_LOCAL(1<<1))
480 return "user local";
481 else if (where == FORWARD_REMOTE(1))
482 return "user remote";
483 }
484 fatal("Unknown forward permission list %d/%d", who, where)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 484
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "Unknown forward permission list %d/%d"
, who, where)
;
485}
486
487/* Returns the forwarding permission list for the specified direction */
488static struct permission_set *
489permission_set_get(struct ssh *ssh, int where)
490{
491 struct ssh_channels *sc = ssh->chanctxt;
492
493 switch (where) {
494 case FORWARD_LOCAL(1<<1):
495 return &sc->local_perms;
496 break;
497 case FORWARD_REMOTE(1):
498 return &sc->remote_perms;
499 break;
500 default:
501 fatal_f("invalid forwarding direction %d", where)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 501
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "invalid forwarding direction %d"
, where)
;
502 }
503}
504
505/* Returns pointers to the specified forwarding list and its element count */
506static void
507permission_set_get_array(struct ssh *ssh, int who, int where,
508 struct permission ***permpp, u_int **npermpp)
509{
510 struct permission_set *pset = permission_set_get(ssh, where);
511
512 switch (who) {
513 case FORWARD_USER0x101:
514 *permpp = &pset->permitted_user;
515 *npermpp = &pset->num_permitted_user;
516 break;
517 case FORWARD_ADM0x100:
518 *permpp = &pset->permitted_admin;
519 *npermpp = &pset->num_permitted_admin;
520 break;
521 default:
522 fatal_f("invalid forwarding client %d", who)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 522
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "invalid forwarding client %d"
, who)
;
523 }
524}
525
526/* Adds an entry to the specified forwarding list */
527static int
528permission_set_add(struct ssh *ssh, int who, int where,
529 const char *host_to_connect, int port_to_connect,
530 const char *listen_host, const char *listen_path, int listen_port,
531 Channel *downstream)
532{
533 struct permission **permp;
534 u_int n, *npermp;
535
536 permission_set_get_array(ssh, who, where, &permp, &npermp);
537
538 if (*npermp >= INT_MAX2147483647)
539 fatal_f("%s overflow", fwd_ident(who, where))sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 539
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "%s overflow", fwd_ident
(who, where))
;
540
541 *permp = xrecallocarray(*permp, *npermp, *npermp + 1, sizeof(**permp));
542 n = (*npermp)++;
543#define MAYBE_DUP(s) ((s == NULL((void *)0)) ? NULL((void *)0) : xstrdup(s))
544 (*permp)[n].host_to_connect = MAYBE_DUP(host_to_connect);
545 (*permp)[n].port_to_connect = port_to_connect;
546 (*permp)[n].listen_host = MAYBE_DUP(listen_host);
547 (*permp)[n].listen_path = MAYBE_DUP(listen_path);
548 (*permp)[n].listen_port = listen_port;
549 (*permp)[n].downstream = downstream;
550#undef MAYBE_DUP
551 return (int)n;
552}
553
554static void
555mux_remove_remote_forwardings(struct ssh *ssh, Channel *c)
556{
557 struct ssh_channels *sc = ssh->chanctxt;
558 struct permission_set *pset = &sc->local_perms;
559 struct permission *perm;
560 int r;
561 u_int i;
562
563 for (i = 0; i < pset->num_permitted_user; i++) {
564 perm = &pset->permitted_user[i];
565 if (perm->downstream != c)
566 continue;
567
568 /* cancel on the server, since mux client is gone */
569 debug("channel %d: cleanup remote forward for %s:%u",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 570
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "channel %d: cleanup remote forward for %s:%u"
, c->self, perm->listen_host, perm->listen_port)
570 c->self, perm->listen_host, perm->listen_port)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 570
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "channel %d: cleanup remote forward for %s:%u"
, c->self, perm->listen_host, perm->listen_port)
;
571 if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST80)) != 0 ||
572 (r = sshpkt_put_cstring(ssh,
573 "cancel-tcpip-forward")) != 0 ||
574 (r = sshpkt_put_u8(ssh, 0)) != 0 ||
575 (r = sshpkt_put_cstring(ssh,
576 channel_rfwd_bind_host(perm->listen_host))) != 0 ||
577 (r = sshpkt_put_u32(ssh, perm->listen_port)) != 0 ||
578 (r = sshpkt_send(ssh)) != 0) {
579 fatal_fr(r, "channel %i", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 579
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i", c->self
)
;
580 }
581 fwd_perm_clear(perm); /* unregister */
582 }
583}
584
585/* Free the channel and close its fd/socket. */
586void
587channel_free(struct ssh *ssh, Channel *c)
588{
589 struct ssh_channels *sc = ssh->chanctxt;
590 char *s;
591 u_int i, n;
592 Channel *other;
593 struct channel_confirm *cc;
594
595 for (n = 0, i = 0; i < sc->channels_alloc; i++) {
596 if ((other = sc->channels[i]) == NULL((void *)0))
597 continue;
598 n++;
599 /* detach from mux client and prepare for closing */
600 if (c->type == SSH_CHANNEL_MUX_CLIENT16 &&
601 other->type == SSH_CHANNEL_MUX_PROXY20 &&
602 other->mux_ctx == c) {
603 other->mux_ctx = NULL((void *)0);
604 other->type = SSH_CHANNEL_OPEN4;
605 other->istate = CHAN_INPUT_CLOSED3;
606 other->ostate = CHAN_OUTPUT_CLOSED3;
607 }
608 }
609 debug("channel %d: free: %s, nchannels %u", c->self,sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 610
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "channel %d: free: %s, nchannels %u"
, c->self, c->remote_name ? c->remote_name : "???", n
)
610 c->remote_name ? c->remote_name : "???", n)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 610
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "channel %d: free: %s, nchannels %u"
, c->self, c->remote_name ? c->remote_name : "???", n
)
;
611
612 if (c->type == SSH_CHANNEL_MUX_CLIENT16) {
613 mux_remove_remote_forwardings(ssh, c);
614 free(c->mux_ctx);
615 c->mux_ctx = NULL((void *)0);
616 } else if (c->type == SSH_CHANNEL_MUX_LISTENER15) {
617 free(c->mux_ctx);
618 c->mux_ctx = NULL((void *)0);
619 }
620
621 if (log_level_get() >= SYSLOG_LEVEL_DEBUG3) {
622 s = channel_open_message(ssh);
623 debug3("channel %d: status: %s", c->self, s)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 623
, 0, SYSLOG_LEVEL_DEBUG3, ((void *)0), "channel %d: status: %s"
, c->self, s)
;
624 free(s);
625 }
626
627 channel_close_fds(ssh, c);
628 sshbuf_free(c->input);
629 sshbuf_free(c->output);
630 sshbuf_free(c->extended);
631 c->input = c->output = c->extended = NULL((void *)0);
632 free(c->remote_name);
633 c->remote_name = NULL((void *)0);
634 free(c->path);
635 c->path = NULL((void *)0);
636 free(c->listening_addr);
637 c->listening_addr = NULL((void *)0);
638 while ((cc = TAILQ_FIRST(&c->status_confirms)((&c->status_confirms)->tqh_first)) != NULL((void *)0)) {
639 if (cc->abandon_cb != NULL((void *)0))
640 cc->abandon_cb(ssh, c, cc->ctx);
641 TAILQ_REMOVE(&c->status_confirms, cc, entry)do { if (((cc)->entry.tqe_next) != ((void *)0)) (cc)->entry
.tqe_next->entry.tqe_prev = (cc)->entry.tqe_prev; else (
&c->status_confirms)->tqh_last = (cc)->entry.tqe_prev
; *(cc)->entry.tqe_prev = (cc)->entry.tqe_next; ; ; } while
(0)
;
642 freezero(cc, sizeof(*cc));
643 }
644 if (c->filter_cleanup != NULL((void *)0) && c->filter_ctx != NULL((void *)0))
645 c->filter_cleanup(ssh, c->self, c->filter_ctx);
646 sc->channels[c->self] = NULL((void *)0);
647 freezero(c, sizeof(*c));
648}
649
650void
651channel_free_all(struct ssh *ssh)
652{
653 u_int i;
654 struct ssh_channels *sc = ssh->chanctxt;
655
656 for (i = 0; i < sc->channels_alloc; i++)
657 if (sc->channels[i] != NULL((void *)0))
658 channel_free(ssh, sc->channels[i]);
659
660 free(sc->channels);
661 sc->channels = NULL((void *)0);
662 sc->channels_alloc = 0;
663
664 free(sc->x11_saved_display);
665 sc->x11_saved_display = NULL((void *)0);
666
667 free(sc->x11_saved_proto);
668 sc->x11_saved_proto = NULL((void *)0);
669
670 free(sc->x11_saved_data);
671 sc->x11_saved_data = NULL((void *)0);
672 sc->x11_saved_data_len = 0;
673
674 free(sc->x11_fake_data);
675 sc->x11_fake_data = NULL((void *)0);
676 sc->x11_fake_data_len = 0;
677}
678
679/*
680 * Closes the sockets/fds of all channels. This is used to close extra file
681 * descriptors after a fork.
682 */
683void
684channel_close_all(struct ssh *ssh)
685{
686 u_int i;
687
688 for (i = 0; i < ssh->chanctxt->channels_alloc; i++)
689 if (ssh->chanctxt->channels[i] != NULL((void *)0))
690 channel_close_fds(ssh, ssh->chanctxt->channels[i]);
691}
692
693/*
694 * Stop listening to channels.
695 */
696void
697channel_stop_listening(struct ssh *ssh)
698{
699 u_int i;
700 Channel *c;
701
702 for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
703 c = ssh->chanctxt->channels[i];
704 if (c != NULL((void *)0)) {
705 switch (c->type) {
706 case SSH_CHANNEL_AUTH_SOCKET6:
707 case SSH_CHANNEL_PORT_LISTENER2:
708 case SSH_CHANNEL_RPORT_LISTENER11:
709 case SSH_CHANNEL_X11_LISTENER1:
710 case SSH_CHANNEL_UNIX_LISTENER18:
711 case SSH_CHANNEL_RUNIX_LISTENER19:
712 channel_close_fd(ssh, c, &c->sock);
713 channel_free(ssh, c);
714 break;
715 }
716 }
717 }
718}
719
720/*
721 * Returns true if no channel has too much buffered data, and false if one or
722 * more channel is overfull.
723 */
724int
725channel_not_very_much_buffered_data(struct ssh *ssh)
726{
727 u_int i;
728 u_int maxsize = ssh_packet_get_maxsize(ssh);
729 Channel *c;
730
731 for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
732 c = ssh->chanctxt->channels[i];
733 if (c == NULL((void *)0) || c->type != SSH_CHANNEL_OPEN4)
734 continue;
735 if (sshbuf_len(c->output) > maxsize) {
736 debug2("channel %d: big output buffer %zu > %u",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 737
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: big output buffer %zu > %u"
, c->self, sshbuf_len(c->output), maxsize)
737 c->self, sshbuf_len(c->output), maxsize)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 737
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: big output buffer %zu > %u"
, c->self, sshbuf_len(c->output), maxsize)
;
738 return 0;
739 }
740 }
741 return 1;
742}
743
744/* Returns true if any channel is still open. */
745int
746channel_still_open(struct ssh *ssh)
747{
748 u_int i;
749 Channel *c;
750
751 for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
752 c = ssh->chanctxt->channels[i];
753 if (c == NULL((void *)0))
754 continue;
755 switch (c->type) {
756 case SSH_CHANNEL_X11_LISTENER1:
757 case SSH_CHANNEL_PORT_LISTENER2:
758 case SSH_CHANNEL_RPORT_LISTENER11:
759 case SSH_CHANNEL_MUX_LISTENER15:
760 case SSH_CHANNEL_CLOSED5:
761 case SSH_CHANNEL_AUTH_SOCKET6:
762 case SSH_CHANNEL_DYNAMIC13:
763 case SSH_CHANNEL_RDYNAMIC_OPEN21:
764 case SSH_CHANNEL_CONNECTING12:
765 case SSH_CHANNEL_ZOMBIE14:
766 case SSH_CHANNEL_ABANDONED17:
767 case SSH_CHANNEL_UNIX_LISTENER18:
768 case SSH_CHANNEL_RUNIX_LISTENER19:
769 continue;
770 case SSH_CHANNEL_LARVAL10:
771 continue;
772 case SSH_CHANNEL_OPENING3:
773 case SSH_CHANNEL_OPEN4:
774 case SSH_CHANNEL_RDYNAMIC_FINISH22:
775 case SSH_CHANNEL_X11_OPEN7:
776 case SSH_CHANNEL_MUX_CLIENT16:
777 case SSH_CHANNEL_MUX_PROXY20:
778 return 1;
779 default:
780 fatal_f("bad channel type %d", c->type)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 780
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "bad channel type %d", c
->type)
;
781 /* NOTREACHED */
782 }
783 }
784 return 0;
785}
786
787/* Returns the id of an open channel suitable for keepaliving */
788int
789channel_find_open(struct ssh *ssh)
790{
791 u_int i;
792 Channel *c;
793
794 for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
795 c = ssh->chanctxt->channels[i];
796 if (c == NULL((void *)0) || !c->have_remote_id)
797 continue;
798 switch (c->type) {
799 case SSH_CHANNEL_CLOSED5:
800 case SSH_CHANNEL_DYNAMIC13:
801 case SSH_CHANNEL_RDYNAMIC_OPEN21:
802 case SSH_CHANNEL_RDYNAMIC_FINISH22:
803 case SSH_CHANNEL_X11_LISTENER1:
804 case SSH_CHANNEL_PORT_LISTENER2:
805 case SSH_CHANNEL_RPORT_LISTENER11:
806 case SSH_CHANNEL_MUX_LISTENER15:
807 case SSH_CHANNEL_MUX_CLIENT16:
808 case SSH_CHANNEL_MUX_PROXY20:
809 case SSH_CHANNEL_OPENING3:
810 case SSH_CHANNEL_CONNECTING12:
811 case SSH_CHANNEL_ZOMBIE14:
812 case SSH_CHANNEL_ABANDONED17:
813 case SSH_CHANNEL_UNIX_LISTENER18:
814 case SSH_CHANNEL_RUNIX_LISTENER19:
815 continue;
816 case SSH_CHANNEL_LARVAL10:
817 case SSH_CHANNEL_AUTH_SOCKET6:
818 case SSH_CHANNEL_OPEN4:
819 case SSH_CHANNEL_X11_OPEN7:
820 return i;
821 default:
822 fatal_f("bad channel type %d", c->type)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 822
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "bad channel type %d", c
->type)
;
823 /* NOTREACHED */
824 }
825 }
826 return -1;
827}
828
829/* Returns the state of the channel's extended usage flag */
830const char *
831channel_format_extended_usage(const Channel *c)
832{
833 if (c->efd == -1)
834 return "closed";
835
836 switch (c->extended_usage) {
837 case CHAN_EXTENDED_WRITE2:
838 return "write";
839 case CHAN_EXTENDED_READ1:
840 return "read";
841 case CHAN_EXTENDED_IGNORE0:
842 return "ignore";
843 default:
844 return "UNKNOWN";
845 }
846}
847
848static char *
849channel_format_status(const Channel *c)
850{
851 char *ret = NULL((void *)0);
852
853 xasprintf(&ret, "t%d %s%u i%u/%zu o%u/%zu e[%s]/%zu "
854 "fd %d/%d/%d sock %d cc %d io 0x%02x/0x%02x",
855 c->type,
856 c->have_remote_id ? "r" : "nr", c->remote_id,
857 c->istate, sshbuf_len(c->input),
858 c->ostate, sshbuf_len(c->output),
859 channel_format_extended_usage(c), sshbuf_len(c->extended),
860 c->rfd, c->wfd, c->efd, c->sock, c->ctl_chan,
861 c->io_want, c->io_ready);
862 return ret;
863}
864
865/*
866 * Returns a message describing the currently open forwarded connections,
867 * suitable for sending to the client. The message contains crlf pairs for
868 * newlines.
869 */
870char *
871channel_open_message(struct ssh *ssh)
872{
873 struct sshbuf *buf;
874 Channel *c;
875 u_int i;
876 int r;
877 char *cp, *ret;
878
879 if ((buf = sshbuf_new()) == NULL((void *)0))
880 fatal_f("sshbuf_new")sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 880
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "sshbuf_new")
;
881 if ((r = sshbuf_putf(buf,
882 "The following connections are open:\r\n")) != 0)
883 fatal_fr(r, "sshbuf_putf")sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 883
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "sshbuf_putf")
;
884 for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
885 c = ssh->chanctxt->channels[i];
886 if (c == NULL((void *)0))
887 continue;
888 switch (c->type) {
889 case SSH_CHANNEL_X11_LISTENER1:
890 case SSH_CHANNEL_PORT_LISTENER2:
891 case SSH_CHANNEL_RPORT_LISTENER11:
892 case SSH_CHANNEL_CLOSED5:
893 case SSH_CHANNEL_AUTH_SOCKET6:
894 case SSH_CHANNEL_ZOMBIE14:
895 case SSH_CHANNEL_ABANDONED17:
896 case SSH_CHANNEL_MUX_LISTENER15:
897 case SSH_CHANNEL_UNIX_LISTENER18:
898 case SSH_CHANNEL_RUNIX_LISTENER19:
899 continue;
900 case SSH_CHANNEL_LARVAL10:
901 case SSH_CHANNEL_OPENING3:
902 case SSH_CHANNEL_CONNECTING12:
903 case SSH_CHANNEL_DYNAMIC13:
904 case SSH_CHANNEL_RDYNAMIC_OPEN21:
905 case SSH_CHANNEL_RDYNAMIC_FINISH22:
906 case SSH_CHANNEL_OPEN4:
907 case SSH_CHANNEL_X11_OPEN7:
908 case SSH_CHANNEL_MUX_PROXY20:
909 case SSH_CHANNEL_MUX_CLIENT16:
910 cp = channel_format_status(c);
911 if ((r = sshbuf_putf(buf, " #%d %.300s (%s)\r\n",
912 c->self, c->remote_name, cp)) != 0) {
913 free(cp);
914 fatal_fr(r, "sshbuf_putf")sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 914
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "sshbuf_putf")
;
915 }
916 free(cp);
917 continue;
918 default:
919 fatal_f("bad channel type %d", c->type)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 919
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "bad channel type %d", c
->type)
;
920 /* NOTREACHED */
921 }
922 }
923 if ((ret = sshbuf_dup_string(buf)) == NULL((void *)0))
924 fatal_f("sshbuf_dup_string")sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 924
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "sshbuf_dup_string")
;
925 sshbuf_free(buf);
926 return ret;
927}
928
929static void
930open_preamble(struct ssh *ssh, const char *where, Channel *c, const char *type)
931{
932 int r;
933
934 if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN90)) != 0 ||
935 (r = sshpkt_put_cstring(ssh, type)) != 0 ||
936 (r = sshpkt_put_u32(ssh, c->self)) != 0 ||
937 (r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||
938 (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0) {
939 fatal_r(r, "%s: channel %i: open", where, c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 939
, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), "%s: channel %i: open", where
, c->self)
;
940 }
941}
942
943void
944channel_send_open(struct ssh *ssh, int id)
945{
946 Channel *c = channel_lookup(ssh, id);
947 int r;
948
949 if (c == NULL((void *)0)) {
950 logit("channel_send_open: %d: bad id", id)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 950
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "channel_send_open: %d: bad id"
, id)
;
951 return;
952 }
953 debug2("channel %d: send open", id)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 953
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: send open"
, id)
;
954 open_preamble(ssh, __func__, c, c->ctype);
955 if ((r = sshpkt_send(ssh)) != 0)
956 fatal_fr(r, "channel %i", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 956
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i", c->self
)
;
957}
958
959void
960channel_request_start(struct ssh *ssh, int id, char *service, int wantconfirm)
961{
962 Channel *c = channel_lookup(ssh, id);
963 int r;
964
965 if (c == NULL((void *)0)) {
966 logit_f("%d: unknown channel id", id)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 966
, 1, SYSLOG_LEVEL_INFO, ((void *)0), "%d: unknown channel id"
, id)
;
967 return;
968 }
969 if (!c->have_remote_id)
970 fatal_f("channel %d: no remote id", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 970
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "channel %d: no remote id"
, c->self)
;
971
972 debug2("channel %d: request %s confirm %d", id, service, wantconfirm)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 972
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: request %s confirm %d"
, id, service, wantconfirm)
;
973 if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_REQUEST98)) != 0 ||
974 (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
975 (r = sshpkt_put_cstring(ssh, service)) != 0 ||
976 (r = sshpkt_put_u8(ssh, wantconfirm)) != 0) {
977 fatal_fr(r, "channel %i", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 977
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i", c->self
)
;
978 }
979}
980
981void
982channel_register_status_confirm(struct ssh *ssh, int id,
983 channel_confirm_cb *cb, channel_confirm_abandon_cb *abandon_cb, void *ctx)
984{
985 struct channel_confirm *cc;
986 Channel *c;
987
988 if ((c = channel_lookup(ssh, id)) == NULL((void *)0))
989 fatal_f("%d: bad id", id)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 989
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "%d: bad id", id)
;
990
991 cc = xcalloc(1, sizeof(*cc));
992 cc->cb = cb;
993 cc->abandon_cb = abandon_cb;
994 cc->ctx = ctx;
995 TAILQ_INSERT_TAIL(&c->status_confirms, cc, entry)do { (cc)->entry.tqe_next = ((void *)0); (cc)->entry.tqe_prev
= (&c->status_confirms)->tqh_last; *(&c->status_confirms
)->tqh_last = (cc); (&c->status_confirms)->tqh_last
= &(cc)->entry.tqe_next; } while (0)
;
996}
997
998void
999channel_register_open_confirm(struct ssh *ssh, int id,
1000 channel_open_fn *fn, void *ctx)
1001{
1002 Channel *c = channel_lookup(ssh, id);
1003
1004 if (c == NULL((void *)0)) {
1005 logit_f("%d: bad id", id)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1005
, 1, SYSLOG_LEVEL_INFO, ((void *)0), "%d: bad id", id)
;
1006 return;
1007 }
1008 c->open_confirm = fn;
1009 c->open_confirm_ctx = ctx;
1010}
1011
1012void
1013channel_register_cleanup(struct ssh *ssh, int id,
1014 channel_callback_fn *fn, int do_close)
1015{
1016 Channel *c = channel_by_id(ssh, id);
1017
1018 if (c == NULL((void *)0)) {
1019 logit_f("%d: bad id", id)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1019
, 1, SYSLOG_LEVEL_INFO, ((void *)0), "%d: bad id", id)
;
1020 return;
1021 }
1022 c->detach_user = fn;
1023 c->detach_close = do_close;
1024}
1025
1026void
1027channel_cancel_cleanup(struct ssh *ssh, int id)
1028{
1029 Channel *c = channel_by_id(ssh, id);
1030
1031 if (c == NULL((void *)0)) {
1032 logit_f("%d: bad id", id)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1032
, 1, SYSLOG_LEVEL_INFO, ((void *)0), "%d: bad id", id)
;
1033 return;
1034 }
1035 c->detach_user = NULL((void *)0);
1036 c->detach_close = 0;
1037}
1038
1039void
1040channel_register_filter(struct ssh *ssh, int id, channel_infilter_fn *ifn,
1041 channel_outfilter_fn *ofn, channel_filter_cleanup_fn *cfn, void *ctx)
1042{
1043 Channel *c = channel_lookup(ssh, id);
1044
1045 if (c == NULL((void *)0)) {
1046 logit_f("%d: bad id", id)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1046
, 1, SYSLOG_LEVEL_INFO, ((void *)0), "%d: bad id", id)
;
1047 return;
1048 }
1049 c->input_filter = ifn;
1050 c->output_filter = ofn;
1051 c->filter_ctx = ctx;
1052 c->filter_cleanup = cfn;
1053}
1054
1055void
1056channel_set_fds(struct ssh *ssh, int id, int rfd, int wfd, int efd,
1057 int extusage, int nonblock, int is_tty, u_int window_max)
1058{
1059 Channel *c = channel_lookup(ssh, id);
1060 int r;
1061
1062 if (c == NULL((void *)0) || c->type != SSH_CHANNEL_LARVAL10)
1063 fatal("channel_activate for non-larval channel %d.", id)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1063
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "channel_activate for non-larval channel %d."
, id)
;
1064 if (!c->have_remote_id)
1065 fatal_f("channel %d: no remote id", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1065
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "channel %d: no remote id"
, c->self)
;
1066
1067 channel_register_fds(ssh, c, rfd, wfd, efd, extusage, nonblock, is_tty);
1068 c->type = SSH_CHANNEL_OPEN4;
1069 c->local_window = c->local_window_max = window_max;
1070
1071 if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_WINDOW_ADJUST93)) != 0 ||
1072 (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
1073 (r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||
1074 (r = sshpkt_send(ssh)) != 0)
1075 fatal_fr(r, "channel %i", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1075
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i", c->self
)
;
1076}
1077
1078static void
1079channel_pre_listener(struct ssh *ssh, Channel *c)
1080{
1081 c->io_want = SSH_CHAN_IO_SOCK_R0x10;
1082}
1083
1084static void
1085channel_pre_connecting(struct ssh *ssh, Channel *c)
1086{
1087 debug3("channel %d: waiting for connection", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1087
, 0, SYSLOG_LEVEL_DEBUG3, ((void *)0), "channel %d: waiting for connection"
, c->self)
;
1088 c->io_want = SSH_CHAN_IO_SOCK_W0x20;
1089}
1090
1091static void
1092channel_pre_open(struct ssh *ssh, Channel *c)
1093{
1094 c->io_want = 0;
1095 if (c->istate == CHAN_INPUT_OPEN0 &&
1096 c->remote_window > 0 &&
1097 sshbuf_len(c->input) < c->remote_window &&
1098 sshbuf_check_reserve(c->input, CHAN_RBUF(16*1024)) == 0)
1099 c->io_want |= SSH_CHAN_IO_RFD0x01;
1100 if (c->ostate == CHAN_OUTPUT_OPEN0 ||
1101 c->ostate == CHAN_OUTPUT_WAIT_DRAIN1) {
1102 if (sshbuf_len(c->output) > 0) {
1103 c->io_want |= SSH_CHAN_IO_WFD0x02;
1104 } else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN1) {
1105 if (CHANNEL_EFD_OUTPUT_ACTIVE(c)(c->extended_usage == 2 && c->efd != -1 &&
(!(c->flags & (0x08|0x02)) || sshbuf_len(c->extended
) > 0))
)
1106 debug2("channel %d: "sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1108
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: " "obuf_empty delayed efd %d/(%zu)"
, c->self, c->efd, sshbuf_len(c->extended))
1107 "obuf_empty delayed efd %d/(%zu)", c->self,sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1108
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: " "obuf_empty delayed efd %d/(%zu)"
, c->self, c->efd, sshbuf_len(c->extended))
1108 c->efd, sshbuf_len(c->extended))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1108
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: " "obuf_empty delayed efd %d/(%zu)"
, c->self, c->efd, sshbuf_len(c->extended))
;
1109 else
1110 chan_obuf_empty(ssh, c);
1111 }
1112 }
1113 /** XXX check close conditions, too */
1114 if (c->efd != -1 && !(c->istate == CHAN_INPUT_CLOSED3 &&
1115 c->ostate == CHAN_OUTPUT_CLOSED3)) {
1116 if (c->extended_usage == CHAN_EXTENDED_WRITE2 &&
1117 sshbuf_len(c->extended) > 0)
1118 c->io_want |= SSH_CHAN_IO_EFD_W0x08;
1119 else if (c->efd != -1 && !(c->flags & CHAN_EOF_SENT0x04) &&
1120 (c->extended_usage == CHAN_EXTENDED_READ1 ||
1121 c->extended_usage == CHAN_EXTENDED_IGNORE0) &&
1122 sshbuf_len(c->extended) < c->remote_window)
1123 c->io_want |= SSH_CHAN_IO_EFD_R0x04;
1124 }
1125 /* XXX: What about efd? races? */
1126}
1127
1128/*
1129 * This is a special state for X11 authentication spoofing. An opened X11
1130 * connection (when authentication spoofing is being done) remains in this
1131 * state until the first packet has been completely read. The authentication
1132 * data in that packet is then substituted by the real data if it matches the
1133 * fake data, and the channel is put into normal mode.
1134 * XXX All this happens at the client side.
1135 * Returns: 0 = need more data, -1 = wrong cookie, 1 = ok
1136 */
1137static int
1138x11_open_helper(struct ssh *ssh, struct sshbuf *b)
1139{
1140 struct ssh_channels *sc = ssh->chanctxt;
1141 u_char *ucp;
1142 u_int proto_len, data_len;
1143
1144 /* Is this being called after the refusal deadline? */
1145 if (sc->x11_refuse_time != 0 &&
1146 (u_int)monotime() >= sc->x11_refuse_time) {
1147 verbose("Rejected X11 connection after ForwardX11Timeout "sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1148
, 0, SYSLOG_LEVEL_VERBOSE, ((void *)0), "Rejected X11 connection after ForwardX11Timeout "
"expired")
1148 "expired")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1148
, 0, SYSLOG_LEVEL_VERBOSE, ((void *)0), "Rejected X11 connection after ForwardX11Timeout "
"expired")
;
1149 return -1;
1150 }
1151
1152 /* Check if the fixed size part of the packet is in buffer. */
1153 if (sshbuf_len(b) < 12)
1154 return 0;
1155
1156 /* Parse the lengths of variable-length fields. */
1157 ucp = sshbuf_mutable_ptr(b);
1158 if (ucp[0] == 0x42) { /* Byte order MSB first. */
1159 proto_len = 256 * ucp[6] + ucp[7];
1160 data_len = 256 * ucp[8] + ucp[9];
1161 } else if (ucp[0] == 0x6c) { /* Byte order LSB first. */
1162 proto_len = ucp[6] + 256 * ucp[7];
1163 data_len = ucp[8] + 256 * ucp[9];
1164 } else {
1165 debug2("Initial X11 packet contains bad byte order byte: 0x%x",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1166
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "Initial X11 packet contains bad byte order byte: 0x%x"
, ucp[0])
1166 ucp[0])sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1166
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "Initial X11 packet contains bad byte order byte: 0x%x"
, ucp[0])
;
1167 return -1;
1168 }
1169
1170 /* Check if the whole packet is in buffer. */
1171 if (sshbuf_len(b) <
1172 12 + ((proto_len + 3) & ~3) + ((data_len + 3) & ~3))
1173 return 0;
1174
1175 /* Check if authentication protocol matches. */
1176 if (proto_len != strlen(sc->x11_saved_proto) ||
1177 memcmp(ucp + 12, sc->x11_saved_proto, proto_len) != 0) {
1178 debug2("X11 connection uses different authentication protocol.")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1178
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "X11 connection uses different authentication protocol."
)
;
1179 return -1;
1180 }
1181 /* Check if authentication data matches our fake data. */
1182 if (data_len != sc->x11_fake_data_len ||
1183 timingsafe_bcmp(ucp + 12 + ((proto_len + 3) & ~3),
1184 sc->x11_fake_data, sc->x11_fake_data_len) != 0) {
1185 debug2("X11 auth data does not match fake data.")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1185
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "X11 auth data does not match fake data."
)
;
1186 return -1;
1187 }
1188 /* Check fake data length */
1189 if (sc->x11_fake_data_len != sc->x11_saved_data_len) {
1190 error("X11 fake_data_len %d != saved_data_len %d",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1191
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "X11 fake_data_len %d != saved_data_len %d"
, sc->x11_fake_data_len, sc->x11_saved_data_len)
1191 sc->x11_fake_data_len, sc->x11_saved_data_len)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1191
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "X11 fake_data_len %d != saved_data_len %d"
, sc->x11_fake_data_len, sc->x11_saved_data_len)
;
1192 return -1;
1193 }
1194 /*
1195 * Received authentication protocol and data match
1196 * our fake data. Substitute the fake data with real
1197 * data.
1198 */
1199 memcpy(ucp + 12 + ((proto_len + 3) & ~3),
1200 sc->x11_saved_data, sc->x11_saved_data_len);
1201 return 1;
1202}
1203
1204static void
1205channel_pre_x11_open(struct ssh *ssh, Channel *c)
1206{
1207 int ret = x11_open_helper(ssh, c->output);
1208
1209 /* c->force_drain = 1; */
1210
1211 if (ret == 1) {
1212 c->type = SSH_CHANNEL_OPEN4;
1213 channel_pre_open(ssh, c);
1214 } else if (ret == -1) {
1215 logit("X11 connection rejected because of wrong authentication.")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1215
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "X11 connection rejected because of wrong authentication."
)
;
1216 debug2("X11 rejected %d i%d/o%d",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1217
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "X11 rejected %d i%d/o%d"
, c->self, c->istate, c->ostate)
1217 c->self, c->istate, c->ostate)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1217
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "X11 rejected %d i%d/o%d"
, c->self, c->istate, c->ostate)
;
1218 chan_read_failed(ssh, c);
1219 sshbuf_reset(c->input);
1220 chan_ibuf_empty(ssh, c);
1221 sshbuf_reset(c->output);
1222 chan_write_failed(ssh, c);
1223 debug2("X11 closed %d i%d/o%d", c->self, c->istate, c->ostate)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1223
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "X11 closed %d i%d/o%d"
, c->self, c->istate, c->ostate)
;
1224 }
1225}
1226
1227static void
1228channel_pre_mux_client(struct ssh *ssh, Channel *c)
1229{
1230 c->io_want = 0;
1231 if (c->istate == CHAN_INPUT_OPEN0 && !c->mux_pause &&
1232 sshbuf_check_reserve(c->input, CHAN_RBUF(16*1024)) == 0)
1233 c->io_want |= SSH_CHAN_IO_RFD0x01;
1234 if (c->istate == CHAN_INPUT_WAIT_DRAIN1) {
1235 /* clear buffer immediately (discard any partial packet) */
1236 sshbuf_reset(c->input);
1237 chan_ibuf_empty(ssh, c);
1238 /* Start output drain. XXX just kill chan? */
1239 chan_rcvd_oclose(ssh, c);
1240 }
1241 if (c->ostate == CHAN_OUTPUT_OPEN0 ||
1242 c->ostate == CHAN_OUTPUT_WAIT_DRAIN1) {
1243 if (sshbuf_len(c->output) > 0)
1244 c->io_want |= SSH_CHAN_IO_WFD0x02;
1245 else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN1)
1246 chan_obuf_empty(ssh, c);
1247 }
1248}
1249
1250/* try to decode a socks4 header */
1251static int
1252channel_decode_socks4(Channel *c, struct sshbuf *input, struct sshbuf *output)
1253{
1254 const u_char *p;
1255 char *host;
1256 u_int len, have, i, found, need;
1257 char username[256];
1258 struct {
1259 u_int8_t version;
1260 u_int8_t command;
1261 u_int16_t dest_port;
1262 struct in_addr dest_addr;
1263 } s4_req, s4_rsp;
1264 int r;
1265
1266 debug2("channel %d: decode socks4", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1266
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: decode socks4"
, c->self)
;
1267
1268 have = sshbuf_len(input);
1269 len = sizeof(s4_req);
1270 if (have < len)
1271 return 0;
1272 p = sshbuf_ptr(input);
1273
1274 need = 1;
1275 /* SOCKS4A uses an invalid IP address 0.0.0.x */
1276 if (p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] != 0) {
1277 debug2("channel %d: socks4a request", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1277
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: socks4a request"
, c->self)
;
1278 /* ... and needs an extra string (the hostname) */
1279 need = 2;
1280 }
1281 /* Check for terminating NUL on the string(s) */
1282 for (found = 0, i = len; i < have; i++) {
1283 if (p[i] == '\0') {
1284 found++;
1285 if (found == need)
1286 break;
1287 }
1288 if (i > 1024) {
1289 /* the peer is probably sending garbage */
1290 debug("channel %d: decode socks4: too long",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1291
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "channel %d: decode socks4: too long"
, c->self)
1291 c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1291
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "channel %d: decode socks4: too long"
, c->self)
;
1292 return -1;
1293 }
1294 }
1295 if (found < need)
1296 return 0;
1297 if ((r = sshbuf_get(input, &s4_req.version, 1)) != 0 ||
1298 (r = sshbuf_get(input, &s4_req.command, 1)) != 0 ||
1299 (r = sshbuf_get(input, &s4_req.dest_port, 2)) != 0 ||
1300 (r = sshbuf_get(input, &s4_req.dest_addr, 4)) != 0) {
1301 debug_r(r, "channels %d: decode socks4", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1301
, 0, SYSLOG_LEVEL_DEBUG1, ssh_err(r), "channels %d: decode socks4"
, c->self)
;
1302 return -1;
1303 }
1304 have = sshbuf_len(input);
1305 p = sshbuf_ptr(input);
1306 if (memchr(p, '\0', have) == NULL((void *)0)) {
1307 error("channel %d: decode socks4: unterminated user", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1307
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "channel %d: decode socks4: unterminated user"
, c->self)
;
1308 return -1;
1309 }
1310 len = strlen(p);
1311 debug2("channel %d: decode socks4: user %s/%d", c->self, p, len)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1311
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: decode socks4: user %s/%d"
, c->self, p, len)
;
1312 len++; /* trailing '\0' */
1313 strlcpy(username, p, sizeof(username));
1314 if ((r = sshbuf_consume(input, len)) != 0)
1315 fatal_fr(r, "channel %d: consume", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1315
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %d: consume", c
->self)
;
1316 free(c->path);
1317 c->path = NULL((void *)0);
1318 if (need == 1) { /* SOCKS4: one string */
1319 host = inet_ntoa(s4_req.dest_addr);
1320 c->path = xstrdup(host);
1321 } else { /* SOCKS4A: two strings */
1322 have = sshbuf_len(input);
1323 p = sshbuf_ptr(input);
1324 if (memchr(p, '\0', have) == NULL((void *)0)) {
1325 error("channel %d: decode socks4a: host not nul "sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1326
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "channel %d: decode socks4a: host not nul "
"terminated", c->self)
1326 "terminated", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1326
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "channel %d: decode socks4a: host not nul "
"terminated", c->self)
;
1327 return -1;
1328 }
1329 len = strlen(p);
1330 debug2("channel %d: decode socks4a: host %s/%d",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1331
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: decode socks4a: host %s/%d"
, c->self, p, len)
1331 c->self, p, len)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1331
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: decode socks4a: host %s/%d"
, c->self, p, len)
;
1332 len++; /* trailing '\0' */
1333 if (len > NI_MAXHOST256) {
1334 error("channel %d: hostname \"%.100s\" too long",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1335
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "channel %d: hostname \"%.100s\" too long"
, c->self, p)
1335 c->self, p)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1335
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "channel %d: hostname \"%.100s\" too long"
, c->self, p)
;
1336 return -1;
1337 }
1338 c->path = xstrdup(p);
1339 if ((r = sshbuf_consume(input, len)) != 0)
1340 fatal_fr(r, "channel %d: consume", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1340
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %d: consume", c
->self)
;
1341 }
1342 c->host_port = ntohs(s4_req.dest_port)(__uint16_t)(__builtin_constant_p(s4_req.dest_port) ? (__uint16_t
)(((__uint16_t)(s4_req.dest_port) & 0xffU) << 8 | (
(__uint16_t)(s4_req.dest_port) & 0xff00U) >> 8) : __swap16md
(s4_req.dest_port))
;
1343
1344 debug2("channel %d: dynamic request: socks4 host %s port %u command %u",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1345
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: dynamic request: socks4 host %s port %u command %u"
, c->self, c->path, c->host_port, s4_req.command)
1345 c->self, c->path, c->host_port, s4_req.command)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1345
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: dynamic request: socks4 host %s port %u command %u"
, c->self, c->path, c->host_port, s4_req.command)
;
1346
1347 if (s4_req.command != 1) {
1348 debug("channel %d: cannot handle: %s cn %d",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1349
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "channel %d: cannot handle: %s cn %d"
, c->self, need == 1 ? "SOCKS4" : "SOCKS4A", s4_req.command
)
1349 c->self, need == 1 ? "SOCKS4" : "SOCKS4A", s4_req.command)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1349
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "channel %d: cannot handle: %s cn %d"
, c->self, need == 1 ? "SOCKS4" : "SOCKS4A", s4_req.command
)
;
1350 return -1;
1351 }
1352 s4_rsp.version = 0; /* vn: 0 for reply */
1353 s4_rsp.command = 90; /* cd: req granted */
1354 s4_rsp.dest_port = 0; /* ignored */
1355 s4_rsp.dest_addr.s_addr = INADDR_ANY((u_int32_t)(0x00000000)); /* ignored */
1356 if ((r = sshbuf_put(output, &s4_rsp, sizeof(s4_rsp))) != 0)
1357 fatal_fr(r, "channel %d: append reply", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1357
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %d: append reply"
, c->self)
;
1358 return 1;
1359}
1360
1361/* try to decode a socks5 header */
1362#define SSH_SOCKS5_AUTHDONE0x1000 0x1000
1363#define SSH_SOCKS5_NOAUTH0x00 0x00
1364#define SSH_SOCKS5_IPV40x01 0x01
1365#define SSH_SOCKS5_DOMAIN0x03 0x03
1366#define SSH_SOCKS5_IPV60x04 0x04
1367#define SSH_SOCKS5_CONNECT0x01 0x01
1368#define SSH_SOCKS5_SUCCESS0x00 0x00
1369
1370static int
1371channel_decode_socks5(Channel *c, struct sshbuf *input, struct sshbuf *output)
1372{
1373 /* XXX use get/put_u8 instead of trusting struct padding */
1374 struct {
1375 u_int8_t version;
1376 u_int8_t command;
1377 u_int8_t reserved;
1378 u_int8_t atyp;
1379 } s5_req, s5_rsp;
1380 u_int16_t dest_port;
1381 char dest_addr[255+1], ntop[INET6_ADDRSTRLEN46];
1382 const u_char *p;
1383 u_int have, need, i, found, nmethods, addrlen, af;
1384 int r;
1385
1386 debug2("channel %d: decode socks5", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1386
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: decode socks5"
, c->self)
;
1387 p = sshbuf_ptr(input);
1388 if (p[0] != 0x05)
1389 return -1;
1390 have = sshbuf_len(input);
1391 if (!(c->flags & SSH_SOCKS5_AUTHDONE0x1000)) {
1392 /* format: ver | nmethods | methods */
1393 if (have < 2)
1394 return 0;
1395 nmethods = p[1];
1396 if (have < nmethods + 2)
1397 return 0;
1398 /* look for method: "NO AUTHENTICATION REQUIRED" */
1399 for (found = 0, i = 2; i < nmethods + 2; i++) {
1400 if (p[i] == SSH_SOCKS5_NOAUTH0x00) {
1401 found = 1;
1402 break;
1403 }
1404 }
1405 if (!found) {
1406 debug("channel %d: method SSH_SOCKS5_NOAUTH not found",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1407
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "channel %d: method SSH_SOCKS5_NOAUTH not found"
, c->self)
1407 c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1407
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "channel %d: method SSH_SOCKS5_NOAUTH not found"
, c->self)
;
1408 return -1;
1409 }
1410 if ((r = sshbuf_consume(input, nmethods + 2)) != 0)
1411 fatal_fr(r, "channel %d: consume", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1411
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %d: consume", c
->self)
;
1412 /* version, method */
1413 if ((r = sshbuf_put_u8(output, 0x05)) != 0 ||
1414 (r = sshbuf_put_u8(output, SSH_SOCKS5_NOAUTH0x00)) != 0)
1415 fatal_fr(r, "channel %d: append reply", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1415
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %d: append reply"
, c->self)
;
1416 c->flags |= SSH_SOCKS5_AUTHDONE0x1000;
1417 debug2("channel %d: socks5 auth done", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1417
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: socks5 auth done"
, c->self)
;
1418 return 0; /* need more */
1419 }
1420 debug2("channel %d: socks5 post auth", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1420
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: socks5 post auth"
, c->self)
;
1421 if (have < sizeof(s5_req)+1)
1422 return 0; /* need more */
1423 memcpy(&s5_req, p, sizeof(s5_req));
1424 if (s5_req.version != 0x05 ||
1425 s5_req.command != SSH_SOCKS5_CONNECT0x01 ||
1426 s5_req.reserved != 0x00) {
1427 debug2("channel %d: only socks5 connect supported", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1427
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: only socks5 connect supported"
, c->self)
;
1428 return -1;
1429 }
1430 switch (s5_req.atyp){
1431 case SSH_SOCKS5_IPV40x01:
1432 addrlen = 4;
1433 af = AF_INET2;
1434 break;
1435 case SSH_SOCKS5_DOMAIN0x03:
1436 addrlen = p[sizeof(s5_req)];
1437 af = -1;
1438 break;
1439 case SSH_SOCKS5_IPV60x04:
1440 addrlen = 16;
1441 af = AF_INET624;
1442 break;
1443 default:
1444 debug2("channel %d: bad socks5 atyp %d", c->self, s5_req.atyp)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1444
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: bad socks5 atyp %d"
, c->self, s5_req.atyp)
;
1445 return -1;
1446 }
1447 need = sizeof(s5_req) + addrlen + 2;
1448 if (s5_req.atyp == SSH_SOCKS5_DOMAIN0x03)
1449 need++;
1450 if (have < need)
1451 return 0;
1452 if ((r = sshbuf_consume(input, sizeof(s5_req))) != 0)
1453 fatal_fr(r, "channel %d: consume", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1453
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %d: consume", c
->self)
;
1454 if (s5_req.atyp == SSH_SOCKS5_DOMAIN0x03) {
1455 /* host string length */
1456 if ((r = sshbuf_consume(input, 1)) != 0)
1457 fatal_fr(r, "channel %d: consume", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1457
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %d: consume", c
->self)
;
1458 }
1459 if ((r = sshbuf_get(input, &dest_addr, addrlen)) != 0 ||
1460 (r = sshbuf_get(input, &dest_port, 2)) != 0) {
1461 debug_r(r, "channel %d: parse addr/port", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1461
, 0, SYSLOG_LEVEL_DEBUG1, ssh_err(r), "channel %d: parse addr/port"
, c->self)
;
1462 return -1;
1463 }
1464 dest_addr[addrlen] = '\0';
1465 free(c->path);
1466 c->path = NULL((void *)0);
1467 if (s5_req.atyp == SSH_SOCKS5_DOMAIN0x03) {
1468 if (addrlen >= NI_MAXHOST256) {
1469 error("channel %d: dynamic request: socks5 hostname "sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1470
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "channel %d: dynamic request: socks5 hostname "
"\"%.100s\" too long", c->self, dest_addr)
1470 "\"%.100s\" too long", c->self, dest_addr)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1470
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "channel %d: dynamic request: socks5 hostname "
"\"%.100s\" too long", c->self, dest_addr)
;
1471 return -1;
1472 }
1473 c->path = xstrdup(dest_addr);
1474 } else {
1475 if (inet_ntop(af, dest_addr, ntop, sizeof(ntop)) == NULL((void *)0))
1476 return -1;
1477 c->path = xstrdup(ntop);
1478 }
1479 c->host_port = ntohs(dest_port)(__uint16_t)(__builtin_constant_p(dest_port) ? (__uint16_t)((
(__uint16_t)(dest_port) & 0xffU) << 8 | ((__uint16_t
)(dest_port) & 0xff00U) >> 8) : __swap16md(dest_port
))
;
1480
1481 debug2("channel %d: dynamic request: socks5 host %s port %u command %u",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1482
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: dynamic request: socks5 host %s port %u command %u"
, c->self, c->path, c->host_port, s5_req.command)
1482 c->self, c->path, c->host_port, s5_req.command)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1482
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: dynamic request: socks5 host %s port %u command %u"
, c->self, c->path, c->host_port, s5_req.command)
;
1483
1484 s5_rsp.version = 0x05;
1485 s5_rsp.command = SSH_SOCKS5_SUCCESS0x00;
1486 s5_rsp.reserved = 0; /* ignored */
1487 s5_rsp.atyp = SSH_SOCKS5_IPV40x01;
1488 dest_port = 0; /* ignored */
1489
1490 if ((r = sshbuf_put(output, &s5_rsp, sizeof(s5_rsp))) != 0 ||
1491 (r = sshbuf_put_u32(output, ntohl(INADDR_ANY)(__uint32_t)(__builtin_constant_p(((u_int32_t)(0x00000000))) ?
(__uint32_t)(((__uint32_t)(((u_int32_t)(0x00000000))) & 0xff
) << 24 | ((__uint32_t)(((u_int32_t)(0x00000000))) &
0xff00) << 8 | ((__uint32_t)(((u_int32_t)(0x00000000))
) & 0xff0000) >> 8 | ((__uint32_t)(((u_int32_t)(0x00000000
))) & 0xff000000) >> 24) : __swap32md(((u_int32_t)(
0x00000000))))
)) != 0 ||
1492 (r = sshbuf_put(output, &dest_port, sizeof(dest_port))) != 0)
1493 fatal_fr(r, "channel %d: append reply", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1493
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %d: append reply"
, c->self)
;
1494 return 1;
1495}
1496
1497Channel *
1498channel_connect_stdio_fwd(struct ssh *ssh,
1499 const char *host_to_connect, u_short port_to_connect,
1500 int in, int out, int nonblock)
1501{
1502 Channel *c;
1503
1504 debug_f("%s:%d", host_to_connect, port_to_connect)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1504
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "%s:%d", host_to_connect
, port_to_connect)
;
1505
1506 c = channel_new(ssh, "stdio-forward", SSH_CHANNEL_OPENING3, in, out,
1507 -1, CHAN_TCP_WINDOW_DEFAULT(64*(32*1024)), CHAN_TCP_PACKET_DEFAULT(32*1024),
1508 0, "stdio-forward", nonblock);
1509
1510 c->path = xstrdup(host_to_connect);
1511 c->host_port = port_to_connect;
1512 c->listening_port = 0;
1513 c->force_drain = 1;
1514
1515 channel_register_fds(ssh, c, in, out, -1, 0, 1, 0);
1516 port_open_helper(ssh, c, "direct-tcpip");
1517
1518 return c;
1519}
1520
1521/* dynamic port forwarding */
1522static void
1523channel_pre_dynamic(struct ssh *ssh, Channel *c)
1524{
1525 const u_char *p;
1526 u_int have;
1527 int ret;
1528
1529 c->io_want = 0;
1530 have = sshbuf_len(c->input);
1531 debug2("channel %d: pre_dynamic: have %d", c->self, have)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1531
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: pre_dynamic: have %d"
, c->self, have)
;
1532 /* sshbuf_dump(c->input, stderr); */
1533 /* check if the fixed size part of the packet is in buffer. */
1534 if (have < 3) {
1535 /* need more */
1536 c->io_want |= SSH_CHAN_IO_RFD0x01;
1537 return;
1538 }
1539 /* try to guess the protocol */
1540 p = sshbuf_ptr(c->input);
1541 /* XXX sshbuf_peek_u8? */
1542 switch (p[0]) {
1543 case 0x04:
1544 ret = channel_decode_socks4(c, c->input, c->output);
1545 break;
1546 case 0x05:
1547 ret = channel_decode_socks5(c, c->input, c->output);
1548 break;
1549 default:
1550 ret = -1;
1551 break;
1552 }
1553 if (ret < 0) {
1554 chan_mark_dead(ssh, c);
1555 } else if (ret == 0) {
1556 debug2("channel %d: pre_dynamic: need more", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1556
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: pre_dynamic: need more"
, c->self)
;
1557 /* need more */
1558 c->io_want |= SSH_CHAN_IO_RFD0x01;
1559 if (sshbuf_len(c->output))
1560 c->io_want |= SSH_CHAN_IO_WFD0x02;
1561 } else {
1562 /* switch to the next state */
1563 c->type = SSH_CHANNEL_OPENING3;
1564 port_open_helper(ssh, c, "direct-tcpip");
1565 }
1566}
1567
1568/* simulate read-error */
1569static void
1570rdynamic_close(struct ssh *ssh, Channel *c)
1571{
1572 c->type = SSH_CHANNEL_OPEN4;
1573 chan_read_failed(ssh, c);
1574 sshbuf_reset(c->input);
1575 chan_ibuf_empty(ssh, c);
1576 sshbuf_reset(c->output);
1577 chan_write_failed(ssh, c);
1578}
1579
1580/* reverse dynamic port forwarding */
1581static void
1582channel_before_prepare_io_rdynamic(struct ssh *ssh, Channel *c)
1583{
1584 const u_char *p;
1585 u_int have, len;
1586 int r, ret;
1587
1588 have = sshbuf_len(c->output);
1589 debug2("channel %d: pre_rdynamic: have %d", c->self, have)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1589
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: pre_rdynamic: have %d"
, c->self, have)
;
1590 /* sshbuf_dump(c->output, stderr); */
1591 /* EOF received */
1592 if (c->flags & CHAN_EOF_RCVD0x08) {
1593 if ((r = sshbuf_consume(c->output, have)) != 0)
1594 fatal_fr(r, "channel %d: consume", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1594
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %d: consume", c
->self)
;
1595 rdynamic_close(ssh, c);
1596 return;
1597 }
1598 /* check if the fixed size part of the packet is in buffer. */
1599 if (have < 3)
1600 return;
1601 /* try to guess the protocol */
1602 p = sshbuf_ptr(c->output);
1603 switch (p[0]) {
1604 case 0x04:
1605 /* switch input/output for reverse forwarding */
1606 ret = channel_decode_socks4(c, c->output, c->input);
1607 break;
1608 case 0x05:
1609 ret = channel_decode_socks5(c, c->output, c->input);
1610 break;
1611 default:
1612 ret = -1;
1613 break;
1614 }
1615 if (ret < 0) {
1616 rdynamic_close(ssh, c);
1617 } else if (ret == 0) {
1618 debug2("channel %d: pre_rdynamic: need more", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1618
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: pre_rdynamic: need more"
, c->self)
;
1619 /* send socks request to peer */
1620 len = sshbuf_len(c->input);
1621 if (len > 0 && len < c->remote_window) {
1622 if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA94)) != 0 ||
1623 (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
1624 (r = sshpkt_put_stringb(ssh, c->input)) != 0 ||
1625 (r = sshpkt_send(ssh)) != 0) {
1626 fatal_fr(r, "channel %i: rdynamic", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1626
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i: rdynamic", c
->self)
;
1627 }
1628 if ((r = sshbuf_consume(c->input, len)) != 0)
1629 fatal_fr(r, "channel %d: consume", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1629
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %d: consume", c
->self)
;
1630 c->remote_window -= len;
1631 }
1632 } else if (rdynamic_connect_finish(ssh, c) < 0) {
1633 /* the connect failed */
1634 rdynamic_close(ssh, c);
1635 }
1636}
1637
1638/* This is our fake X11 server socket. */
1639static void
1640channel_post_x11_listener(struct ssh *ssh, Channel *c)
1641{
1642 Channel *nc;
1643 struct sockaddr_storage addr;
1644 int r, newsock, oerrno, remote_port;
1645 socklen_t addrlen;
1646 char buf[16384], *remote_ipaddr;
1647
1648 if ((c->io_ready & SSH_CHAN_IO_SOCK_R0x10) == 0)
1649 return;
1650
1651 debug("X11 connection requested.")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1651
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "X11 connection requested."
)
;
1652 addrlen = sizeof(addr);
1653 newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen);
1654 if (c->single_connection) {
1655 oerrno = errno(*__errno());
1656 debug2("single_connection: closing X11 listener.")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1656
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "single_connection: closing X11 listener."
)
;
1657 channel_close_fd(ssh, c, &c->sock);
1658 chan_mark_dead(ssh, c);
1659 errno(*__errno()) = oerrno;
1660 }
1661 if (newsock == -1) {
1662 if (errno(*__errno()) != EINTR4 && errno(*__errno()) != EWOULDBLOCK35 &&
1663 errno(*__errno()) != ECONNABORTED53)
1664 error("accept: %.100s", strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1664
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "accept: %.100s", strerror
((*__errno())))
;
1665 if (errno(*__errno()) == EMFILE24 || errno(*__errno()) == ENFILE23)
1666 c->notbefore = monotime() + 1;
1667 return;
1668 }
1669 set_nodelay(newsock);
1670 remote_ipaddr = get_peer_ipaddr(newsock);
1671 remote_port = get_peer_port(newsock);
1672 snprintf(buf, sizeof buf, "X11 connection from %.200s port %d",
1673 remote_ipaddr, remote_port);
1674
1675 nc = channel_new(ssh, "accepted x11 socket",
1676 SSH_CHANNEL_OPENING3, newsock, newsock, -1,
1677 c->local_window_max, c->local_maxpacket, 0, buf, 1);
1678 open_preamble(ssh, __func__, nc, "x11");
1679 if ((r = sshpkt_put_cstring(ssh, remote_ipaddr)) != 0 ||
1680 (r = sshpkt_put_u32(ssh, remote_port)) != 0) {
1681 fatal_fr(r, "channel %i: reply", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1681
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i: reply", c->
self)
;
1682 }
1683 if ((r = sshpkt_send(ssh)) != 0)
1684 fatal_fr(r, "channel %i: send", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1684
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i: send", c->
self)
;
1685 free(remote_ipaddr);
1686}
1687
1688static void
1689port_open_helper(struct ssh *ssh, Channel *c, char *rtype)
1690{
1691 char *local_ipaddr = get_local_ipaddr(c->sock);
1692 int local_port = c->sock == -1 ? 65536 : get_local_port(c->sock);
1693 char *remote_ipaddr = get_peer_ipaddr(c->sock);
1694 int remote_port = get_peer_port(c->sock);
1695 int r;
1696
1697 if (remote_port == -1) {
1698 /* Fake addr/port to appease peers that validate it (Tectia) */
1699 free(remote_ipaddr);
1700 remote_ipaddr = xstrdup("127.0.0.1");
1701 remote_port = 65535;
1702 }
1703
1704 free(c->remote_name);
1705 xasprintf(&c->remote_name,
1706 "%s: listening port %d for %.100s port %d, "
1707 "connect from %.200s port %d to %.100s port %d",
1708 rtype, c->listening_port, c->path, c->host_port,
1709 remote_ipaddr, remote_port, local_ipaddr, local_port);
1710
1711 open_preamble(ssh, __func__, c, rtype);
1712 if (strcmp(rtype, "direct-tcpip") == 0) {
1713 /* target host, port */
1714 if ((r = sshpkt_put_cstring(ssh, c->path)) != 0 ||
1715 (r = sshpkt_put_u32(ssh, c->host_port)) != 0)
1716 fatal_fr(r, "channel %i: reply", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1716
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i: reply", c->
self)
;
1717 } else if (strcmp(rtype, "direct-streamlocal@openssh.com") == 0) {
1718 /* target path */
1719 if ((r = sshpkt_put_cstring(ssh, c->path)) != 0)
1720 fatal_fr(r, "channel %i: reply", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1720
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i: reply", c->
self)
;
1721 } else if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) {
1722 /* listen path */
1723 if ((r = sshpkt_put_cstring(ssh, c->path)) != 0)
1724 fatal_fr(r, "channel %i: reply", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1724
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i: reply", c->
self)
;
1725 } else {
1726 /* listen address, port */
1727 if ((r = sshpkt_put_cstring(ssh, c->path)) != 0 ||
1728 (r = sshpkt_put_u32(ssh, local_port)) != 0)
1729 fatal_fr(r, "channel %i: reply", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1729
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i: reply", c->
self)
;
1730 }
1731 if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) {
1732 /* reserved for future owner/mode info */
1733 if ((r = sshpkt_put_cstring(ssh, "")) != 0)
1734 fatal_fr(r, "channel %i: reply", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1734
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i: reply", c->
self)
;
1735 } else {
1736 /* originator host and port */
1737 if ((r = sshpkt_put_cstring(ssh, remote_ipaddr)) != 0 ||
1738 (r = sshpkt_put_u32(ssh, (u_int)remote_port)) != 0)
1739 fatal_fr(r, "channel %i: reply", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1739
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i: reply", c->
self)
;
1740 }
1741 if ((r = sshpkt_send(ssh)) != 0)
1742 fatal_fr(r, "channel %i: send", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1742
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i: send", c->
self)
;
1743 free(remote_ipaddr);
1744 free(local_ipaddr);
1745}
1746
1747void
1748channel_set_x11_refuse_time(struct ssh *ssh, u_int refuse_time)
1749{
1750 ssh->chanctxt->x11_refuse_time = refuse_time;
1751}
1752
1753/*
1754 * This socket is listening for connections to a forwarded TCP/IP port.
1755 */
1756static void
1757channel_post_port_listener(struct ssh *ssh, Channel *c)
1758{
1759 Channel *nc;
1760 struct sockaddr_storage addr;
1761 int newsock, nextstate;
1762 socklen_t addrlen;
1763 char *rtype;
1764
1765 if ((c->io_ready & SSH_CHAN_IO_SOCK_R0x10) == 0)
1766 return;
1767
1768 debug("Connection to port %d forwarding to %.100s port %d requested.",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1769
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "Connection to port %d forwarding to %.100s port %d requested."
, c->listening_port, c->path, c->host_port)
1769 c->listening_port, c->path, c->host_port)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1769
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "Connection to port %d forwarding to %.100s port %d requested."
, c->listening_port, c->path, c->host_port)
;
1770
1771 if (c->type == SSH_CHANNEL_RPORT_LISTENER11) {
1772 nextstate = SSH_CHANNEL_OPENING3;
1773 rtype = "forwarded-tcpip";
1774 } else if (c->type == SSH_CHANNEL_RUNIX_LISTENER19) {
1775 nextstate = SSH_CHANNEL_OPENING3;
1776 rtype = "forwarded-streamlocal@openssh.com";
1777 } else if (c->host_port == PORT_STREAMLOCAL-2) {
1778 nextstate = SSH_CHANNEL_OPENING3;
1779 rtype = "direct-streamlocal@openssh.com";
1780 } else if (c->host_port == 0) {
1781 nextstate = SSH_CHANNEL_DYNAMIC13;
1782 rtype = "dynamic-tcpip";
1783 } else {
1784 nextstate = SSH_CHANNEL_OPENING3;
1785 rtype = "direct-tcpip";
1786 }
1787
1788 addrlen = sizeof(addr);
1789 newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen);
1790 if (newsock == -1) {
1791 if (errno(*__errno()) != EINTR4 && errno(*__errno()) != EWOULDBLOCK35 &&
1792 errno(*__errno()) != ECONNABORTED53)
1793 error("accept: %.100s", strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1793
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "accept: %.100s", strerror
((*__errno())))
;
1794 if (errno(*__errno()) == EMFILE24 || errno(*__errno()) == ENFILE23)
1795 c->notbefore = monotime() + 1;
1796 return;
1797 }
1798 if (c->host_port != PORT_STREAMLOCAL-2)
1799 set_nodelay(newsock);
1800 nc = channel_new(ssh, rtype, nextstate, newsock, newsock, -1,
1801 c->local_window_max, c->local_maxpacket, 0, rtype, 1);
1802 nc->listening_port = c->listening_port;
1803 nc->host_port = c->host_port;
1804 if (c->path != NULL((void *)0))
1805 nc->path = xstrdup(c->path);
1806
1807 if (nextstate != SSH_CHANNEL_DYNAMIC13)
1808 port_open_helper(ssh, nc, rtype);
1809}
1810
1811/*
1812 * This is the authentication agent socket listening for connections from
1813 * clients.
1814 */
1815static void
1816channel_post_auth_listener(struct ssh *ssh, Channel *c)
1817{
1818 Channel *nc;
1819 int r, newsock;
1820 struct sockaddr_storage addr;
1821 socklen_t addrlen;
1822
1823 if ((c->io_ready & SSH_CHAN_IO_SOCK_R0x10) == 0)
1824 return;
1825
1826 addrlen = sizeof(addr);
1827 newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen);
1828 if (newsock == -1) {
1829 error("accept from auth socket: %.100s", strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1829
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "accept from auth socket: %.100s"
, strerror((*__errno())))
;
1830 if (errno(*__errno()) == EMFILE24 || errno(*__errno()) == ENFILE23)
1831 c->notbefore = monotime() + 1;
1832 return;
1833 }
1834 nc = channel_new(ssh, "accepted auth socket",
1835 SSH_CHANNEL_OPENING3, newsock, newsock, -1,
1836 c->local_window_max, c->local_maxpacket,
1837 0, "accepted auth socket", 1);
1838 open_preamble(ssh, __func__, nc, "auth-agent@openssh.com");
1839 if ((r = sshpkt_send(ssh)) != 0)
1840 fatal_fr(r, "channel %i", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1840
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i", c->self
)
;
1841}
1842
1843static void
1844channel_post_connecting(struct ssh *ssh, Channel *c)
1845{
1846 int err = 0, sock, isopen, r;
1847 socklen_t sz = sizeof(err);
1848
1849 if ((c->io_ready & SSH_CHAN_IO_SOCK_W0x20) == 0)
1850 return;
1851 if (!c->have_remote_id)
1852 fatal_f("channel %d: no remote id", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1852
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "channel %d: no remote id"
, c->self)
;
1853 /* for rdynamic the OPEN_CONFIRMATION has been sent already */
1854 isopen = (c->type == SSH_CHANNEL_RDYNAMIC_FINISH22);
1855 if (getsockopt(c->sock, SOL_SOCKET0xffff, SO_ERROR0x1007, &err, &sz) == -1) {
1856 err = errno(*__errno());
1857 error("getsockopt SO_ERROR failed")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1857
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "getsockopt SO_ERROR failed"
)
;
1858 }
1859 if (err == 0) {
1860 debug("channel %d: connected to %s port %d",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1861
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "channel %d: connected to %s port %d"
, c->self, c->connect_ctx.host, c->connect_ctx.port)
1861 c->self, c->connect_ctx.host, c->connect_ctx.port)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1861
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "channel %d: connected to %s port %d"
, c->self, c->connect_ctx.host, c->connect_ctx.port)
;
1862 channel_connect_ctx_free(&c->connect_ctx);
1863 c->type = SSH_CHANNEL_OPEN4;
1864 if (isopen) {
1865 /* no message necessary */
1866 } else {
1867 if ((r = sshpkt_start(ssh,
1868 SSH2_MSG_CHANNEL_OPEN_CONFIRMATION91)) != 0 ||
1869 (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
1870 (r = sshpkt_put_u32(ssh, c->self)) != 0 ||
1871 (r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||
1872 (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0 ||
1873 (r = sshpkt_send(ssh)) != 0)
1874 fatal_fr(r, "channel %i open confirm", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1874
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i open confirm"
, c->self)
;
1875 }
1876 } else {
1877 debug("channel %d: connection failed: %s",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1878
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "channel %d: connection failed: %s"
, c->self, strerror(err))
1878 c->self, strerror(err))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1878
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "channel %d: connection failed: %s"
, c->self, strerror(err))
;
1879 /* Try next address, if any */
1880 if ((sock = connect_next(&c->connect_ctx)) > 0) {
1881 close(c->sock);
1882 c->sock = c->rfd = c->wfd = sock;
1883 return;
1884 }
1885 /* Exhausted all addresses */
1886 error("connect_to %.100s port %d: failed.",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1887
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "connect_to %.100s port %d: failed."
, c->connect_ctx.host, c->connect_ctx.port)
1887 c->connect_ctx.host, c->connect_ctx.port)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1887
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "connect_to %.100s port %d: failed."
, c->connect_ctx.host, c->connect_ctx.port)
;
1888 channel_connect_ctx_free(&c->connect_ctx);
1889 if (isopen) {
1890 rdynamic_close(ssh, c);
1891 } else {
1892 if ((r = sshpkt_start(ssh,
1893 SSH2_MSG_CHANNEL_OPEN_FAILURE92)) != 0 ||
1894 (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
1895 (r = sshpkt_put_u32(ssh,
1896 SSH2_OPEN_CONNECT_FAILED2)) != 0 ||
1897 (r = sshpkt_put_cstring(ssh, strerror(err))) != 0 ||
1898 (r = sshpkt_put_cstring(ssh, "")) != 0 ||
1899 (r = sshpkt_send(ssh)) != 0)
1900 fatal_fr(r, "channel %i: failure", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1900
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i: failure", c
->self)
;
1901 chan_mark_dead(ssh, c);
1902 }
1903 }
1904}
1905
1906static int
1907channel_handle_rfd(struct ssh *ssh, Channel *c)
1908{
1909 char buf[CHAN_RBUF(16*1024)];
1910 ssize_t len;
1911 int r;
1912
1913 if ((c->io_ready & SSH_CHAN_IO_RFD0x01) == 0)
1914 return 1;
1915
1916 len = read(c->rfd, buf, sizeof(buf));
1917 if (len == -1 && (errno(*__errno()) == EINTR4 || errno(*__errno()) == EAGAIN35))
1918 return 1;
1919 if (len <= 0) {
1920 debug2("channel %d: read<=0 rfd %d len %zd",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1921
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: read<=0 rfd %d len %zd"
, c->self, c->rfd, len)
1921 c->self, c->rfd, len)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1921
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: read<=0 rfd %d len %zd"
, c->self, c->rfd, len)
;
1922 if (c->type != SSH_CHANNEL_OPEN4) {
1923 debug2("channel %d: not open", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1923
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: not open"
, c->self)
;
1924 chan_mark_dead(ssh, c);
1925 return -1;
1926 } else {
1927 chan_read_failed(ssh, c);
1928 }
1929 return -1;
1930 }
1931 if (c->input_filter != NULL((void *)0)) {
1932 if (c->input_filter(ssh, c, buf, len) == -1) {
1933 debug2("channel %d: filter stops", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1933
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: filter stops"
, c->self)
;
1934 chan_read_failed(ssh, c);
1935 }
1936 } else if (c->datagram) {
1937 if ((r = sshbuf_put_string(c->input, buf, len)) != 0)
1938 fatal_fr(r, "channel %i: put datagram", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1938
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i: put datagram"
, c->self)
;
1939 } else if ((r = sshbuf_put(c->input, buf, len)) != 0)
1940 fatal_fr(r, "channel %i: put data", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1940
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i: put data", c
->self)
;
1941 return 1;
1942}
1943
1944static int
1945channel_handle_wfd(struct ssh *ssh, Channel *c)
1946{
1947 struct termios tio;
1948 u_char *data = NULL((void *)0), *buf; /* XXX const; need filter API change */
1949 size_t dlen, olen = 0;
1950 int r, len;
1951
1952 if ((c->io_ready & SSH_CHAN_IO_WFD0x02) == 0)
1953 return 1;
1954 if (sshbuf_len(c->output) == 0)
1955 return 1;
1956
1957 /* Send buffered output data to the socket. */
1958 olen = sshbuf_len(c->output);
1959 if (c->output_filter != NULL((void *)0)) {
1960 if ((buf = c->output_filter(ssh, c, &data, &dlen)) == NULL((void *)0)) {
1961 debug2("channel %d: filter stops", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1961
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: filter stops"
, c->self)
;
1962 if (c->type != SSH_CHANNEL_OPEN4)
1963 chan_mark_dead(ssh, c);
1964 else
1965 chan_write_failed(ssh, c);
1966 return -1;
1967 }
1968 } else if (c->datagram) {
1969 if ((r = sshbuf_get_string(c->output, &data, &dlen)) != 0)
1970 fatal_fr(r, "channel %i: get datagram", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1970
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i: get datagram"
, c->self)
;
1971 buf = data;
1972 } else {
1973 buf = data = sshbuf_mutable_ptr(c->output);
1974 dlen = sshbuf_len(c->output);
1975 }
1976
1977 if (c->datagram) {
1978 /* ignore truncated writes, datagrams might get lost */
1979 len = write(c->wfd, buf, dlen);
1980 free(data);
1981 if (len == -1 && (errno(*__errno()) == EINTR4 || errno(*__errno()) == EAGAIN35))
1982 return 1;
1983 if (len <= 0)
1984 goto write_fail;
1985 goto out;
1986 }
1987
1988 len = write(c->wfd, buf, dlen);
1989 if (len == -1 && (errno(*__errno()) == EINTR4 || errno(*__errno()) == EAGAIN35))
1990 return 1;
1991 if (len <= 0) {
1992 write_fail:
1993 if (c->type != SSH_CHANNEL_OPEN4) {
1994 debug2("channel %d: not open", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 1994
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: not open"
, c->self)
;
1995 chan_mark_dead(ssh, c);
1996 return -1;
1997 } else {
1998 chan_write_failed(ssh, c);
1999 }
2000 return -1;
2001 }
2002 if (c->isatty && dlen >= 1 && buf[0] != '\r') {
2003 if (tcgetattr(c->wfd, &tio) == 0 &&
2004 !(tio.c_lflag & ECHO0x00000008) && (tio.c_lflag & ICANON0x00000100)) {
2005 /*
2006 * Simulate echo to reduce the impact of
2007 * traffic analysis. We need to match the
2008 * size of a SSH2_MSG_CHANNEL_DATA message
2009 * (4 byte channel id + buf)
2010 */
2011 if ((r = sshpkt_msg_ignore(ssh, 4+len)) != 0 ||
2012 (r = sshpkt_send(ssh)) != 0)
2013 fatal_fr(r, "channel %i: ignore", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2013
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i: ignore", c->
self)
;
2014 }
2015 }
2016 if ((r = sshbuf_consume(c->output, len)) != 0)
2017 fatal_fr(r, "channel %i: consume", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2017
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i: consume", c
->self)
;
2018 out:
2019 c->local_consumed += olen - sshbuf_len(c->output);
2020
2021 return 1;
2022}
2023
2024static int
2025channel_handle_efd_write(struct ssh *ssh, Channel *c)
2026{
2027 int r;
2028 ssize_t len;
2029
2030 if ((c->io_ready & SSH_CHAN_IO_EFD_W0x08) == 0)
2031 return 1;
2032 if (sshbuf_len(c->extended) == 0)
2033 return 1;
2034
2035 len = write(c->efd, sshbuf_ptr(c->extended),
2036 sshbuf_len(c->extended));
2037 debug2("channel %d: written %zd to efd %d", c->self, len, c->efd)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2037
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: written %zd to efd %d"
, c->self, len, c->efd)
;
2038 if (len == -1 && (errno(*__errno()) == EINTR4 || errno(*__errno()) == EAGAIN35))
2039 return 1;
2040 if (len <= 0) {
2041 debug2("channel %d: closing write-efd %d", c->self, c->efd)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2041
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: closing write-efd %d"
, c->self, c->efd)
;
2042 channel_close_fd(ssh, c, &c->efd);
2043 } else {
2044 if ((r = sshbuf_consume(c->extended, len)) != 0)
2045 fatal_fr(r, "channel %i: consume", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2045
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i: consume", c
->self)
;
2046 c->local_consumed += len;
2047 }
2048 return 1;
2049}
2050
2051static int
2052channel_handle_efd_read(struct ssh *ssh, Channel *c)
2053{
2054 char buf[CHAN_RBUF(16*1024)];
2055 int r;
2056 ssize_t len;
2057
2058 if ((c->io_ready & SSH_CHAN_IO_EFD_R0x04) == 0)
2059 return 1;
2060
2061 len = read(c->efd, buf, sizeof(buf));
2062 debug2("channel %d: read %zd from efd %d", c->self, len, c->efd)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2062
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: read %zd from efd %d"
, c->self, len, c->efd)
;
2063 if (len == -1 && (errno(*__errno()) == EINTR4 || errno(*__errno()) == EAGAIN35))
2064 return 1;
2065 if (len <= 0) {
2066 debug2("channel %d: closing read-efd %d", c->self, c->efd)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2066
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: closing read-efd %d"
, c->self, c->efd)
;
2067 channel_close_fd(ssh, c, &c->efd);
2068 } else if (c->extended_usage == CHAN_EXTENDED_IGNORE0)
2069 debug3("channel %d: discard efd", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2069
, 0, SYSLOG_LEVEL_DEBUG3, ((void *)0), "channel %d: discard efd"
, c->self)
;
2070 else if ((r = sshbuf_put(c->extended, buf, len)) != 0)
2071 fatal_fr(r, "channel %i: append", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2071
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i: append", c->
self)
;
2072 return 1;
2073}
2074
2075static int
2076channel_handle_efd(struct ssh *ssh, Channel *c)
2077{
2078 if (c->efd == -1)
2079 return 1;
2080
2081 /** XXX handle drain efd, too */
2082
2083 if (c->extended_usage == CHAN_EXTENDED_WRITE2)
2084 return channel_handle_efd_write(ssh, c);
2085 else if (c->extended_usage == CHAN_EXTENDED_READ1 ||
2086 c->extended_usage == CHAN_EXTENDED_IGNORE0)
2087 return channel_handle_efd_read(ssh, c);
2088
2089 return 1;
2090}
2091
2092static int
2093channel_check_window(struct ssh *ssh, Channel *c)
2094{
2095 int r;
2096
2097 if (c->type == SSH_CHANNEL_OPEN4 &&
2098 !(c->flags & (CHAN_CLOSE_SENT0x01|CHAN_CLOSE_RCVD0x02)) &&
2099 ((c->local_window_max - c->local_window >
2100 c->local_maxpacket*3) ||
2101 c->local_window < c->local_window_max/2) &&
2102 c->local_consumed > 0) {
2103 if (!c->have_remote_id)
2104 fatal_f("channel %d: no remote id", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2104
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "channel %d: no remote id"
, c->self)
;
2105 if ((r = sshpkt_start(ssh,
2106 SSH2_MSG_CHANNEL_WINDOW_ADJUST93)) != 0 ||
2107 (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
2108 (r = sshpkt_put_u32(ssh, c->local_consumed)) != 0 ||
2109 (r = sshpkt_send(ssh)) != 0) {
2110 fatal_fr(r, "channel %i", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2110
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i", c->self
)
;
2111 }
2112 debug2("channel %d: window %d sent adjust %d", c->self,sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2113
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: window %d sent adjust %d"
, c->self, c->local_window, c->local_consumed)
2113 c->local_window, c->local_consumed)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2113
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: window %d sent adjust %d"
, c->self, c->local_window, c->local_consumed)
;
2114 c->local_window += c->local_consumed;
2115 c->local_consumed = 0;
2116 }
2117 return 1;
2118}
2119
2120static void
2121channel_post_open(struct ssh *ssh, Channel *c)
2122{
2123 channel_handle_rfd(ssh, c);
2124 channel_handle_wfd(ssh, c);
2125 channel_handle_efd(ssh, c);
2126 channel_check_window(ssh, c);
2127}
2128
2129static u_int
2130read_mux(struct ssh *ssh, Channel *c, u_int need)
2131{
2132 char buf[CHAN_RBUF(16*1024)];
2133 ssize_t len;
2134 u_int rlen;
2135 int r;
2136
2137 if (sshbuf_len(c->input) < need) {
2138 rlen = need - sshbuf_len(c->input);
2139 len = read(c->rfd, buf, MINIMUM(rlen, CHAN_RBUF)(((rlen) < ((16*1024))) ? (rlen) : ((16*1024))));
2140 if (len == -1 && (errno(*__errno()) == EINTR4 || errno(*__errno()) == EAGAIN35))
2141 return sshbuf_len(c->input);
2142 if (len <= 0) {
2143 debug2("channel %d: ctl read<=0 rfd %d len %zd",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2144
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: ctl read<=0 rfd %d len %zd"
, c->self, c->rfd, len)
2144 c->self, c->rfd, len)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2144
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: ctl read<=0 rfd %d len %zd"
, c->self, c->rfd, len)
;
2145 chan_read_failed(ssh, c);
2146 return 0;
2147 } else if ((r = sshbuf_put(c->input, buf, len)) != 0)
2148 fatal_fr(r, "channel %i: append", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2148
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i: append", c->
self)
;
2149 }
2150 return sshbuf_len(c->input);
2151}
2152
2153static void
2154channel_post_mux_client_read(struct ssh *ssh, Channel *c)
2155{
2156 u_int need;
2157
2158 if ((c->io_ready & SSH_CHAN_IO_RFD0x01) == 0)
2159 return;
2160 if (c->istate != CHAN_INPUT_OPEN0 && c->istate != CHAN_INPUT_WAIT_DRAIN1)
2161 return;
2162 if (c->mux_pause)
2163 return;
2164
2165 /*
2166 * Don't not read past the precise end of packets to
2167 * avoid disrupting fd passing.
2168 */
2169 if (read_mux(ssh, c, 4) < 4) /* read header */
2170 return;
2171 /* XXX sshbuf_peek_u32 */
2172 need = PEEK_U32(sshbuf_ptr(c->input))(((u_int32_t)(((const u_char *)(sshbuf_ptr(c->input)))[0])
<< 24) | ((u_int32_t)(((const u_char *)(sshbuf_ptr(c->
input)))[1]) << 16) | ((u_int32_t)(((const u_char *)(sshbuf_ptr
(c->input)))[2]) << 8) | (u_int32_t)(((const u_char *
)(sshbuf_ptr(c->input)))[3]))
;
2173#define CHANNEL_MUX_MAX_PACKET(256 * 1024) (256 * 1024)
2174 if (need > CHANNEL_MUX_MAX_PACKET(256 * 1024)) {
2175 debug2("channel %d: packet too big %u > %u",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2176
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: packet too big %u > %u"
, c->self, (256 * 1024), need)
2176 c->self, CHANNEL_MUX_MAX_PACKET, need)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2176
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: packet too big %u > %u"
, c->self, (256 * 1024), need)
;
2177 chan_rcvd_oclose(ssh, c);
2178 return;
2179 }
2180 if (read_mux(ssh, c, need + 4) < need + 4) /* read body */
2181 return;
2182 if (c->mux_rcb(ssh, c) != 0) {
2183 debug("channel %d: mux_rcb failed", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2183
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "channel %d: mux_rcb failed"
, c->self)
;
2184 chan_mark_dead(ssh, c);
2185 return;
2186 }
2187}
2188
2189static void
2190channel_post_mux_client_write(struct ssh *ssh, Channel *c)
2191{
2192 ssize_t len;
2193 int r;
2194
2195 if ((c->io_ready & SSH_CHAN_IO_WFD0x02) == 0)
2196 return;
2197 if (sshbuf_len(c->output) == 0)
2198 return;
2199
2200 len = write(c->wfd, sshbuf_ptr(c->output), sshbuf_len(c->output));
2201 if (len == -1 && (errno(*__errno()) == EINTR4 || errno(*__errno()) == EAGAIN35))
2202 return;
2203 if (len <= 0) {
2204 chan_mark_dead(ssh, c);
2205 return;
2206 }
2207 if ((r = sshbuf_consume(c->output, len)) != 0)
2208 fatal_fr(r, "channel %i: consume", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2208
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i: consume", c
->self)
;
2209}
2210
2211static void
2212channel_post_mux_client(struct ssh *ssh, Channel *c)
2213{
2214 channel_post_mux_client_read(ssh, c);
2215 channel_post_mux_client_write(ssh, c);
2216}
2217
2218static void
2219channel_post_mux_listener(struct ssh *ssh, Channel *c)
2220{
2221 Channel *nc;
2222 struct sockaddr_storage addr;
2223 socklen_t addrlen;
2224 int newsock;
2225 uid_t euid;
2226 gid_t egid;
2227
2228 if ((c->io_ready & SSH_CHAN_IO_SOCK_R0x10) == 0)
2229 return;
2230
2231 debug("multiplexing control connection")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2231
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "multiplexing control connection"
)
;
2232
2233 /*
2234 * Accept connection on control socket
2235 */
2236 memset(&addr, 0, sizeof(addr));
2237 addrlen = sizeof(addr);
2238 if ((newsock = accept(c->sock, (struct sockaddr*)&addr,
2239 &addrlen)) == -1) {
2240 error_f("accept: %s", strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2240
, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "accept: %s", strerror(
(*__errno())))
;
2241 if (errno(*__errno()) == EMFILE24 || errno(*__errno()) == ENFILE23)
2242 c->notbefore = monotime() + 1;
2243 return;
2244 }
2245
2246 if (getpeereid(newsock, &euid, &egid) == -1) {
2247 error_f("getpeereid failed: %s", strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2247
, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "getpeereid failed: %s"
, strerror((*__errno())))
;
2248 close(newsock);
2249 return;
2250 }
2251 if ((euid != 0) && (getuid() != euid)) {
2252 error("multiplex uid mismatch: peer euid %u != uid %u",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2253
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "multiplex uid mismatch: peer euid %u != uid %u"
, (u_int)euid, (u_int)getuid())
2253 (u_int)euid, (u_int)getuid())sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2253
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "multiplex uid mismatch: peer euid %u != uid %u"
, (u_int)euid, (u_int)getuid())
;
2254 close(newsock);
2255 return;
2256 }
2257 nc = channel_new(ssh, "multiplex client", SSH_CHANNEL_MUX_CLIENT16,
2258 newsock, newsock, -1, c->local_window_max,
2259 c->local_maxpacket, 0, "mux-control", 1);
2260 nc->mux_rcb = c->mux_rcb;
2261 debug3_f("new mux channel %d fd %d", nc->self, nc->sock)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2261
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "new mux channel %d fd %d"
, nc->self, nc->sock)
;
2262 /* establish state */
2263 nc->mux_rcb(ssh, nc);
2264 /* mux state transitions must not elicit protocol messages */
2265 nc->flags |= CHAN_LOCAL0x10;
2266}
2267
2268static void
2269channel_handler_init(struct ssh_channels *sc)
2270{
2271 chan_fn **pre, **post;
2272
2273 if ((pre = calloc(SSH_CHANNEL_MAX_TYPE23, sizeof(*pre))) == NULL((void *)0) ||
2274 (post = calloc(SSH_CHANNEL_MAX_TYPE23, sizeof(*post))) == NULL((void *)0))
2275 fatal_f("allocation failed")sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2275
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "allocation failed")
;
2276
2277 pre[SSH_CHANNEL_OPEN4] = &channel_pre_open;
2278 pre[SSH_CHANNEL_X11_OPEN7] = &channel_pre_x11_open;
2279 pre[SSH_CHANNEL_PORT_LISTENER2] = &channel_pre_listener;
2280 pre[SSH_CHANNEL_RPORT_LISTENER11] = &channel_pre_listener;
2281 pre[SSH_CHANNEL_UNIX_LISTENER18] = &channel_pre_listener;
2282 pre[SSH_CHANNEL_RUNIX_LISTENER19] = &channel_pre_listener;
2283 pre[SSH_CHANNEL_X11_LISTENER1] = &channel_pre_listener;
2284 pre[SSH_CHANNEL_AUTH_SOCKET6] = &channel_pre_listener;
2285 pre[SSH_CHANNEL_CONNECTING12] = &channel_pre_connecting;
2286 pre[SSH_CHANNEL_DYNAMIC13] = &channel_pre_dynamic;
2287 pre[SSH_CHANNEL_RDYNAMIC_FINISH22] = &channel_pre_connecting;
2288 pre[SSH_CHANNEL_MUX_LISTENER15] = &channel_pre_listener;
2289 pre[SSH_CHANNEL_MUX_CLIENT16] = &channel_pre_mux_client;
2290
2291 post[SSH_CHANNEL_OPEN4] = &channel_post_open;
2292 post[SSH_CHANNEL_PORT_LISTENER2] = &channel_post_port_listener;
2293 post[SSH_CHANNEL_RPORT_LISTENER11] = &channel_post_port_listener;
2294 post[SSH_CHANNEL_UNIX_LISTENER18] = &channel_post_port_listener;
2295 post[SSH_CHANNEL_RUNIX_LISTENER19] = &channel_post_port_listener;
2296 post[SSH_CHANNEL_X11_LISTENER1] = &channel_post_x11_listener;
2297 post[SSH_CHANNEL_AUTH_SOCKET6] = &channel_post_auth_listener;
2298 post[SSH_CHANNEL_CONNECTING12] = &channel_post_connecting;
2299 post[SSH_CHANNEL_DYNAMIC13] = &channel_post_open;
2300 post[SSH_CHANNEL_RDYNAMIC_FINISH22] = &channel_post_connecting;
2301 post[SSH_CHANNEL_MUX_LISTENER15] = &channel_post_mux_listener;
2302 post[SSH_CHANNEL_MUX_CLIENT16] = &channel_post_mux_client;
2303
2304 sc->channel_pre = pre;
2305 sc->channel_post = post;
2306}
2307
2308/* gc dead channels */
2309static void
2310channel_garbage_collect(struct ssh *ssh, Channel *c)
2311{
2312 if (c == NULL((void *)0))
2313 return;
2314 if (c->detach_user != NULL((void *)0)) {
2315 if (!chan_is_dead(ssh, c, c->detach_close))
2316 return;
2317
2318 debug2("channel %d: gc: notify user", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2318
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: gc: notify user"
, c->self)
;
2319 c->detach_user(ssh, c->self, NULL((void *)0));
2320 /* if we still have a callback */
2321 if (c->detach_user != NULL((void *)0))
2322 return;
2323 debug2("channel %d: gc: user detached", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2323
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: gc: user detached"
, c->self)
;
2324 }
2325 if (!chan_is_dead(ssh, c, 1))
2326 return;
2327 debug2("channel %d: garbage collecting", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2327
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: garbage collecting"
, c->self)
;
2328 channel_free(ssh, c);
2329}
2330
2331enum channel_table { CHAN_PRE, CHAN_POST };
2332
2333static void
2334channel_handler(struct ssh *ssh, int table, time_t *unpause_secs)
2335{
2336 struct ssh_channels *sc = ssh->chanctxt;
2337 chan_fn **ftab = table == CHAN_PRE ? sc->channel_pre : sc->channel_post;
2338 u_int i, oalloc;
2339 Channel *c;
2340 time_t now;
2341
2342 now = monotime();
2343 if (unpause_secs != NULL((void *)0))
2344 *unpause_secs = 0;
2345 for (i = 0, oalloc = sc->channels_alloc; i < oalloc; i++) {
2346 c = sc->channels[i];
2347 if (c == NULL((void *)0))
2348 continue;
2349 if (c->delayed) {
2350 if (table == CHAN_PRE)
2351 c->delayed = 0;
2352 else
2353 continue;
2354 }
2355 if (ftab[c->type] != NULL((void *)0)) {
2356 /*
2357 * Run handlers that are not paused.
2358 */
2359 if (c->notbefore <= now)
2360 (*ftab[c->type])(ssh, c);
2361 else if (unpause_secs != NULL((void *)0)) {
2362 /*
2363 * Collect the time that the earliest
2364 * channel comes off pause.
2365 */
2366 debug3_f("chan %d: skip for %d more "sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2368
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "chan %d: skip for %d more "
"seconds", c->self, (int)(c->notbefore - now))
2367 "seconds", c->self,sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2368
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "chan %d: skip for %d more "
"seconds", c->self, (int)(c->notbefore - now))
2368 (int)(c->notbefore - now))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2368
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "chan %d: skip for %d more "
"seconds", c->self, (int)(c->notbefore - now))
;
2369 if (*unpause_secs == 0 ||
2370 (c->notbefore - now) < *unpause_secs)
2371 *unpause_secs = c->notbefore - now;
2372 }
2373 }
2374 channel_garbage_collect(ssh, c);
2375 }
2376 if (unpause_secs != NULL((void *)0) && *unpause_secs != 0)
2377 debug3_f("first channel unpauses in %d seconds",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2378
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "first channel unpauses in %d seconds"
, (int)*unpause_secs)
2378 (int)*unpause_secs)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2378
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "first channel unpauses in %d seconds"
, (int)*unpause_secs)
;
2379}
2380
2381/*
2382 * Create sockets before preparing IO.
2383 * This is necessary for things that need to happen after reading
2384 * the network-input but need to be completed before IO event setup, e.g.
2385 * because they may create new channels.
2386 */
2387static void
2388channel_before_prepare_io(struct ssh *ssh)
2389{
2390 struct ssh_channels *sc = ssh->chanctxt;
2391 Channel *c;
2392 u_int i, oalloc;
2393
2394 for (i = 0, oalloc = sc->channels_alloc; i < oalloc; i++) {
2395 c = sc->channels[i];
2396 if (c == NULL((void *)0))
2397 continue;
2398 if (c->type == SSH_CHANNEL_RDYNAMIC_OPEN21)
2399 channel_before_prepare_io_rdynamic(ssh, c);
2400 }
2401}
2402
2403static void
2404dump_channel_poll(const char *func, const char *what, Channel *c,
2405 u_int pollfd_offset, struct pollfd *pfd)
2406{
2407#ifdef DEBUG_CHANNEL_POLL
2408 debug3_f("channel %d: rfd r%d w%d e%d s%d "sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2411
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "channel %d: rfd r%d w%d e%d s%d "
"pfd[%u].fd=%d want 0x%02x ev 0x%02x ready 0x%02x rev 0x%02x"
, c->self, c->rfd, c->wfd, c->efd, c->sock, pollfd_offset
, pfd->fd, c->io_want, pfd->events, c->io_ready, pfd
->revents)
2409 "pfd[%u].fd=%d want 0x%02x ev 0x%02x ready 0x%02x rev 0x%02x",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2411
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "channel %d: rfd r%d w%d e%d s%d "
"pfd[%u].fd=%d want 0x%02x ev 0x%02x ready 0x%02x rev 0x%02x"
, c->self, c->rfd, c->wfd, c->efd, c->sock, pollfd_offset
, pfd->fd, c->io_want, pfd->events, c->io_ready, pfd
->revents)
2410 c->self, c->rfd, c->wfd, c->efd, c->sock, pollfd_offset, pfd->fd,sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2411
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "channel %d: rfd r%d w%d e%d s%d "
"pfd[%u].fd=%d want 0x%02x ev 0x%02x ready 0x%02x rev 0x%02x"
, c->self, c->rfd, c->wfd, c->efd, c->sock, pollfd_offset
, pfd->fd, c->io_want, pfd->events, c->io_ready, pfd
->revents)
2411 c->io_want, pfd->events, c->io_ready, pfd->revents)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2411
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "channel %d: rfd r%d w%d e%d s%d "
"pfd[%u].fd=%d want 0x%02x ev 0x%02x ready 0x%02x rev 0x%02x"
, c->self, c->rfd, c->wfd, c->efd, c->sock, pollfd_offset
, pfd->fd, c->io_want, pfd->events, c->io_ready, pfd
->revents)
;
2412#endif
2413}
2414
2415/* Prepare pollfd entries for a single channel */
2416static void
2417channel_prepare_pollfd(Channel *c, u_int *next_pollfd,
2418 struct pollfd *pfd, u_int npfd)
2419{
2420 u_int p = *next_pollfd;
2421
2422 if (c == NULL((void *)0))
2423 return;
2424 if (p + 4 > npfd) {
2425 /* Shouldn't happen */
2426 fatal_f("channel %d: bad pfd offset %u (max %u)",sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2427
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "channel %d: bad pfd offset %u (max %u)"
, c->self, p, npfd)
2427 c->self, p, npfd)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2427
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "channel %d: bad pfd offset %u (max %u)"
, c->self, p, npfd)
;
2428 }
2429 c->pollfd_offset = -1;
2430 /*
2431 * prepare c->rfd
2432 *
2433 * This is a special case, since c->rfd might be the same as
2434 * c->wfd, c->efd and/or c->sock. Handle those here if they want
2435 * IO too.
2436 */
2437 if (c->rfd != -1) {
2438 if (c->pollfd_offset == -1)
2439 c->pollfd_offset = p;
2440 pfd[p].fd = c->rfd;
2441 pfd[p].events = 0;
2442 if ((c->io_want & SSH_CHAN_IO_RFD0x01) != 0)
2443 pfd[p].events |= POLLIN0x0001;
2444 /* rfd == wfd */
2445 if (c->wfd == c->rfd &&
2446 (c->io_want & SSH_CHAN_IO_WFD0x02) != 0)
2447 pfd[p].events |= POLLOUT0x0004;
2448 /* rfd == efd */
2449 if (c->efd == c->rfd &&
2450 (c->io_want & SSH_CHAN_IO_EFD_R0x04) != 0)
2451 pfd[p].events |= POLLIN0x0001;
2452 if (c->efd == c->rfd &&
2453 (c->io_want & SSH_CHAN_IO_EFD_W0x08) != 0)
2454 pfd[p].events |= POLLOUT0x0004;
2455 /* rfd == sock */
2456 if (c->sock == c->rfd &&
2457 (c->io_want & SSH_CHAN_IO_SOCK_R0x10) != 0)
2458 pfd[p].events |= POLLIN0x0001;
2459 if (c->sock == c->rfd &&
2460 (c->io_want & SSH_CHAN_IO_SOCK_W0x20) != 0)
2461 pfd[p].events |= POLLOUT0x0004;
2462 dump_channel_poll(__func__, "rfd", c, p, &pfd[p]);
2463 p++;
2464 }
2465 /* prepare c->wfd (if not already handled above) */
2466 if (c->wfd != -1 && c->rfd != c->wfd) {
2467 if (c->pollfd_offset == -1)
2468 c->pollfd_offset = p;
2469 pfd[p].fd = c->wfd;
2470 pfd[p].events = 0;
2471 if ((c->io_want & SSH_CHAN_IO_WFD0x02) != 0)
2472 pfd[p].events = POLLOUT0x0004;
2473 dump_channel_poll(__func__, "wfd", c, p, &pfd[p]);
2474 p++;
2475 }
2476 /* prepare c->efd (if not already handled above) */
2477 if (c->efd != -1 && c->rfd != c->efd) {
2478 if (c->pollfd_offset == -1)
2479 c->pollfd_offset = p;
2480 pfd[p].fd = c->efd;
2481 pfd[p].events = 0;
2482 if ((c->io_want & SSH_CHAN_IO_EFD_R0x04) != 0)
2483 pfd[p].events |= POLLIN0x0001;
2484 if ((c->io_want & SSH_CHAN_IO_EFD_W0x08) != 0)
2485 pfd[p].events |= POLLOUT0x0004;
2486 dump_channel_poll(__func__, "efd", c, p, &pfd[p]);
2487 p++;
2488 }
2489 /* prepare c->sock (if not already handled above) */
2490 if (c->sock != -1 && c->rfd != c->sock) {
2491 if (c->pollfd_offset == -1)
2492 c->pollfd_offset = p;
2493 pfd[p].fd = c->sock;
2494 pfd[p].events = 0;
2495 if ((c->io_want & SSH_CHAN_IO_SOCK_R0x10) != 0)
2496 pfd[p].events |= POLLIN0x0001;
2497 if ((c->io_want & SSH_CHAN_IO_SOCK_W0x20) != 0)
2498 pfd[p].events |= POLLOUT0x0004;
2499 dump_channel_poll(__func__, "sock", c, p, &pfd[p]);
2500 p++;
2501 }
2502 *next_pollfd = p;
2503}
2504
2505/* * Allocate/prepare poll structure */
2506void
2507channel_prepare_poll(struct ssh *ssh, struct pollfd **pfdp, u_int *npfd_allocp,
2508 u_int *npfd_activep, u_int npfd_reserved, time_t *minwait_secs)
2509{
2510 struct ssh_channels *sc = ssh->chanctxt;
2511 u_int i, oalloc, p, npfd = npfd_reserved;
2512
2513 channel_before_prepare_io(ssh); /* might create a new channel */
2514
2515 /* Allocate 4x pollfd for each channel (rfd, wfd, efd, sock) */
2516 if (sc->channels_alloc >= (INT_MAX2147483647 / 4) - npfd_reserved)
2517 fatal_f("too many channels")sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2517
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "too many channels")
; /* shouldn't happen */
2518 if (!ssh_packet_is_rekeying(ssh))
2519 npfd += sc->channels_alloc * 4;
2520 if (npfd > *npfd_allocp) {
2521 *pfdp = xrecallocarray(*pfdp, *npfd_allocp,
2522 npfd, sizeof(**pfdp));
2523 *npfd_allocp = npfd;
2524 }
2525 *npfd_activep = npfd_reserved;
2526 if (ssh_packet_is_rekeying(ssh))
2527 return;
2528
2529 oalloc = sc->channels_alloc;
2530
2531 channel_handler(ssh, CHAN_PRE, minwait_secs);
2532
2533 if (oalloc != sc->channels_alloc) {
2534 /* shouldn't happen */
2535 fatal_f("channels_alloc changed during CHAN_PRE "sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2536
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "channels_alloc changed during CHAN_PRE "
"(was %u, now %u)", oalloc, sc->channels_alloc)
2536 "(was %u, now %u)", oalloc, sc->channels_alloc)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2536
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "channels_alloc changed during CHAN_PRE "
"(was %u, now %u)", oalloc, sc->channels_alloc)
;
2537 }
2538
2539 /* Prepare pollfd */
2540 p = npfd_reserved;
2541 for (i = 0; i < sc->channels_alloc; i++)
2542 channel_prepare_pollfd(sc->channels[i], &p, *pfdp, npfd);
2543 *npfd_activep = p;
2544}
2545
2546static void
2547fd_ready(Channel *c, u_int p, struct pollfd *pfds, int fd,
2548 const char *what, u_int revents_mask, u_int ready)
2549{
2550 struct pollfd *pfd = &pfds[p];
2551
2552 if (fd == -1)
2553 return;
2554 dump_channel_poll(__func__, what, c, p, pfd);
2555 if (pfd->fd != fd) {
2556 fatal("channel %d: inconsistent %s fd=%d pollfd[%u].fd %d "sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2558
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "channel %d: inconsistent %s fd=%d pollfd[%u].fd %d "
"r%d w%d e%d s%d", c->self, what, fd, p, pfd->fd, c->
rfd, c->wfd, c->efd, c->sock)
2557 "r%d w%d e%d s%d", c->self, what, fd, p, pfd->fd,sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2558
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "channel %d: inconsistent %s fd=%d pollfd[%u].fd %d "
"r%d w%d e%d s%d", c->self, what, fd, p, pfd->fd, c->
rfd, c->wfd, c->efd, c->sock)
2558 c->rfd, c->wfd, c->efd, c->sock)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2558
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "channel %d: inconsistent %s fd=%d pollfd[%u].fd %d "
"r%d w%d e%d s%d", c->self, what, fd, p, pfd->fd, c->
rfd, c->wfd, c->efd, c->sock)
;
2559 }
2560 if ((pfd->revents & POLLNVAL0x0020) != 0) {
2561 fatal("channel %d: invalid %s pollfd[%u].fd %d r%d w%d e%d s%d",sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2562
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "channel %d: invalid %s pollfd[%u].fd %d r%d w%d e%d s%d"
, c->self, what, p, pfd->fd, c->rfd, c->wfd, c->
efd, c->sock)
2562 c->self, what, p, pfd->fd, c->rfd, c->wfd, c->efd, c->sock)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2562
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "channel %d: invalid %s pollfd[%u].fd %d r%d w%d e%d s%d"
, c->self, what, p, pfd->fd, c->rfd, c->wfd, c->
efd, c->sock)
;
2563 }
2564 if ((pfd->revents & (revents_mask|POLLHUP0x0010|POLLERR0x0008)) != 0)
2565 c->io_ready |= ready & c->io_want;
2566}
2567
2568/*
2569 * After poll, perform any appropriate operations for channels which have
2570 * events pending.
2571 */
2572void
2573channel_after_poll(struct ssh *ssh, struct pollfd *pfd, u_int npfd)
2574{
2575 struct ssh_channels *sc = ssh->chanctxt;
2576 u_int i, p;
2577 Channel *c;
2578
2579#ifdef DEBUG_CHANNEL_POLL
2580 for (p = 0; p < npfd; p++) {
2581 if (pfd[p].revents == 0)
2582 continue;
2583 debug_f("pfd[%u].fd %d rev 0x%04x",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2584
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "pfd[%u].fd %d rev 0x%04x"
, p, pfd[p].fd, pfd[p].revents)
2584 p, pfd[p].fd, pfd[p].revents)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2584
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "pfd[%u].fd %d rev 0x%04x"
, p, pfd[p].fd, pfd[p].revents)
;
2585 }
2586#endif
2587
2588 /* Convert pollfd into c->io_ready */
2589 for (i = 0; i < sc->channels_alloc; i++) {
2590 c = sc->channels[i];
2591 if (c == NULL((void *)0) || c->pollfd_offset < 0)
2592 continue;
2593 if ((u_int)c->pollfd_offset >= npfd) {
2594 /* shouldn't happen */
2595 fatal_f("channel %d: (before) bad pfd %u (max %u)",sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2596
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "channel %d: (before) bad pfd %u (max %u)"
, c->self, c->pollfd_offset, npfd)
2596 c->self, c->pollfd_offset, npfd)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2596
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "channel %d: (before) bad pfd %u (max %u)"
, c->self, c->pollfd_offset, npfd)
;
2597 }
2598 /* if rfd is shared with efd/sock then wfd should be too */
2599 if (c->rfd != -1 && c->wfd != -1 && c->rfd != c->wfd &&
2600 (c->rfd == c->efd || c->rfd == c->sock)) {
2601 /* Shouldn't happen */
2602 fatal_f("channel %d: unexpected fds r%d w%d e%d s%d",sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2603
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "channel %d: unexpected fds r%d w%d e%d s%d"
, c->self, c->rfd, c->wfd, c->efd, c->sock)
2603 c->self, c->rfd, c->wfd, c->efd, c->sock)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2603
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "channel %d: unexpected fds r%d w%d e%d s%d"
, c->self, c->rfd, c->wfd, c->efd, c->sock)
;
2604 }
2605 c->io_ready = 0;
2606 p = c->pollfd_offset;
2607 /* rfd, potentially shared with wfd, efd and sock */
2608 if (c->rfd != -1) {
2609 fd_ready(c, p, pfd, c->rfd, "rfd", POLLIN0x0001,
2610 SSH_CHAN_IO_RFD0x01);
2611 if (c->rfd == c->wfd) {
2612 fd_ready(c, p, pfd, c->wfd, "wfd/r", POLLOUT0x0004,
2613 SSH_CHAN_IO_WFD0x02);
2614 }
2615 if (c->rfd == c->efd) {
2616 fd_ready(c, p, pfd, c->efd, "efdr/r", POLLIN0x0001,
2617 SSH_CHAN_IO_EFD_R0x04);
2618 fd_ready(c, p, pfd, c->efd, "efdw/r", POLLOUT0x0004,
2619 SSH_CHAN_IO_EFD_W0x08);
2620 }
2621 if (c->rfd == c->sock) {
2622 fd_ready(c, p, pfd, c->sock, "sockr/r", POLLIN0x0001,
2623 SSH_CHAN_IO_SOCK_R0x10);
2624 fd_ready(c, p, pfd, c->sock, "sockw/r", POLLOUT0x0004,
2625 SSH_CHAN_IO_SOCK_W0x20);
2626 }
2627 p++;
2628 }
2629 /* wfd */
2630 if (c->wfd != -1 && c->wfd != c->rfd) {
2631 fd_ready(c, p, pfd, c->wfd, "wfd", POLLOUT0x0004,
2632 SSH_CHAN_IO_WFD0x02);
2633 p++;
2634 }
2635 /* efd */
2636 if (c->efd != -1 && c->efd != c->rfd) {
2637 fd_ready(c, p, pfd, c->efd, "efdr", POLLIN0x0001,
2638 SSH_CHAN_IO_EFD_R0x04);
2639 fd_ready(c, p, pfd, c->efd, "efdw", POLLOUT0x0004,
2640 SSH_CHAN_IO_EFD_W0x08);
2641 p++;
2642 }
2643 /* sock */
2644 if (c->sock != -1 && c->sock != c->rfd) {
2645 fd_ready(c, p, pfd, c->sock, "sockr", POLLIN0x0001,
2646 SSH_CHAN_IO_SOCK_R0x10);
2647 fd_ready(c, p, pfd, c->sock, "sockw", POLLOUT0x0004,
2648 SSH_CHAN_IO_SOCK_W0x20);
2649 p++;
2650 }
2651
2652 if (p > npfd) {
2653 /* shouldn't happen */
2654 fatal_f("channel %d: (after) bad pfd %u (max %u)",sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2655
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "channel %d: (after) bad pfd %u (max %u)"
, c->self, c->pollfd_offset, npfd)
2655 c->self, c->pollfd_offset, npfd)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2655
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "channel %d: (after) bad pfd %u (max %u)"
, c->self, c->pollfd_offset, npfd)
;
2656 }
2657 }
2658 channel_handler(ssh, CHAN_POST, NULL((void *)0));
2659}
2660
2661/*
2662 * Enqueue data for channels with open or draining c->input.
2663 */
2664static void
2665channel_output_poll_input_open(struct ssh *ssh, Channel *c)
2666{
2667 size_t len, plen;
2668 const u_char *pkt;
2669 int r;
2670
2671 if ((len = sshbuf_len(c->input)) == 0) {
2672 if (c->istate == CHAN_INPUT_WAIT_DRAIN1) {
2673 /*
2674 * input-buffer is empty and read-socket shutdown:
2675 * tell peer, that we will not send more data:
2676 * send IEOF.
2677 * hack for extended data: delay EOF if EFD still
2678 * in use.
2679 */
2680 if (CHANNEL_EFD_INPUT_ACTIVE(c)(c->extended_usage == 1 && (c->efd != -1 || sshbuf_len
(c->extended) > 0))
)
2681 debug2("channel %d: "sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2683
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: " "ibuf_empty delayed efd %d/(%zu)"
, c->self, c->efd, sshbuf_len(c->extended))
2682 "ibuf_empty delayed efd %d/(%zu)",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2683
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: " "ibuf_empty delayed efd %d/(%zu)"
, c->self, c->efd, sshbuf_len(c->extended))
2683 c->self, c->efd, sshbuf_len(c->extended))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2683
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: " "ibuf_empty delayed efd %d/(%zu)"
, c->self, c->efd, sshbuf_len(c->extended))
;
2684 else
2685 chan_ibuf_empty(ssh, c);
2686 }
2687 return;
2688 }
2689
2690 if (!c->have_remote_id)
2691 fatal_f("channel %d: no remote id", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2691
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "channel %d: no remote id"
, c->self)
;
2692
2693 if (c->datagram) {
2694 /* Check datagram will fit; drop if not */
2695 if ((r = sshbuf_get_string_direct(c->input, &pkt, &plen)) != 0)
2696 fatal_fr(r, "channel %i: get datagram", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2696
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i: get datagram"
, c->self)
;
2697 /*
2698 * XXX this does tail-drop on the datagram queue which is
2699 * usually suboptimal compared to head-drop. Better to have
2700 * backpressure at read time? (i.e. read + discard)
2701 */
2702 if (plen > c->remote_window || plen > c->remote_maxpacket) {
2703 debug("channel %d: datagram too big", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2703
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "channel %d: datagram too big"
, c->self)
;
2704 return;
2705 }
2706 /* Enqueue it */
2707 if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA94)) != 0 ||
2708 (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
2709 (r = sshpkt_put_string(ssh, pkt, plen)) != 0 ||
2710 (r = sshpkt_send(ssh)) != 0)
2711 fatal_fr(r, "channel %i: send datagram", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2711
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i: send datagram"
, c->self)
;
2712 c->remote_window -= plen;
2713 return;
2714 }
2715
2716 /* Enqueue packet for buffered data. */
2717 if (len > c->remote_window)
2718 len = c->remote_window;
2719 if (len > c->remote_maxpacket)
2720 len = c->remote_maxpacket;
2721 if (len == 0)
2722 return;
2723 if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA94)) != 0 ||
2724 (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
2725 (r = sshpkt_put_string(ssh, sshbuf_ptr(c->input), len)) != 0 ||
2726 (r = sshpkt_send(ssh)) != 0)
2727 fatal_fr(r, "channel %i: send data", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2727
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i: send data",
c->self)
;
2728 if ((r = sshbuf_consume(c->input, len)) != 0)
2729 fatal_fr(r, "channel %i: consume", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2729
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i: consume", c
->self)
;
2730 c->remote_window -= len;
2731}
2732
2733/*
2734 * Enqueue data for channels with open c->extended in read mode.
2735 */
2736static void
2737channel_output_poll_extended_read(struct ssh *ssh, Channel *c)
2738{
2739 size_t len;
2740 int r;
2741
2742 if ((len = sshbuf_len(c->extended)) == 0)
2743 return;
2744
2745 debug2("channel %d: rwin %u elen %zu euse %d", c->self,sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2746
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: rwin %u elen %zu euse %d"
, c->self, c->remote_window, sshbuf_len(c->extended)
, c->extended_usage)
2746 c->remote_window, sshbuf_len(c->extended), c->extended_usage)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2746
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: rwin %u elen %zu euse %d"
, c->self, c->remote_window, sshbuf_len(c->extended)
, c->extended_usage)
;
2747 if (len > c->remote_window)
2748 len = c->remote_window;
2749 if (len > c->remote_maxpacket)
2750 len = c->remote_maxpacket;
2751 if (len == 0)
2752 return;
2753 if (!c->have_remote_id)
2754 fatal_f("channel %d: no remote id", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2754
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "channel %d: no remote id"
, c->self)
;
2755 if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_EXTENDED_DATA95)) != 0 ||
2756 (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
2757 (r = sshpkt_put_u32(ssh, SSH2_EXTENDED_DATA_STDERR1)) != 0 ||
2758 (r = sshpkt_put_string(ssh, sshbuf_ptr(c->extended), len)) != 0 ||
2759 (r = sshpkt_send(ssh)) != 0)
2760 fatal_fr(r, "channel %i: data", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2760
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i: data", c->
self)
;
2761 if ((r = sshbuf_consume(c->extended, len)) != 0)
2762 fatal_fr(r, "channel %i: consume", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2762
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i: consume", c
->self)
;
2763 c->remote_window -= len;
2764 debug2("channel %d: sent ext data %zu", c->self, len)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2764
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: sent ext data %zu"
, c->self, len)
;
2765}
2766
2767/* If there is data to send to the connection, enqueue some of it now. */
2768void
2769channel_output_poll(struct ssh *ssh)
2770{
2771 struct ssh_channels *sc = ssh->chanctxt;
2772 Channel *c;
2773 u_int i;
2774
2775 for (i = 0; i < sc->channels_alloc; i++) {
2776 c = sc->channels[i];
2777 if (c == NULL((void *)0))
2778 continue;
2779
2780 /*
2781 * We are only interested in channels that can have buffered
2782 * incoming data.
2783 */
2784 if (c->type != SSH_CHANNEL_OPEN4)
2785 continue;
2786 if ((c->flags & (CHAN_CLOSE_SENT0x01|CHAN_CLOSE_RCVD0x02))) {
2787 /* XXX is this true? */
2788 debug3("channel %d: will not send data after close",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2789
, 0, SYSLOG_LEVEL_DEBUG3, ((void *)0), "channel %d: will not send data after close"
, c->self)
2789 c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2789
, 0, SYSLOG_LEVEL_DEBUG3, ((void *)0), "channel %d: will not send data after close"
, c->self)
;
2790 continue;
2791 }
2792
2793 /* Get the amount of buffered data for this channel. */
2794 if (c->istate == CHAN_INPUT_OPEN0 ||
2795 c->istate == CHAN_INPUT_WAIT_DRAIN1)
2796 channel_output_poll_input_open(ssh, c);
2797 /* Send extended data, i.e. stderr */
2798 if (!(c->flags & CHAN_EOF_SENT0x04) &&
2799 c->extended_usage == CHAN_EXTENDED_READ1)
2800 channel_output_poll_extended_read(ssh, c);
2801 }
2802}
2803
2804/* -- mux proxy support */
2805
2806/*
2807 * When multiplexing channel messages for mux clients we have to deal
2808 * with downstream messages from the mux client and upstream messages
2809 * from the ssh server:
2810 * 1) Handling downstream messages is straightforward and happens
2811 * in channel_proxy_downstream():
2812 * - We forward all messages (mostly) unmodified to the server.
2813 * - However, in order to route messages from upstream to the correct
2814 * downstream client, we have to replace the channel IDs used by the
2815 * mux clients with a unique channel ID because the mux clients might
2816 * use conflicting channel IDs.
2817 * - so we inspect and change both SSH2_MSG_CHANNEL_OPEN and
2818 * SSH2_MSG_CHANNEL_OPEN_CONFIRMATION messages, create a local
2819 * SSH_CHANNEL_MUX_PROXY channel and replace the mux clients ID
2820 * with the newly allocated channel ID.
2821 * 2) Upstream messages are received by matching SSH_CHANNEL_MUX_PROXY
2822 * channels and processed by channel_proxy_upstream(). The local channel ID
2823 * is then translated back to the original mux client ID.
2824 * 3) In both cases we need to keep track of matching SSH2_MSG_CHANNEL_CLOSE
2825 * messages so we can clean up SSH_CHANNEL_MUX_PROXY channels.
2826 * 4) The SSH_CHANNEL_MUX_PROXY channels also need to closed when the
2827 * downstream mux client are removed.
2828 * 5) Handling SSH2_MSG_CHANNEL_OPEN messages from the upstream server
2829 * requires more work, because they are not addressed to a specific
2830 * channel. E.g. client_request_forwarded_tcpip() needs to figure
2831 * out whether the request is addressed to the local client or a
2832 * specific downstream client based on the listen-address/port.
2833 * 6) Agent and X11-Forwarding have a similar problem and are currently
2834 * not supported as the matching session/channel cannot be identified
2835 * easily.
2836 */
2837
2838/*
2839 * receive packets from downstream mux clients:
2840 * channel callback fired on read from mux client, creates
2841 * SSH_CHANNEL_MUX_PROXY channels and translates channel IDs
2842 * on channel creation.
2843 */
2844int
2845channel_proxy_downstream(struct ssh *ssh, Channel *downstream)
2846{
2847 Channel *c = NULL((void *)0);
2848 struct sshbuf *original = NULL((void *)0), *modified = NULL((void *)0);
2849 const u_char *cp;
2850 char *ctype = NULL((void *)0), *listen_host = NULL((void *)0);
2851 u_char type;
2852 size_t have;
2853 int ret = -1, r;
2854 u_int id, remote_id, listen_port;
2855
2856 /* sshbuf_dump(downstream->input, stderr); */
2857 if ((r = sshbuf_get_string_direct(downstream->input, &cp, &have))
2858 != 0) {
2859 error_fr(r, "parse")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2859
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse")
;
2860 return -1;
2861 }
2862 if (have < 2) {
2863 error_f("short message")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2863
, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "short message")
;
2864 return -1;
2865 }
2866 type = cp[1];
2867 /* skip padlen + type */
2868 cp += 2;
2869 have -= 2;
2870 if (ssh_packet_log_type(type))
2871 debug3_f("channel %u: down->up: type %u",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2872
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "channel %u: down->up: type %u"
, downstream->self, type)
2872 downstream->self, type)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2872
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "channel %u: down->up: type %u"
, downstream->self, type)
;
2873
2874 switch (type) {
2875 case SSH2_MSG_CHANNEL_OPEN90:
2876 if ((original = sshbuf_from(cp, have)) == NULL((void *)0) ||
2877 (modified = sshbuf_new()) == NULL((void *)0)) {
2878 error_f("alloc")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2878
, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "alloc")
;
2879 goto out;
2880 }
2881 if ((r = sshbuf_get_cstring(original, &ctype, NULL((void *)0))) != 0 ||
2882 (r = sshbuf_get_u32(original, &id)) != 0) {
2883 error_fr(r, "parse")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2883
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse")
;
2884 goto out;
2885 }
2886 c = channel_new(ssh, "mux proxy", SSH_CHANNEL_MUX_PROXY20,
2887 -1, -1, -1, 0, 0, 0, ctype, 1);
2888 c->mux_ctx = downstream; /* point to mux client */
2889 c->mux_downstream_id = id; /* original downstream id */
2890 if ((r = sshbuf_put_cstring(modified, ctype)) != 0 ||
2891 (r = sshbuf_put_u32(modified, c->self)) != 0 ||
2892 (r = sshbuf_putb(modified, original)) != 0) {
2893 error_fr(r, "compose")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2893
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "compose")
;
2894 channel_free(ssh, c);
2895 goto out;
2896 }
2897 break;
2898 case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION91:
2899 /*
2900 * Almost the same as SSH2_MSG_CHANNEL_OPEN, except then we
2901 * need to parse 'remote_id' instead of 'ctype'.
2902 */
2903 if ((original = sshbuf_from(cp, have)) == NULL((void *)0) ||
2904 (modified = sshbuf_new()) == NULL((void *)0)) {
2905 error_f("alloc")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2905
, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "alloc")
;
2906 goto out;
2907 }
2908 if ((r = sshbuf_get_u32(original, &remote_id)) != 0 ||
2909 (r = sshbuf_get_u32(original, &id)) != 0) {
2910 error_fr(r, "parse")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2910
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse")
;
2911 goto out;
2912 }
2913 c = channel_new(ssh, "mux proxy", SSH_CHANNEL_MUX_PROXY20,
2914 -1, -1, -1, 0, 0, 0, "mux-down-connect", 1);
2915 c->mux_ctx = downstream; /* point to mux client */
2916 c->mux_downstream_id = id;
2917 c->remote_id = remote_id;
2918 c->have_remote_id = 1;
2919 if ((r = sshbuf_put_u32(modified, remote_id)) != 0 ||
2920 (r = sshbuf_put_u32(modified, c->self)) != 0 ||
2921 (r = sshbuf_putb(modified, original)) != 0) {
2922 error_fr(r, "compose")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2922
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "compose")
;
2923 channel_free(ssh, c);
2924 goto out;
2925 }
2926 break;
2927 case SSH2_MSG_GLOBAL_REQUEST80:
2928 if ((original = sshbuf_from(cp, have)) == NULL((void *)0)) {
2929 error_f("alloc")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2929
, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "alloc")
;
2930 goto out;
2931 }
2932 if ((r = sshbuf_get_cstring(original, &ctype, NULL((void *)0))) != 0) {
2933 error_fr(r, "parse")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2933
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse")
;
2934 goto out;
2935 }
2936 if (strcmp(ctype, "tcpip-forward") != 0) {
2937 error_f("unsupported request %s", ctype)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2937
, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "unsupported request %s"
, ctype)
;
2938 goto out;
2939 }
2940 if ((r = sshbuf_get_u8(original, NULL((void *)0))) != 0 ||
2941 (r = sshbuf_get_cstring(original, &listen_host, NULL((void *)0))) != 0 ||
2942 (r = sshbuf_get_u32(original, &listen_port)) != 0) {
2943 error_fr(r, "parse")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2943
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse")
;
2944 goto out;
2945 }
2946 if (listen_port > 65535) {
2947 error_f("tcpip-forward for %s: bad port %u",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2948
, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "tcpip-forward for %s: bad port %u"
, listen_host, listen_port)
2948 listen_host, listen_port)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2948
, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "tcpip-forward for %s: bad port %u"
, listen_host, listen_port)
;
2949 goto out;
2950 }
2951 /* Record that connection to this host/port is permitted. */
2952 permission_set_add(ssh, FORWARD_USER0x101, FORWARD_LOCAL(1<<1), "<mux>", -1,
2953 listen_host, NULL((void *)0), (int)listen_port, downstream);
2954 listen_host = NULL((void *)0);
2955 break;
2956 case SSH2_MSG_CHANNEL_CLOSE97:
2957 if (have < 4)
2958 break;
2959 remote_id = PEEK_U32(cp)(((u_int32_t)(((const u_char *)(cp))[0]) << 24) | ((u_int32_t
)(((const u_char *)(cp))[1]) << 16) | ((u_int32_t)(((const
u_char *)(cp))[2]) << 8) | (u_int32_t)(((const u_char *
)(cp))[3]))
;
2960 if ((c = channel_by_remote_id(ssh, remote_id)) != NULL((void *)0)) {
2961 if (c->flags & CHAN_CLOSE_RCVD0x02)
2962 channel_free(ssh, c);
2963 else
2964 c->flags |= CHAN_CLOSE_SENT0x01;
2965 }
2966 break;
2967 }
2968 if (modified) {
2969 if ((r = sshpkt_start(ssh, type)) != 0 ||
2970 (r = sshpkt_putb(ssh, modified)) != 0 ||
2971 (r = sshpkt_send(ssh)) != 0) {
2972 error_fr(r, "send")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2972
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "send")
;
2973 goto out;
2974 }
2975 } else {
2976 if ((r = sshpkt_start(ssh, type)) != 0 ||
2977 (r = sshpkt_put(ssh, cp, have)) != 0 ||
2978 (r = sshpkt_send(ssh)) != 0) {
2979 error_fr(r, "send")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 2979
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "send")
;
2980 goto out;
2981 }
2982 }
2983 ret = 0;
2984 out:
2985 free(ctype);
2986 free(listen_host);
2987 sshbuf_free(original);
2988 sshbuf_free(modified);
2989 return ret;
2990}
2991
2992/*
2993 * receive packets from upstream server and de-multiplex packets
2994 * to correct downstream:
2995 * implemented as a helper for channel input handlers,
2996 * replaces local (proxy) channel ID with downstream channel ID.
2997 */
2998int
2999channel_proxy_upstream(Channel *c, int type, u_int32_t seq, struct ssh *ssh)
3000{
3001 struct sshbuf *b = NULL((void *)0);
3002 Channel *downstream;
3003 const u_char *cp = NULL((void *)0);
3004 size_t len;
3005 int r;
3006
3007 /*
3008 * When receiving packets from the peer we need to check whether we
3009 * need to forward the packets to the mux client. In this case we
3010 * restore the original channel id and keep track of CLOSE messages,
3011 * so we can cleanup the channel.
3012 */
3013 if (c == NULL((void *)0) || c->type != SSH_CHANNEL_MUX_PROXY20)
3014 return 0;
3015 if ((downstream = c->mux_ctx) == NULL((void *)0))
3016 return 0;
3017 switch (type) {
3018 case SSH2_MSG_CHANNEL_CLOSE97:
3019 case SSH2_MSG_CHANNEL_DATA94:
3020 case SSH2_MSG_CHANNEL_EOF96:
3021 case SSH2_MSG_CHANNEL_EXTENDED_DATA95:
3022 case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION91:
3023 case SSH2_MSG_CHANNEL_OPEN_FAILURE92:
3024 case SSH2_MSG_CHANNEL_WINDOW_ADJUST93:
3025 case SSH2_MSG_CHANNEL_SUCCESS99:
3026 case SSH2_MSG_CHANNEL_FAILURE100:
3027 case SSH2_MSG_CHANNEL_REQUEST98:
3028 break;
3029 default:
3030 debug2_f("channel %u: unsupported type %u", c->self, type)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3030
, 1, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %u: unsupported type %u"
, c->self, type)
;
3031 return 0;
3032 }
3033 if ((b = sshbuf_new()) == NULL((void *)0)) {
3034 error_f("alloc reply")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3034
, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "alloc reply")
;
3035 goto out;
3036 }
3037 /* get remaining payload (after id) */
3038 cp = sshpkt_ptr(ssh, &len);
3039 if (cp == NULL((void *)0)) {
3040 error_f("no packet")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3040
, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "no packet")
;
3041 goto out;
3042 }
3043 /* translate id and send to muxclient */
3044 if ((r = sshbuf_put_u8(b, 0)) != 0 || /* padlen */
3045 (r = sshbuf_put_u8(b, type)) != 0 ||
3046 (r = sshbuf_put_u32(b, c->mux_downstream_id)) != 0 ||
3047 (r = sshbuf_put(b, cp, len)) != 0 ||
3048 (r = sshbuf_put_stringb(downstream->output, b)) != 0) {
3049 error_fr(r, "compose muxclient")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3049
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "compose muxclient")
;
3050 goto out;
3051 }
3052 /* sshbuf_dump(b, stderr); */
3053 if (ssh_packet_log_type(type))
3054 debug3_f("channel %u: up->down: type %u", c->self, type)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3054
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "channel %u: up->down: type %u"
, c->self, type)
;
3055 out:
3056 /* update state */
3057 switch (type) {
3058 case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION91:
3059 /* record remote_id for SSH2_MSG_CHANNEL_CLOSE */
3060 if (cp && len > 4) {
3061 c->remote_id = PEEK_U32(cp)(((u_int32_t)(((const u_char *)(cp))[0]) << 24) | ((u_int32_t
)(((const u_char *)(cp))[1]) << 16) | ((u_int32_t)(((const
u_char *)(cp))[2]) << 8) | (u_int32_t)(((const u_char *
)(cp))[3]))
;
3062 c->have_remote_id = 1;
3063 }
3064 break;
3065 case SSH2_MSG_CHANNEL_CLOSE97:
3066 if (c->flags & CHAN_CLOSE_SENT0x01)
3067 channel_free(ssh, c);
3068 else
3069 c->flags |= CHAN_CLOSE_RCVD0x02;
3070 break;
3071 }
3072 sshbuf_free(b);
3073 return 1;
3074}
3075
3076/* -- protocol input */
3077
3078/* Parse a channel ID from the current packet */
3079static int
3080channel_parse_id(struct ssh *ssh, const char *where, const char *what)
3081{
3082 u_int32_t id;
3083 int r;
3084
3085 if ((r = sshpkt_get_u32(ssh, &id)) != 0) {
3086 error_r(r, "%s: parse id", where)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3086
, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), "%s: parse id", where)
;
3087 ssh_packet_disconnect(ssh, "Invalid %s message", what);
3088 }
3089 if (id > INT_MAX2147483647) {
3090 error_r(r, "%s: bad channel id %u", where, id)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3090
, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), "%s: bad channel id %u",
where, id)
;
3091 ssh_packet_disconnect(ssh, "Invalid %s channel id", what);
3092 }
3093 return (int)id;
3094}
3095
3096/* Lookup a channel from an ID in the current packet */
3097static Channel *
3098channel_from_packet_id(struct ssh *ssh, const char *where, const char *what)
3099{
3100 int id = channel_parse_id(ssh, where, what);
3101 Channel *c;
3102
3103 if ((c = channel_lookup(ssh, id)) == NULL((void *)0)) {
3104 ssh_packet_disconnect(ssh,
3105 "%s packet referred to nonexistent channel %d", what, id);
3106 }
3107 return c;
3108}
3109
3110int
3111channel_input_data(int type, u_int32_t seq, struct ssh *ssh)
3112{
3113 const u_char *data;
3114 size_t data_len, win_len;
3115 Channel *c = channel_from_packet_id(ssh, __func__, "data");
3116 int r;
3117
3118 if (channel_proxy_upstream(c, type, seq, ssh))
3119 return 0;
3120
3121 /* Ignore any data for non-open channels (might happen on close) */
3122 if (c->type != SSH_CHANNEL_OPEN4 &&
3123 c->type != SSH_CHANNEL_RDYNAMIC_OPEN21 &&
3124 c->type != SSH_CHANNEL_RDYNAMIC_FINISH22 &&
3125 c->type != SSH_CHANNEL_X11_OPEN7)
3126 return 0;
3127
3128 /* Get the data. */
3129 if ((r = sshpkt_get_string_direct(ssh, &data, &data_len)) != 0 ||
3130 (r = sshpkt_get_end(ssh)) != 0)
3131 fatal_fr(r, "channel %i: get data", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3131
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i: get data", c
->self)
;
3132
3133 win_len = data_len;
3134 if (c->datagram)
3135 win_len += 4; /* string length header */
3136
3137 /*
3138 * The sending side reduces its window as it sends data, so we
3139 * must 'fake' consumption of the data in order to ensure that window
3140 * updates are sent back. Otherwise the connection might deadlock.
3141 */
3142 if (c->ostate != CHAN_OUTPUT_OPEN0) {
3143 c->local_window -= win_len;
3144 c->local_consumed += win_len;
3145 return 0;
3146 }
3147
3148 if (win_len > c->local_maxpacket) {
3149 logit("channel %d: rcvd big packet %zu, maxpack %u",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3150
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "channel %d: rcvd big packet %zu, maxpack %u"
, c->self, win_len, c->local_maxpacket)
3150 c->self, win_len, c->local_maxpacket)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3150
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "channel %d: rcvd big packet %zu, maxpack %u"
, c->self, win_len, c->local_maxpacket)
;
3151 return 0;
3152 }
3153 if (win_len > c->local_window) {
3154 logit("channel %d: rcvd too much data %zu, win %u",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3155
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "channel %d: rcvd too much data %zu, win %u"
, c->self, win_len, c->local_window)
3155 c->self, win_len, c->local_window)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3155
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "channel %d: rcvd too much data %zu, win %u"
, c->self, win_len, c->local_window)
;
3156 return 0;
3157 }
3158 c->local_window -= win_len;
3159
3160 if (c->datagram) {
3161 if ((r = sshbuf_put_string(c->output, data, data_len)) != 0)
3162 fatal_fr(r, "channel %i: append datagram", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3162
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i: append datagram"
, c->self)
;
3163 } else if ((r = sshbuf_put(c->output, data, data_len)) != 0)
3164 fatal_fr(r, "channel %i: append data", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3164
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i: append data"
, c->self)
;
3165
3166 return 0;
3167}
3168
3169int
3170channel_input_extended_data(int type, u_int32_t seq, struct ssh *ssh)
3171{
3172 const u_char *data;
3173 size_t data_len;
3174 u_int32_t tcode;
3175 Channel *c = channel_from_packet_id(ssh, __func__, "extended data");
3176 int r;
3177
3178 if (channel_proxy_upstream(c, type, seq, ssh))
3179 return 0;
3180 if (c->type != SSH_CHANNEL_OPEN4) {
3181 logit("channel %d: ext data for non open", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3181
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "channel %d: ext data for non open"
, c->self)
;
3182 return 0;
3183 }
3184 if (c->flags & CHAN_EOF_RCVD0x08) {
3185 if (ssh->compat & SSH_BUG_EXTEOF0x00200000)
3186 debug("channel %d: accepting ext data after eof",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3187
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "channel %d: accepting ext data after eof"
, c->self)
3187 c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3187
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "channel %d: accepting ext data after eof"
, c->self)
;
3188 else
3189 ssh_packet_disconnect(ssh, "Received extended_data "
3190 "after EOF on channel %d.", c->self);
3191 }
3192
3193 if ((r = sshpkt_get_u32(ssh, &tcode)) != 0) {
3194 error_fr(r, "parse tcode")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3194
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse tcode")
;
3195 ssh_packet_disconnect(ssh, "Invalid extended_data message");
3196 }
3197 if (c->efd == -1 ||
3198 c->extended_usage != CHAN_EXTENDED_WRITE2 ||
3199 tcode != SSH2_EXTENDED_DATA_STDERR1) {
3200 logit("channel %d: bad ext data", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3200
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "channel %d: bad ext data"
, c->self)
;
3201 return 0;
3202 }
3203 if ((r = sshpkt_get_string_direct(ssh, &data, &data_len)) != 0 ||
3204 (r = sshpkt_get_end(ssh)) != 0) {
3205 error_fr(r, "parse data")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3205
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse data")
;
3206 ssh_packet_disconnect(ssh, "Invalid extended_data message");
3207 }
3208
3209 if (data_len > c->local_window) {
3210 logit("channel %d: rcvd too much extended_data %zu, win %u",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3211
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "channel %d: rcvd too much extended_data %zu, win %u"
, c->self, data_len, c->local_window)
3211 c->self, data_len, c->local_window)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3211
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "channel %d: rcvd too much extended_data %zu, win %u"
, c->self, data_len, c->local_window)
;
3212 return 0;
3213 }
3214 debug2("channel %d: rcvd ext data %zu", c->self, data_len)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3214
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: rcvd ext data %zu"
, c->self, data_len)
;
3215 /* XXX sshpkt_getb? */
3216 if ((r = sshbuf_put(c->extended, data, data_len)) != 0)
3217 error_fr(r, "append")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3217
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "append")
;
3218 c->local_window -= data_len;
3219 return 0;
3220}
3221
3222int
3223channel_input_ieof(int type, u_int32_t seq, struct ssh *ssh)
3224{
3225 Channel *c = channel_from_packet_id(ssh, __func__, "ieof");
3226 int r;
3227
3228 if ((r = sshpkt_get_end(ssh)) != 0) {
3229 error_fr(r, "parse data")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3229
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse data")
;
3230 ssh_packet_disconnect(ssh, "Invalid ieof message");
3231 }
3232
3233 if (channel_proxy_upstream(c, type, seq, ssh))
3234 return 0;
3235 chan_rcvd_ieof(ssh, c);
3236
3237 /* XXX force input close */
3238 if (c->force_drain && c->istate == CHAN_INPUT_OPEN0) {
3239 debug("channel %d: FORCE input drain", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3239
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "channel %d: FORCE input drain"
, c->self)
;
3240 c->istate = CHAN_INPUT_WAIT_DRAIN1;
3241 if (sshbuf_len(c->input) == 0)
3242 chan_ibuf_empty(ssh, c);
3243 }
3244 return 0;
3245}
3246
3247int
3248channel_input_oclose(int type, u_int32_t seq, struct ssh *ssh)
3249{
3250 Channel *c = channel_from_packet_id(ssh, __func__, "oclose");
3251 int r;
3252
3253 if (channel_proxy_upstream(c, type, seq, ssh))
3254 return 0;
3255 if ((r = sshpkt_get_end(ssh)) != 0) {
3256 error_fr(r, "parse data")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3256
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse data")
;
3257 ssh_packet_disconnect(ssh, "Invalid oclose message");
3258 }
3259 chan_rcvd_oclose(ssh, c);
3260 return 0;
3261}
3262
3263int
3264channel_input_open_confirmation(int type, u_int32_t seq, struct ssh *ssh)
3265{
3266 Channel *c = channel_from_packet_id(ssh, __func__, "open confirmation");
3267 u_int32_t remote_window, remote_maxpacket;
3268 int r;
3269
3270 if (channel_proxy_upstream(c, type, seq, ssh))
3271 return 0;
3272 if (c->type != SSH_CHANNEL_OPENING3)
3273 ssh_packet_disconnect(ssh, "Received open confirmation for "
3274 "non-opening channel %d.", c->self);
3275 /*
3276 * Record the remote channel number and mark that the channel
3277 * is now open.
3278 */
3279 if ((r = sshpkt_get_u32(ssh, &c->remote_id)) != 0 ||
3280 (r = sshpkt_get_u32(ssh, &remote_window)) != 0 ||
3281 (r = sshpkt_get_u32(ssh, &remote_maxpacket)) != 0 ||
3282 (r = sshpkt_get_end(ssh)) != 0) {
3283 error_fr(r, "window/maxpacket")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3283
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "window/maxpacket")
;
3284 ssh_packet_disconnect(ssh, "Invalid open confirmation message");
3285 }
3286
3287 c->have_remote_id = 1;
3288 c->remote_window = remote_window;
3289 c->remote_maxpacket = remote_maxpacket;
3290 c->type = SSH_CHANNEL_OPEN4;
3291 if (c->open_confirm) {
3292 debug2_f("channel %d: callback start", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3292
, 1, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: callback start"
, c->self)
;
3293 c->open_confirm(ssh, c->self, 1, c->open_confirm_ctx);
3294 debug2_f("channel %d: callback done", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3294
, 1, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: callback done"
, c->self)
;
3295 }
3296 debug2("channel %d: open confirm rwindow %u rmax %u", c->self,sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3297
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: open confirm rwindow %u rmax %u"
, c->self, c->remote_window, c->remote_maxpacket)
3297 c->remote_window, c->remote_maxpacket)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3297
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: open confirm rwindow %u rmax %u"
, c->self, c->remote_window, c->remote_maxpacket)
;
3298 return 0;
3299}
3300
3301static char *
3302reason2txt(int reason)
3303{
3304 switch (reason) {
3305 case SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED1:
3306 return "administratively prohibited";
3307 case SSH2_OPEN_CONNECT_FAILED2:
3308 return "connect failed";
3309 case SSH2_OPEN_UNKNOWN_CHANNEL_TYPE3:
3310 return "unknown channel type";
3311 case SSH2_OPEN_RESOURCE_SHORTAGE4:
3312 return "resource shortage";
3313 }
3314 return "unknown reason";
3315}
3316
3317int
3318channel_input_open_failure(int type, u_int32_t seq, struct ssh *ssh)
3319{
3320 Channel *c = channel_from_packet_id(ssh, __func__, "open failure");
3321 u_int32_t reason;
3322 char *msg = NULL((void *)0);
3323 int r;
3324
3325 if (channel_proxy_upstream(c, type, seq, ssh))
3326 return 0;
3327 if (c->type != SSH_CHANNEL_OPENING3)
3328 ssh_packet_disconnect(ssh, "Received open failure for "
3329 "non-opening channel %d.", c->self);
3330 if ((r = sshpkt_get_u32(ssh, &reason)) != 0) {
3331 error_fr(r, "parse reason")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3331
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse reason")
;
3332 ssh_packet_disconnect(ssh, "Invalid open failure message");
3333 }
3334 /* skip language */
3335 if ((r = sshpkt_get_cstring(ssh, &msg, NULL((void *)0))) != 0 ||
3336 (r = sshpkt_get_string_direct(ssh, NULL((void *)0), NULL((void *)0))) != 0 ||
3337 (r = sshpkt_get_end(ssh)) != 0) {
3338 error_fr(r, "parse msg/lang")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3338
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse msg/lang")
;
3339 ssh_packet_disconnect(ssh, "Invalid open failure message");
3340 }
3341 logit("channel %d: open failed: %s%s%s", c->self,sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3342
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "channel %d: open failed: %s%s%s"
, c->self, reason2txt(reason), msg ? ": ": "", msg ? msg :
"")
3342 reason2txt(reason), msg ? ": ": "", msg ? msg : "")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3342
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "channel %d: open failed: %s%s%s"
, c->self, reason2txt(reason), msg ? ": ": "", msg ? msg :
"")
;
3343 free(msg);
3344 if (c->open_confirm) {
3345 debug2_f("channel %d: callback start", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3345
, 1, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: callback start"
, c->self)
;
3346 c->open_confirm(ssh, c->self, 0, c->open_confirm_ctx);
3347 debug2_f("channel %d: callback done", c->self)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3347
, 1, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: callback done"
, c->self)
;
3348 }
3349 /* Schedule the channel for cleanup/deletion. */
3350 chan_mark_dead(ssh, c);
3351 return 0;
3352}
3353
3354int
3355channel_input_window_adjust(int type, u_int32_t seq, struct ssh *ssh)
3356{
3357 int id = channel_parse_id(ssh, __func__, "window adjust");
3358 Channel *c;
3359 u_int32_t adjust;
3360 u_int new_rwin;
3361 int r;
3362
3363 if ((c = channel_lookup(ssh, id)) == NULL((void *)0)) {
3364 logit("Received window adjust for non-open channel %d.", id)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3364
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Received window adjust for non-open channel %d."
, id)
;
3365 return 0;
3366 }
3367
3368 if (channel_proxy_upstream(c, type, seq, ssh))
3369 return 0;
3370 if ((r = sshpkt_get_u32(ssh, &adjust)) != 0 ||
3371 (r = sshpkt_get_end(ssh)) != 0) {
3372 error_fr(r, "parse adjust")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3372
, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), "parse adjust")
;
3373 ssh_packet_disconnect(ssh, "Invalid window adjust message");
3374 }
3375 debug2("channel %d: rcvd adjust %u", c->self, adjust)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3375
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "channel %d: rcvd adjust %u"
, c->self, adjust)
;
3376 if ((new_rwin = c->remote_window + adjust) < c->remote_window) {
3377 fatal("channel %d: adjust %u overflows remote window %u",sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3378
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "channel %d: adjust %u overflows remote window %u"
, c->self, adjust, c->remote_window)
3378 c->self, adjust, c->remote_window)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3378
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "channel %d: adjust %u overflows remote window %u"
, c->self, adjust, c->remote_window)
;
3379 }
3380 c->remote_window = new_rwin;
3381 return 0;
3382}
3383
3384int
3385channel_input_status_confirm(int type, u_int32_t seq, struct ssh *ssh)
3386{
3387 int id = channel_parse_id(ssh, __func__, "status confirm");
3388 Channel *c;
3389 struct channel_confirm *cc;
3390
3391 /* Reset keepalive timeout */
3392 ssh_packet_set_alive_timeouts(ssh, 0);
3393
3394 debug2_f("type %d id %d", type, id)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3394
, 1, SYSLOG_LEVEL_DEBUG2, ((void *)0), "type %d id %d", type,
id)
;
3395
3396 if ((c = channel_lookup(ssh, id)) == NULL((void *)0)) {
3397 logit_f("%d: unknown", id)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3397
, 1, SYSLOG_LEVEL_INFO, ((void *)0), "%d: unknown", id)
;
3398 return 0;
3399 }
3400 if (channel_proxy_upstream(c, type, seq, ssh))
3401 return 0;
3402 if (sshpkt_get_end(ssh) != 0)
3403 ssh_packet_disconnect(ssh, "Invalid status confirm message");
3404 if ((cc = TAILQ_FIRST(&c->status_confirms)((&c->status_confirms)->tqh_first)) == NULL((void *)0))
3405 return 0;
3406 cc->cb(ssh, type, c, cc->ctx);
3407 TAILQ_REMOVE(&c->status_confirms, cc, entry)do { if (((cc)->entry.tqe_next) != ((void *)0)) (cc)->entry
.tqe_next->entry.tqe_prev = (cc)->entry.tqe_prev; else (
&c->status_confirms)->tqh_last = (cc)->entry.tqe_prev
; *(cc)->entry.tqe_prev = (cc)->entry.tqe_next; ; ; } while
(0)
;
3408 freezero(cc, sizeof(*cc));
3409 return 0;
3410}
3411
3412/* -- tcp forwarding */
3413
3414void
3415channel_set_af(struct ssh *ssh, int af)
3416{
3417 ssh->chanctxt->IPv4or6 = af;
3418}
3419
3420
3421/*
3422 * Determine whether or not a port forward listens to loopback, the
3423 * specified address or wildcard. On the client, a specified bind
3424 * address will always override gateway_ports. On the server, a
3425 * gateway_ports of 1 (``yes'') will override the client's specification
3426 * and force a wildcard bind, whereas a value of 2 (``clientspecified'')
3427 * will bind to whatever address the client asked for.
3428 *
3429 * Special-case listen_addrs are:
3430 *
3431 * "0.0.0.0" -> wildcard v4/v6 if SSH_OLD_FORWARD_ADDR
3432 * "" (empty string), "*" -> wildcard v4/v6
3433 * "localhost" -> loopback v4/v6
3434 * "127.0.0.1" / "::1" -> accepted even if gateway_ports isn't set
3435 */
3436static const char *
3437channel_fwd_bind_addr(struct ssh *ssh, const char *listen_addr, int *wildcardp,
3438 int is_client, struct ForwardOptions *fwd_opts)
3439{
3440 const char *addr = NULL((void *)0);
3441 int wildcard = 0;
3442
3443 if (listen_addr == NULL((void *)0)) {
3444 /* No address specified: default to gateway_ports setting */
3445 if (fwd_opts->gateway_ports)
3446 wildcard = 1;
3447 } else if (fwd_opts->gateway_ports || is_client) {
3448 if (((ssh->compat & SSH_OLD_FORWARD_ADDR0x01000000) &&
3449 strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) ||
3450 *listen_addr == '\0' || strcmp(listen_addr, "*") == 0 ||
3451 (!is_client && fwd_opts->gateway_ports == 1)) {
3452 wildcard = 1;
3453 /*
3454 * Notify client if they requested a specific listen
3455 * address and it was overridden.
3456 */
3457 if (*listen_addr != '\0' &&
3458 strcmp(listen_addr, "0.0.0.0") != 0 &&
3459 strcmp(listen_addr, "*") != 0) {
3460 ssh_packet_send_debug(ssh,
3461 "Forwarding listen address "
3462 "\"%s\" overridden by server "
3463 "GatewayPorts", listen_addr);
3464 }
3465 } else if (strcmp(listen_addr, "localhost") != 0 ||
3466 strcmp(listen_addr, "127.0.0.1") == 0 ||
3467 strcmp(listen_addr, "::1") == 0) {
3468 /*
3469 * Accept explicit localhost address when
3470 * GatewayPorts=yes. The "localhost" hostname is
3471 * deliberately skipped here so it will listen on all
3472 * available local address families.
3473 */
3474 addr = listen_addr;
3475 }
3476 } else if (strcmp(listen_addr, "127.0.0.1") == 0 ||
3477 strcmp(listen_addr, "::1") == 0) {
3478 /*
3479 * If a specific IPv4/IPv6 localhost address has been
3480 * requested then accept it even if gateway_ports is in
3481 * effect. This allows the client to prefer IPv4 or IPv6.
3482 */
3483 addr = listen_addr;
3484 }
3485 if (wildcardp != NULL((void *)0))
3486 *wildcardp = wildcard;
3487 return addr;
3488}
3489
3490static int
3491channel_setup_fwd_listener_tcpip(struct ssh *ssh, int type,
3492 struct Forward *fwd, int *allocated_listen_port,
3493 struct ForwardOptions *fwd_opts)
3494{
3495 Channel *c;
3496 int sock, r, success = 0, wildcard = 0, is_client;
3497 struct addrinfo hints, *ai, *aitop;
3498 const char *host, *addr;
3499 char ntop[NI_MAXHOST256], strport[NI_MAXSERV32];
3500 in_port_t *lport_p;
3501
3502 is_client = (type == SSH_CHANNEL_PORT_LISTENER2);
3503
3504 if (is_client && fwd->connect_path != NULL((void *)0)) {
3505 host = fwd->connect_path;
3506 } else {
3507 host = (type == SSH_CHANNEL_RPORT_LISTENER11) ?
3508 fwd->listen_host : fwd->connect_host;
3509 if (host == NULL((void *)0)) {
3510 error("No forward host name.")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3510
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "No forward host name."
)
;
3511 return 0;
3512 }
3513 if (strlen(host) >= NI_MAXHOST256) {
3514 error("Forward host name too long.")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3514
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Forward host name too long."
)
;
3515 return 0;
3516 }
3517 }
3518
3519 /* Determine the bind address, cf. channel_fwd_bind_addr() comment */
3520 addr = channel_fwd_bind_addr(ssh, fwd->listen_host, &wildcard,
3521 is_client, fwd_opts);
3522 debug3_f("type %d wildcard %d addr %s", type, wildcard,sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3523
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "type %d wildcard %d addr %s"
, type, wildcard, (addr == ((void *)0)) ? "NULL" : addr)
3523 (addr == NULL) ? "NULL" : addr)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3523
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "type %d wildcard %d addr %s"
, type, wildcard, (addr == ((void *)0)) ? "NULL" : addr)
;
3524
3525 /*
3526 * getaddrinfo returns a loopback address if the hostname is
3527 * set to NULL and hints.ai_flags is not AI_PASSIVE
3528 */
3529 memset(&hints, 0, sizeof(hints));
3530 hints.ai_family = ssh->chanctxt->IPv4or6;
3531 hints.ai_flags = wildcard ? AI_PASSIVE1 : 0;
3532 hints.ai_socktype = SOCK_STREAM1;
3533 snprintf(strport, sizeof strport, "%d", fwd->listen_port);
3534 if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) {
3535 if (addr == NULL((void *)0)) {
3536 /* This really shouldn't happen */
3537 ssh_packet_disconnect(ssh, "getaddrinfo: fatal error: %s",
3538 ssh_gai_strerror(r));
3539 } else {
3540 error_f("getaddrinfo(%.64s): %s", addr,sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3541
, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "getaddrinfo(%.64s): %s"
, addr, ssh_gai_strerror(r))
3541 ssh_gai_strerror(r))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3541
, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "getaddrinfo(%.64s): %s"
, addr, ssh_gai_strerror(r))
;
3542 }
3543 return 0;
3544 }
3545 if (allocated_listen_port != NULL((void *)0))
3546 *allocated_listen_port = 0;
3547 for (ai = aitop; ai; ai = ai->ai_next) {
3548 switch (ai->ai_family) {
3549 case AF_INET2:
3550 lport_p = &((struct sockaddr_in *)ai->ai_addr)->
3551 sin_port;
3552 break;
3553 case AF_INET624:
3554 lport_p = &((struct sockaddr_in6 *)ai->ai_addr)->
3555 sin6_port;
3556 break;
3557 default:
3558 continue;
3559 }
3560 /*
3561 * If allocating a port for -R forwards, then use the
3562 * same port for all address families.
3563 */
3564 if (type == SSH_CHANNEL_RPORT_LISTENER11 &&
3565 fwd->listen_port == 0 && allocated_listen_port != NULL((void *)0) &&
3566 *allocated_listen_port > 0)
3567 *lport_p = htons(*allocated_listen_port)(__uint16_t)(__builtin_constant_p(*allocated_listen_port) ? (
__uint16_t)(((__uint16_t)(*allocated_listen_port) & 0xffU
) << 8 | ((__uint16_t)(*allocated_listen_port) & 0xff00U
) >> 8) : __swap16md(*allocated_listen_port))
;
3568
3569 if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
3570 strport, sizeof(strport),
3571 NI_NUMERICHOST1|NI_NUMERICSERV2) != 0) {
3572 error_f("getnameinfo failed")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3572
, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "getnameinfo failed")
;
3573 continue;
3574 }
3575 /* Create a port to listen for the host. */
3576 sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
3577 if (sock == -1) {
3578 /* this is no error since kernel may not support ipv6 */
3579 verbose("socket [%s]:%s: %.100s", ntop, strport,sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3580
, 0, SYSLOG_LEVEL_VERBOSE, ((void *)0), "socket [%s]:%s: %.100s"
, ntop, strport, strerror((*__errno())))
3580 strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3580
, 0, SYSLOG_LEVEL_VERBOSE, ((void *)0), "socket [%s]:%s: %.100s"
, ntop, strport, strerror((*__errno())))
;
3581 continue;
3582 }
3583
3584 set_reuseaddr(sock);
3585
3586 debug("Local forwarding listening on %s port %s.",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3587
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "Local forwarding listening on %s port %s."
, ntop, strport)
3587 ntop, strport)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3587
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "Local forwarding listening on %s port %s."
, ntop, strport)
;
3588
3589 /* Bind the socket to the address. */
3590 if (bind(sock, ai->ai_addr, ai->ai_addrlen) == -1) {
3591 /*
3592 * address can be in if use ipv6 address is
3593 * already bound
3594 */
3595 verbose("bind [%s]:%s: %.100s",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3596
, 0, SYSLOG_LEVEL_VERBOSE, ((void *)0), "bind [%s]:%s: %.100s"
, ntop, strport, strerror((*__errno())))
3596 ntop, strport, strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3596
, 0, SYSLOG_LEVEL_VERBOSE, ((void *)0), "bind [%s]:%s: %.100s"
, ntop, strport, strerror((*__errno())))
;
3597 close(sock);
3598 continue;
3599 }
3600 /* Start listening for connections on the socket. */
3601 if (listen(sock, SSH_LISTEN_BACKLOG128) == -1) {
3602 error("listen [%s]:%s: %.100s", ntop, strport,sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3603
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "listen [%s]:%s: %.100s"
, ntop, strport, strerror((*__errno())))
3603 strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3603
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "listen [%s]:%s: %.100s"
, ntop, strport, strerror((*__errno())))
;
3604 close(sock);
3605 continue;
3606 }
3607
3608 /*
3609 * fwd->listen_port == 0 requests a dynamically allocated port -
3610 * record what we got.
3611 */
3612 if (type == SSH_CHANNEL_RPORT_LISTENER11 &&
3613 fwd->listen_port == 0 &&
3614 allocated_listen_port != NULL((void *)0) &&
3615 *allocated_listen_port == 0) {
3616 *allocated_listen_port = get_local_port(sock);
3617 debug("Allocated listen port %d",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3618
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "Allocated listen port %d"
, *allocated_listen_port)
3618 *allocated_listen_port)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3618
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "Allocated listen port %d"
, *allocated_listen_port)
;
3619 }
3620
3621 /* Allocate a channel number for the socket. */
3622 c = channel_new(ssh, "port listener", type, sock, sock, -1,
3623 CHAN_TCP_WINDOW_DEFAULT(64*(32*1024)), CHAN_TCP_PACKET_DEFAULT(32*1024),
3624 0, "port listener", 1);
3625 c->path = xstrdup(host);
3626 c->host_port = fwd->connect_port;
3627 c->listening_addr = addr == NULL((void *)0) ? NULL((void *)0) : xstrdup(addr);
3628 if (fwd->listen_port == 0 && allocated_listen_port != NULL((void *)0) &&
3629 !(ssh->compat & SSH_BUG_DYNAMIC_RPORT0x08000000))
3630 c->listening_port = *allocated_listen_port;
3631 else
3632 c->listening_port = fwd->listen_port;
3633 success = 1;
3634 }
3635 if (success == 0)
3636 error_f("cannot listen to port: %d", fwd->listen_port)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3636
, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "cannot listen to port: %d"
, fwd->listen_port)
;
3637 freeaddrinfo(aitop);
3638 return success;
3639}
3640
3641static int
3642channel_setup_fwd_listener_streamlocal(struct ssh *ssh, int type,
3643 struct Forward *fwd, struct ForwardOptions *fwd_opts)
3644{
3645 struct sockaddr_un sunaddr;
3646 const char *path;
3647 Channel *c;
3648 int port, sock;
3649 mode_t omask;
3650
3651 switch (type) {
3652 case SSH_CHANNEL_UNIX_LISTENER18:
3653 if (fwd->connect_path != NULL((void *)0)) {
3654 if (strlen(fwd->connect_path) > sizeof(sunaddr.sun_path)) {
3655 error("Local connecting path too long: %s",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3656
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Local connecting path too long: %s"
, fwd->connect_path)
3656 fwd->connect_path)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3656
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Local connecting path too long: %s"
, fwd->connect_path)
;
3657 return 0;
3658 }
3659 path = fwd->connect_path;
3660 port = PORT_STREAMLOCAL-2;
3661 } else {
3662 if (fwd->connect_host == NULL((void *)0)) {
3663 error("No forward host name.")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3663
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "No forward host name."
)
;
3664 return 0;
3665 }
3666 if (strlen(fwd->connect_host) >= NI_MAXHOST256) {
3667 error("Forward host name too long.")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3667
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Forward host name too long."
)
;
3668 return 0;
3669 }
3670 path = fwd->connect_host;
3671 port = fwd->connect_port;
3672 }
3673 break;
3674 case SSH_CHANNEL_RUNIX_LISTENER19:
3675 path = fwd->listen_path;
3676 port = PORT_STREAMLOCAL-2;
3677 break;
3678 default:
3679 error_f("unexpected channel type %d", type)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3679
, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "unexpected channel type %d"
, type)
;
3680 return 0;
3681 }
3682
3683 if (fwd->listen_path == NULL((void *)0)) {
3684 error("No forward path name.")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3684
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "No forward path name."
)
;
3685 return 0;
3686 }
3687 if (strlen(fwd->listen_path) > sizeof(sunaddr.sun_path)) {
3688 error("Local listening path too long: %s", fwd->listen_path)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3688
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Local listening path too long: %s"
, fwd->listen_path)
;
3689 return 0;
3690 }
3691
3692 debug3_f("type %d path %s", type, fwd->listen_path)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3692
, 1, SYSLOG_LEVEL_DEBUG3, ((void *)0), "type %d path %s", type
, fwd->listen_path)
;
3693
3694 /* Start a Unix domain listener. */
3695 omask = umask(fwd_opts->streamlocal_bind_mask);
3696 sock = unix_listener(fwd->listen_path, SSH_LISTEN_BACKLOG128,
3697 fwd_opts->streamlocal_bind_unlink);
3698 umask(omask);
3699 if (sock < 0)
3700 return 0;
3701
3702 debug("Local forwarding listening on path %s.", fwd->listen_path)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3702
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "Local forwarding listening on path %s."
, fwd->listen_path)
;
3703
3704 /* Allocate a channel number for the socket. */
3705 c = channel_new(ssh, "unix listener", type, sock, sock, -1,
3706 CHAN_TCP_WINDOW_DEFAULT(64*(32*1024)), CHAN_TCP_PACKET_DEFAULT(32*1024),
3707 0, "unix listener", 1);
3708 c->path = xstrdup(path);
3709 c->host_port = port;
3710 c->listening_port = PORT_STREAMLOCAL-2;
3711 c->listening_addr = xstrdup(fwd->listen_path);
3712 return 1;
3713}
3714
3715static int
3716channel_cancel_rport_listener_tcpip(struct ssh *ssh,
3717 const char *host, u_short port)
3718{
3719 u_int i;
3720 int found = 0;
3721
3722 for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
3723 Channel *c = ssh->chanctxt->channels[i];
3724 if (c == NULL((void *)0) || c->type != SSH_CHANNEL_RPORT_LISTENER11)
3725 continue;
3726 if (strcmp(c->path, host) == 0 && c->listening_port == port) {
3727 debug2_f("close channel %d", i)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3727
, 1, SYSLOG_LEVEL_DEBUG2, ((void *)0), "close channel %d", i)
;
3728 channel_free(ssh, c);
3729 found = 1;
3730 }
3731 }
3732
3733 return found;
3734}
3735
3736static int
3737channel_cancel_rport_listener_streamlocal(struct ssh *ssh, const char *path)
3738{
3739 u_int i;
3740 int found = 0;
3741
3742 for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
3743 Channel *c = ssh->chanctxt->channels[i];
3744 if (c == NULL((void *)0) || c->type != SSH_CHANNEL_RUNIX_LISTENER19)
3745 continue;
3746 if (c->path == NULL((void *)0))
3747 continue;
3748 if (strcmp(c->path, path) == 0) {
3749 debug2_f("close channel %d", i)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3749
, 1, SYSLOG_LEVEL_DEBUG2, ((void *)0), "close channel %d", i)
;
3750 channel_free(ssh, c);
3751 found = 1;
3752 }
3753 }
3754
3755 return found;
3756}
3757
3758int
3759channel_cancel_rport_listener(struct ssh *ssh, struct Forward *fwd)
3760{
3761 if (fwd->listen_path != NULL((void *)0)) {
3762 return channel_cancel_rport_listener_streamlocal(ssh,
3763 fwd->listen_path);
3764 } else {
3765 return channel_cancel_rport_listener_tcpip(ssh,
3766 fwd->listen_host, fwd->listen_port);
3767 }
3768}
3769
3770static int
3771channel_cancel_lport_listener_tcpip(struct ssh *ssh,
3772 const char *lhost, u_short lport, int cport,
3773 struct ForwardOptions *fwd_opts)
3774{
3775 u_int i;
3776 int found = 0;
3777 const char *addr = channel_fwd_bind_addr(ssh, lhost, NULL((void *)0), 1, fwd_opts);
3778
3779 for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
3780 Channel *c = ssh->chanctxt->channels[i];
3781 if (c == NULL((void *)0) || c->type != SSH_CHANNEL_PORT_LISTENER2)
3782 continue;
3783 if (c->listening_port != lport)
3784 continue;
3785 if (cport == CHANNEL_CANCEL_PORT_STATIC-1) {
3786 /* skip dynamic forwardings */
3787 if (c->host_port == 0)
3788 continue;
3789 } else {
3790 if (c->host_port != cport)
3791 continue;
3792 }
3793 if ((c->listening_addr == NULL((void *)0) && addr != NULL((void *)0)) ||
3794 (c->listening_addr != NULL((void *)0) && addr == NULL((void *)0)))
3795 continue;
3796 if (addr == NULL((void *)0) || strcmp(c->listening_addr, addr) == 0) {
3797 debug2_f("close channel %d", i)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3797
, 1, SYSLOG_LEVEL_DEBUG2, ((void *)0), "close channel %d", i)
;
3798 channel_free(ssh, c);
3799 found = 1;
3800 }
3801 }
3802
3803 return found;
3804}
3805
3806static int
3807channel_cancel_lport_listener_streamlocal(struct ssh *ssh, const char *path)
3808{
3809 u_int i;
3810 int found = 0;
3811
3812 if (path == NULL((void *)0)) {
3813 error_f("no path specified.")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3813
, 1, SYSLOG_LEVEL_ERROR, ((void *)0), "no path specified.")
;
3814 return 0;
3815 }
3816
3817 for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
3818 Channel *c = ssh->chanctxt->channels[i];
3819 if (c == NULL((void *)0) || c->type != SSH_CHANNEL_UNIX_LISTENER18)
3820 continue;
3821 if (c->listening_addr == NULL((void *)0))
3822 continue;
3823 if (strcmp(c->listening_addr, path) == 0) {
3824 debug2_f("close channel %d", i)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3824
, 1, SYSLOG_LEVEL_DEBUG2, ((void *)0), "close channel %d", i)
;
3825 channel_free(ssh, c);
3826 found = 1;
3827 }
3828 }
3829
3830 return found;
3831}
3832
3833int
3834channel_cancel_lport_listener(struct ssh *ssh,
3835 struct Forward *fwd, int cport, struct ForwardOptions *fwd_opts)
3836{
3837 if (fwd->listen_path != NULL((void *)0)) {
3838 return channel_cancel_lport_listener_streamlocal(ssh,
3839 fwd->listen_path);
3840 } else {
3841 return channel_cancel_lport_listener_tcpip(ssh,
3842 fwd->listen_host, fwd->listen_port, cport, fwd_opts);
3843 }
3844}
3845
3846/* protocol local port fwd, used by ssh */
3847int
3848channel_setup_local_fwd_listener(struct ssh *ssh,
3849 struct Forward *fwd, struct ForwardOptions *fwd_opts)
3850{
3851 if (fwd->listen_path != NULL((void *)0)) {
3852 return channel_setup_fwd_listener_streamlocal(ssh,
3853 SSH_CHANNEL_UNIX_LISTENER18, fwd, fwd_opts);
3854 } else {
3855 return channel_setup_fwd_listener_tcpip(ssh,
3856 SSH_CHANNEL_PORT_LISTENER2, fwd, NULL((void *)0), fwd_opts);
3857 }
3858}
3859
3860/* Matches a remote forwarding permission against a requested forwarding */
3861static int
3862remote_open_match(struct permission *allowed_open, struct Forward *fwd)
3863{
3864 int ret;
3865 char *lhost;
3866
3867 /* XXX add ACLs for streamlocal */
3868 if (fwd->listen_path != NULL((void *)0))
3869 return 1;
3870
3871 if (fwd->listen_host == NULL((void *)0) || allowed_open->listen_host == NULL((void *)0))
3872 return 0;
3873
3874 if (allowed_open->listen_port != FWD_PERMIT_ANY_PORT0 &&
3875 allowed_open->listen_port != fwd->listen_port)
3876 return 0;
3877
3878 /* Match hostnames case-insensitively */
3879 lhost = xstrdup(fwd->listen_host);
3880 lowercase(lhost);
3881 ret = match_pattern(lhost, allowed_open->listen_host);
3882 free(lhost);
3883
3884 return ret;
3885}
3886
3887/* Checks whether a requested remote forwarding is permitted */
3888static int
3889check_rfwd_permission(struct ssh *ssh, struct Forward *fwd)
3890{
3891 struct ssh_channels *sc = ssh->chanctxt;
3892 struct permission_set *pset = &sc->remote_perms;
3893 u_int i, permit, permit_adm = 1;
3894 struct permission *perm;
3895
3896 /* XXX apply GatewayPorts override before checking? */
3897
3898 permit = pset->all_permitted;
3899 if (!permit) {
3900 for (i = 0; i < pset->num_permitted_user; i++) {
3901 perm = &pset->permitted_user[i];
3902 if (remote_open_match(perm, fwd)) {
3903 permit = 1;
3904 break;
3905 }
3906 }
3907 }
3908
3909 if (pset->num_permitted_admin > 0) {
3910 permit_adm = 0;
3911 for (i = 0; i < pset->num_permitted_admin; i++) {
3912 perm = &pset->permitted_admin[i];
3913 if (remote_open_match(perm, fwd)) {
3914 permit_adm = 1;
3915 break;
3916 }
3917 }
3918 }
3919
3920 return permit && permit_adm;
3921}
3922
3923/* protocol v2 remote port fwd, used by sshd */
3924int
3925channel_setup_remote_fwd_listener(struct ssh *ssh, struct Forward *fwd,
3926 int *allocated_listen_port, struct ForwardOptions *fwd_opts)
3927{
3928 if (!check_rfwd_permission(ssh, fwd)) {
3929 ssh_packet_send_debug(ssh, "port forwarding refused");
3930 if (fwd->listen_path != NULL((void *)0))
3931 /* XXX always allowed, see remote_open_match() */
3932 logit("Received request from %.100s port %d to "sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3936
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Received request from %.100s port %d to "
"remote forward to path \"%.100s\", " "but the request was denied."
, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), fwd->listen_path
)
3933 "remote forward to path \"%.100s\", "sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3936
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Received request from %.100s port %d to "
"remote forward to path \"%.100s\", " "but the request was denied."
, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), fwd->listen_path
)
3934 "but the request was denied.",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3936
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Received request from %.100s port %d to "
"remote forward to path \"%.100s\", " "but the request was denied."
, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), fwd->listen_path
)
3935 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3936
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Received request from %.100s port %d to "
"remote forward to path \"%.100s\", " "but the request was denied."
, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), fwd->listen_path
)
3936 fwd->listen_path)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3936
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Received request from %.100s port %d to "
"remote forward to path \"%.100s\", " "but the request was denied."
, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), fwd->listen_path
)
;
3937 else if(fwd->listen_host != NULL((void *)0))
3938 logit("Received request from %.100s port %d to "sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3942
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Received request from %.100s port %d to "
"remote forward to host %.100s port %d, " "but the request was denied."
, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), fwd->listen_host
, fwd->listen_port)
3939 "remote forward to host %.100s port %d, "sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3942
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Received request from %.100s port %d to "
"remote forward to host %.100s port %d, " "but the request was denied."
, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), fwd->listen_host
, fwd->listen_port)
3940 "but the request was denied.",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3942
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Received request from %.100s port %d to "
"remote forward to host %.100s port %d, " "but the request was denied."
, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), fwd->listen_host
, fwd->listen_port)
3941 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3942
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Received request from %.100s port %d to "
"remote forward to host %.100s port %d, " "but the request was denied."
, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), fwd->listen_host
, fwd->listen_port)
3942 fwd->listen_host, fwd->listen_port )sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3942
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Received request from %.100s port %d to "
"remote forward to host %.100s port %d, " "but the request was denied."
, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), fwd->listen_host
, fwd->listen_port)
;
3943 else
3944 logit("Received request from %.100s port %d to remote "sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3946
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Received request from %.100s port %d to remote "
"forward, but the request was denied.", ssh_remote_ipaddr(ssh
), ssh_remote_port(ssh))
3945 "forward, but the request was denied.",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3946
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Received request from %.100s port %d to remote "
"forward, but the request was denied.", ssh_remote_ipaddr(ssh
), ssh_remote_port(ssh))
3946 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3946
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Received request from %.100s port %d to remote "
"forward, but the request was denied.", ssh_remote_ipaddr(ssh
), ssh_remote_port(ssh))
;
3947 return 0;
3948 }
3949 if (fwd->listen_path != NULL((void *)0)) {
3950 return channel_setup_fwd_listener_streamlocal(ssh,
3951 SSH_CHANNEL_RUNIX_LISTENER19, fwd, fwd_opts);
3952 } else {
3953 return channel_setup_fwd_listener_tcpip(ssh,
3954 SSH_CHANNEL_RPORT_LISTENER11, fwd, allocated_listen_port,
3955 fwd_opts);
3956 }
3957}
3958
3959/*
3960 * Translate the requested rfwd listen host to something usable for
3961 * this server.
3962 */
3963static const char *
3964channel_rfwd_bind_host(const char *listen_host)
3965{
3966 if (listen_host == NULL((void *)0)) {
3967 return "localhost";
3968 } else if (*listen_host == '\0' || strcmp(listen_host, "*") == 0) {
3969 return "";
3970 } else
3971 return listen_host;
3972}
3973
3974/*
3975 * Initiate forwarding of connections to port "port" on remote host through
3976 * the secure channel to host:port from local side.
3977 * Returns handle (index) for updating the dynamic listen port with
3978 * channel_update_permission().
3979 */
3980int
3981channel_request_remote_forwarding(struct ssh *ssh, struct Forward *fwd)
3982{
3983 int r, success = 0, idx = -1;
3984 char *host_to_connect, *listen_host, *listen_path;
3985 int port_to_connect, listen_port;
3986
3987 /* Send the forward request to the remote side. */
3988 if (fwd->listen_path != NULL((void *)0)) {
3989 if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST80)) != 0 ||
3990 (r = sshpkt_put_cstring(ssh,
3991 "streamlocal-forward@openssh.com")) != 0 ||
3992 (r = sshpkt_put_u8(ssh, 1)) != 0 || /* want reply */
3993 (r = sshpkt_put_cstring(ssh, fwd->listen_path)) != 0 ||
3994 (r = sshpkt_send(ssh)) != 0 ||
3995 (r = ssh_packet_write_wait(ssh)) != 0)
3996 fatal_fr(r, "request streamlocal")sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 3996
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "request streamlocal")
;
3997 } else {
3998 if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST80)) != 0 ||
3999 (r = sshpkt_put_cstring(ssh, "tcpip-forward")) != 0 ||
4000 (r = sshpkt_put_u8(ssh, 1)) != 0 || /* want reply */
4001 (r = sshpkt_put_cstring(ssh,
4002 channel_rfwd_bind_host(fwd->listen_host))) != 0 ||
4003 (r = sshpkt_put_u32(ssh, fwd->listen_port)) != 0 ||
4004 (r = sshpkt_send(ssh)) != 0 ||
4005 (r = ssh_packet_write_wait(ssh)) != 0)
4006 fatal_fr(r, "request tcpip-forward")sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4006
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "request tcpip-forward")
;
4007 }
4008 /* Assume that server accepts the request */
4009 success = 1;
4010 if (success) {
4011 /* Record that connection to this host/port is permitted. */
4012 host_to_connect = listen_host = listen_path = NULL((void *)0);
4013 port_to_connect = listen_port = 0;
Value stored to 'port_to_connect' is never read
4014 if (fwd->connect_path != NULL((void *)0)) {
4015 host_to_connect = xstrdup(fwd->connect_path);
4016 port_to_connect = PORT_STREAMLOCAL-2;
4017 } else {
4018 host_to_connect = xstrdup(fwd->connect_host);
4019 port_to_connect = fwd->connect_port;
4020 }
4021 if (fwd->listen_path != NULL((void *)0)) {
4022 listen_path = xstrdup(fwd->listen_path);
4023 listen_port = PORT_STREAMLOCAL-2;
4024 } else {
4025 if (fwd->listen_host != NULL((void *)0))
4026 listen_host = xstrdup(fwd->listen_host);
4027 listen_port = fwd->listen_port;
4028 }
4029 idx = permission_set_add(ssh, FORWARD_USER0x101, FORWARD_LOCAL(1<<1),
4030 host_to_connect, port_to_connect,
4031 listen_host, listen_path, listen_port, NULL((void *)0));
4032 }
4033 return idx;
4034}
4035
4036static int
4037open_match(struct permission *allowed_open, const char *requestedhost,
4038 int requestedport)
4039{
4040 if (allowed_open->host_to_connect == NULL((void *)0))
4041 return 0;
4042 if (allowed_open->port_to_connect != FWD_PERMIT_ANY_PORT0 &&
4043 allowed_open->port_to_connect != requestedport)
4044 return 0;
4045 if (strcmp(allowed_open->host_to_connect, FWD_PERMIT_ANY_HOST"*") != 0 &&
4046 strcmp(allowed_open->host_to_connect, requestedhost) != 0)
4047 return 0;
4048 return 1;
4049}
4050
4051/*
4052 * Note that in the listen host/port case
4053 * we don't support FWD_PERMIT_ANY_PORT and
4054 * need to translate between the configured-host (listen_host)
4055 * and what we've sent to the remote server (channel_rfwd_bind_host)
4056 */
4057static int
4058open_listen_match_tcpip(struct permission *allowed_open,
4059 const char *requestedhost, u_short requestedport, int translate)
4060{
4061 const char *allowed_host;
4062
4063 if (allowed_open->host_to_connect == NULL((void *)0))
4064 return 0;
4065 if (allowed_open->listen_port != requestedport)
4066 return 0;
4067 if (!translate && allowed_open->listen_host == NULL((void *)0) &&
4068 requestedhost == NULL((void *)0))
4069 return 1;
4070 allowed_host = translate ?
4071 channel_rfwd_bind_host(allowed_open->listen_host) :
4072 allowed_open->listen_host;
4073 if (allowed_host == NULL((void *)0) || requestedhost == NULL((void *)0) ||
4074 strcmp(allowed_host, requestedhost) != 0)
4075 return 0;
4076 return 1;
4077}
4078
4079static int
4080open_listen_match_streamlocal(struct permission *allowed_open,
4081 const char *requestedpath)
4082{
4083 if (allowed_open->host_to_connect == NULL((void *)0))
4084 return 0;
4085 if (allowed_open->listen_port != PORT_STREAMLOCAL-2)
4086 return 0;
4087 if (allowed_open->listen_path == NULL((void *)0) ||
4088 strcmp(allowed_open->listen_path, requestedpath) != 0)
4089 return 0;
4090 return 1;
4091}
4092
4093/*
4094 * Request cancellation of remote forwarding of connection host:port from
4095 * local side.
4096 */
4097static int
4098channel_request_rforward_cancel_tcpip(struct ssh *ssh,
4099 const char *host, u_short port)
4100{
4101 struct ssh_channels *sc = ssh->chanctxt;
4102 struct permission_set *pset = &sc->local_perms;
4103 int r;
4104 u_int i;
4105 struct permission *perm = NULL((void *)0);
4106
4107 for (i = 0; i < pset->num_permitted_user; i++) {
4108 perm = &pset->permitted_user[i];
4109 if (open_listen_match_tcpip(perm, host, port, 0))
4110 break;
4111 perm = NULL((void *)0);
4112 }
4113 if (perm == NULL((void *)0)) {
4114 debug_f("requested forward not found")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4114
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "requested forward not found"
)
;
4115 return -1;
4116 }
4117 if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST80)) != 0 ||
4118 (r = sshpkt_put_cstring(ssh, "cancel-tcpip-forward")) != 0 ||
4119 (r = sshpkt_put_u8(ssh, 0)) != 0 || /* want reply */
4120 (r = sshpkt_put_cstring(ssh, channel_rfwd_bind_host(host))) != 0 ||
4121 (r = sshpkt_put_u32(ssh, port)) != 0 ||
4122 (r = sshpkt_send(ssh)) != 0)
4123 fatal_fr(r, "send cancel")sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4123
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "send cancel")
;
4124
4125 fwd_perm_clear(perm); /* unregister */
4126
4127 return 0;
4128}
4129
4130/*
4131 * Request cancellation of remote forwarding of Unix domain socket
4132 * path from local side.
4133 */
4134static int
4135channel_request_rforward_cancel_streamlocal(struct ssh *ssh, const char *path)
4136{
4137 struct ssh_channels *sc = ssh->chanctxt;
4138 struct permission_set *pset = &sc->local_perms;
4139 int r;
4140 u_int i;
4141 struct permission *perm = NULL((void *)0);
4142
4143 for (i = 0; i < pset->num_permitted_user; i++) {
4144 perm = &pset->permitted_user[i];
4145 if (open_listen_match_streamlocal(perm, path))
4146 break;
4147 perm = NULL((void *)0);
4148 }
4149 if (perm == NULL((void *)0)) {
4150 debug_f("requested forward not found")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4150
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "requested forward not found"
)
;
4151 return -1;
4152 }
4153 if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST80)) != 0 ||
4154 (r = sshpkt_put_cstring(ssh,
4155 "cancel-streamlocal-forward@openssh.com")) != 0 ||
4156 (r = sshpkt_put_u8(ssh, 0)) != 0 || /* want reply */
4157 (r = sshpkt_put_cstring(ssh, path)) != 0 ||
4158 (r = sshpkt_send(ssh)) != 0)
4159 fatal_fr(r, "send cancel")sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4159
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "send cancel")
;
4160
4161 fwd_perm_clear(perm); /* unregister */
4162
4163 return 0;
4164}
4165
4166/*
4167 * Request cancellation of remote forwarding of a connection from local side.
4168 */
4169int
4170channel_request_rforward_cancel(struct ssh *ssh, struct Forward *fwd)
4171{
4172 if (fwd->listen_path != NULL((void *)0)) {
4173 return channel_request_rforward_cancel_streamlocal(ssh,
4174 fwd->listen_path);
4175 } else {
4176 return channel_request_rforward_cancel_tcpip(ssh,
4177 fwd->listen_host,
4178 fwd->listen_port ? fwd->listen_port : fwd->allocated_port);
4179 }
4180}
4181
4182/*
4183 * Permits opening to any host/port if permitted_user[] is empty. This is
4184 * usually called by the server, because the user could connect to any port
4185 * anyway, and the server has no way to know but to trust the client anyway.
4186 */
4187void
4188channel_permit_all(struct ssh *ssh, int where)
4189{
4190 struct permission_set *pset = permission_set_get(ssh, where);
4191
4192 if (pset->num_permitted_user == 0)
4193 pset->all_permitted = 1;
4194}
4195
4196/*
4197 * Permit the specified host/port for forwarding.
4198 */
4199void
4200channel_add_permission(struct ssh *ssh, int who, int where,
4201 char *host, int port)
4202{
4203 int local = where == FORWARD_LOCAL(1<<1);
4204 struct permission_set *pset = permission_set_get(ssh, where);
4205
4206 debug("allow %s forwarding to host %s port %d",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4207
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "allow %s forwarding to host %s port %d"
, fwd_ident(who, where), host, port)
4207 fwd_ident(who, where), host, port)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4207
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "allow %s forwarding to host %s port %d"
, fwd_ident(who, where), host, port)
;
4208 /*
4209 * Remote forwards set listen_host/port, local forwards set
4210 * host/port_to_connect.
4211 */
4212 permission_set_add(ssh, who, where,
4213 local ? host : 0, local ? port : 0,
4214 local ? NULL((void *)0) : host, NULL((void *)0), local ? 0 : port, NULL((void *)0));
4215 pset->all_permitted = 0;
4216}
4217
4218/*
4219 * Administratively disable forwarding.
4220 */
4221void
4222channel_disable_admin(struct ssh *ssh, int where)
4223{
4224 channel_clear_permission(ssh, FORWARD_ADM0x100, where);
4225 permission_set_add(ssh, FORWARD_ADM0x100, where,
4226 NULL((void *)0), 0, NULL((void *)0), NULL((void *)0), 0, NULL((void *)0));
4227}
4228
4229/*
4230 * Clear a list of permitted opens.
4231 */
4232void
4233channel_clear_permission(struct ssh *ssh, int who, int where)
4234{
4235 struct permission **permp;
4236 u_int *npermp;
4237
4238 permission_set_get_array(ssh, who, where, &permp, &npermp);
4239 *permp = xrecallocarray(*permp, *npermp, 0, sizeof(**permp));
4240 *npermp = 0;
4241}
4242
4243/*
4244 * Update the listen port for a dynamic remote forward, after
4245 * the actual 'newport' has been allocated. If 'newport' < 0 is
4246 * passed then they entry will be invalidated.
4247 */
4248void
4249channel_update_permission(struct ssh *ssh, int idx, int newport)
4250{
4251 struct permission_set *pset = &ssh->chanctxt->local_perms;
4252
4253 if (idx < 0 || (u_int)idx >= pset->num_permitted_user) {
4254 debug_f("index out of range: %d num_permitted_user %d",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4255
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "index out of range: %d num_permitted_user %d"
, idx, pset->num_permitted_user)
4255 idx, pset->num_permitted_user)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4255
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "index out of range: %d num_permitted_user %d"
, idx, pset->num_permitted_user)
;
4256 return;
4257 }
4258 debug("%s allowed port %d for forwarding to host %s port %d",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4262
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "%s allowed port %d for forwarding to host %s port %d"
, newport > 0 ? "Updating" : "Removing", newport, pset->
permitted_user[idx].host_to_connect, pset->permitted_user[
idx].port_to_connect)
4259 newport > 0 ? "Updating" : "Removing",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4262
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "%s allowed port %d for forwarding to host %s port %d"
, newport > 0 ? "Updating" : "Removing", newport, pset->
permitted_user[idx].host_to_connect, pset->permitted_user[
idx].port_to_connect)
4260 newport,sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4262
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "%s allowed port %d for forwarding to host %s port %d"
, newport > 0 ? "Updating" : "Removing", newport, pset->
permitted_user[idx].host_to_connect, pset->permitted_user[
idx].port_to_connect)
4261 pset->permitted_user[idx].host_to_connect,sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4262
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "%s allowed port %d for forwarding to host %s port %d"
, newport > 0 ? "Updating" : "Removing", newport, pset->
permitted_user[idx].host_to_connect, pset->permitted_user[
idx].port_to_connect)
4262 pset->permitted_user[idx].port_to_connect)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4262
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "%s allowed port %d for forwarding to host %s port %d"
, newport > 0 ? "Updating" : "Removing", newport, pset->
permitted_user[idx].host_to_connect, pset->permitted_user[
idx].port_to_connect)
;
4263 if (newport <= 0)
4264 fwd_perm_clear(&pset->permitted_user[idx]);
4265 else {
4266 pset->permitted_user[idx].listen_port =
4267 (ssh->compat & SSH_BUG_DYNAMIC_RPORT0x08000000) ? 0 : newport;
4268 }
4269}
4270
4271/* returns port number, FWD_PERMIT_ANY_PORT or -1 on error */
4272int
4273permitopen_port(const char *p)
4274{
4275 int port;
4276
4277 if (strcmp(p, "*") == 0)
4278 return FWD_PERMIT_ANY_PORT0;
4279 if ((port = a2port(p)) > 0)
4280 return port;
4281 return -1;
4282}
4283
4284/* Try to start non-blocking connect to next host in cctx list */
4285static int
4286connect_next(struct channel_connect *cctx)
4287{
4288 int sock, saved_errno;
4289 struct sockaddr_un *sunaddr;
4290 char ntop[NI_MAXHOST256];
4291 char strport[MAXIMUM(NI_MAXSERV, sizeof(sunaddr->sun_path))(((32) > (sizeof(sunaddr->sun_path))) ? (32) : (sizeof(
sunaddr->sun_path)))
];
4292
4293 for (; cctx->ai; cctx->ai = cctx->ai->ai_next) {
4294 switch (cctx->ai->ai_family) {
4295 case AF_UNIX1:
4296 /* unix:pathname instead of host:port */
4297 sunaddr = (struct sockaddr_un *)cctx->ai->ai_addr;
4298 strlcpy(ntop, "unix", sizeof(ntop));
4299 strlcpy(strport, sunaddr->sun_path, sizeof(strport));
4300 break;
4301 case AF_INET2:
4302 case AF_INET624:
4303 if (getnameinfo(cctx->ai->ai_addr, cctx->ai->ai_addrlen,
4304 ntop, sizeof(ntop), strport, sizeof(strport),
4305 NI_NUMERICHOST1|NI_NUMERICSERV2) != 0) {
4306 error("connect_next: getnameinfo failed")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4306
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "connect_next: getnameinfo failed"
)
;
4307 continue;
4308 }
4309 break;
4310 default:
4311 continue;
4312 }
4313 if ((sock = socket(cctx->ai->ai_family, cctx->ai->ai_socktype,
4314 cctx->ai->ai_protocol)) == -1) {
4315 if (cctx->ai->ai_next == NULL((void *)0))
4316 error("socket: %.100s", strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4316
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "socket: %.100s", strerror
((*__errno())))
;
4317 else
4318 verbose("socket: %.100s", strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4318
, 0, SYSLOG_LEVEL_VERBOSE, ((void *)0), "socket: %.100s", strerror
((*__errno())))
;
4319 continue;
4320 }
4321 if (set_nonblock(sock) == -1)
4322 fatal_f("set_nonblock(%d)", sock)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4322
, 1, SYSLOG_LEVEL_FATAL, ((void *)0), "set_nonblock(%d)", sock
)
;
4323 if (connect(sock, cctx->ai->ai_addr,
4324 cctx->ai->ai_addrlen) == -1 && errno(*__errno()) != EINPROGRESS36) {
4325 debug("connect_next: host %.100s ([%.100s]:%s): "sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4327
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "connect_next: host %.100s ([%.100s]:%s): "
"%.100s", cctx->host, ntop, strport, strerror((*__errno()
)))
4326 "%.100s", cctx->host, ntop, strport,sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4327
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "connect_next: host %.100s ([%.100s]:%s): "
"%.100s", cctx->host, ntop, strport, strerror((*__errno()
)))
4327 strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4327
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "connect_next: host %.100s ([%.100s]:%s): "
"%.100s", cctx->host, ntop, strport, strerror((*__errno()
)))
;
4328 saved_errno = errno(*__errno());
4329 close(sock);
4330 errno(*__errno()) = saved_errno;
4331 continue; /* fail -- try next */
4332 }
4333 if (cctx->ai->ai_family != AF_UNIX1)
4334 set_nodelay(sock);
4335 debug("connect_next: host %.100s ([%.100s]:%s) "sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4336
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "connect_next: host %.100s ([%.100s]:%s) "
"in progress, fd=%d", cctx->host, ntop, strport, sock)
4336 "in progress, fd=%d", cctx->host, ntop, strport, sock)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4336
, 0, SYSLOG_LEVEL_DEBUG1, ((void *)0), "connect_next: host %.100s ([%.100s]:%s) "
"in progress, fd=%d", cctx->host, ntop, strport, sock)
;
4337 cctx->ai = cctx->ai->ai_next;
4338 return sock;
4339 }
4340 return -1;
4341}
4342
4343static void
4344channel_connect_ctx_free(struct channel_connect *cctx)
4345{
4346 free(cctx->host);
4347 if (cctx->aitop) {
4348 if (cctx->aitop->ai_family == AF_UNIX1)
4349 free(cctx->aitop);
4350 else
4351 freeaddrinfo(cctx->aitop);
4352 }
4353 memset(cctx, 0, sizeof(*cctx));
4354}
4355
4356/*
4357 * Return connecting socket to remote host:port or local socket path,
4358 * passing back the failure reason if appropriate.
4359 */
4360static int
4361connect_to_helper(struct ssh *ssh, const char *name, int port, int socktype,
4362 char *ctype, char *rname, struct channel_connect *cctx,
4363 int *reason, const char **errmsg)
4364{
4365 struct addrinfo hints;
4366 int gaierr;
4367 int sock = -1;
4368 char strport[NI_MAXSERV32];
4369
4370 if (port == PORT_STREAMLOCAL-2) {
4371 struct sockaddr_un *sunaddr;
4372 struct addrinfo *ai;
4373
4374 if (strlen(name) > sizeof(sunaddr->sun_path)) {
4375 error("%.100s: %.100s", name, strerror(ENAMETOOLONG))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4375
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.100s: %.100s", name,
strerror(63))
;
4376 return -1;
4377 }
4378
4379 /*
4380 * Fake up a struct addrinfo for AF_UNIX connections.
4381 * channel_connect_ctx_free() must check ai_family
4382 * and use free() not freeaddirinfo() for AF_UNIX.
4383 */
4384 ai = xmalloc(sizeof(*ai) + sizeof(*sunaddr));
4385 memset(ai, 0, sizeof(*ai) + sizeof(*sunaddr));
4386 ai->ai_addr = (struct sockaddr *)(ai + 1);
4387 ai->ai_addrlen = sizeof(*sunaddr);
4388 ai->ai_family = AF_UNIX1;
4389 ai->ai_socktype = socktype;
4390 ai->ai_protocol = PF_UNSPEC0;
4391 sunaddr = (struct sockaddr_un *)ai->ai_addr;
4392 sunaddr->sun_family = AF_UNIX1;
4393 strlcpy(sunaddr->sun_path, name, sizeof(sunaddr->sun_path));
4394 cctx->aitop = ai;
4395 } else {
4396 memset(&hints, 0, sizeof(hints));
4397 hints.ai_family = ssh->chanctxt->IPv4or6;
4398 hints.ai_socktype = socktype;
4399 snprintf(strport, sizeof strport, "%d", port);
4400 if ((gaierr = getaddrinfo(name, strport, &hints, &cctx->aitop))
4401 != 0) {
4402 if (errmsg != NULL((void *)0))
4403 *errmsg = ssh_gai_strerror(gaierr);
4404 if (reason != NULL((void *)0))
4405 *reason = SSH2_OPEN_CONNECT_FAILED2;
4406 error("connect_to %.100s: unknown host (%s)", name,sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4407
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "connect_to %.100s: unknown host (%s)"
, name, ssh_gai_strerror(gaierr))
4407 ssh_gai_strerror(gaierr))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4407
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "connect_to %.100s: unknown host (%s)"
, name, ssh_gai_strerror(gaierr))
;
4408 return -1;
4409 }
4410 }
4411
4412 cctx->host = xstrdup(name);
4413 cctx->port = port;
4414 cctx->ai = cctx->aitop;
4415
4416 if ((sock = connect_next(cctx)) == -1) {
4417 error("connect to %.100s port %d failed: %s",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4418
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "connect to %.100s port %d failed: %s"
, name, port, strerror((*__errno())))
4418 name, port, strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4418
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "connect to %.100s port %d failed: %s"
, name, port, strerror((*__errno())))
;
4419 return -1;
4420 }
4421
4422 return sock;
4423}
4424
4425/* Return CONNECTING channel to remote host:port or local socket path */
4426static Channel *
4427connect_to(struct ssh *ssh, const char *host, int port,
4428 char *ctype, char *rname)
4429{
4430 struct channel_connect cctx;
4431 Channel *c;
4432 int sock;
4433
4434 memset(&cctx, 0, sizeof(cctx));
4435 sock = connect_to_helper(ssh, host, port, SOCK_STREAM1, ctype, rname,
4436 &cctx, NULL((void *)0), NULL((void *)0));
4437 if (sock == -1) {
4438 channel_connect_ctx_free(&cctx);
4439 return NULL((void *)0);
4440 }
4441 c = channel_new(ssh, ctype, SSH_CHANNEL_CONNECTING12, sock, sock, -1,
4442 CHAN_TCP_WINDOW_DEFAULT(64*(32*1024)), CHAN_TCP_PACKET_DEFAULT(32*1024), 0, rname, 1);
4443 c->host_port = port;
4444 c->path = xstrdup(host);
4445 c->connect_ctx = cctx;
4446
4447 return c;
4448}
4449
4450/*
4451 * returns either the newly connected channel or the downstream channel
4452 * that needs to deal with this connection.
4453 */
4454Channel *
4455channel_connect_by_listen_address(struct ssh *ssh, const char *listen_host,
4456 u_short listen_port, char *ctype, char *rname)
4457{
4458 struct ssh_channels *sc = ssh->chanctxt;
4459 struct permission_set *pset = &sc->local_perms;
4460 u_int i;
4461 struct permission *perm;
4462
4463 for (i = 0; i < pset->num_permitted_user; i++) {
4464 perm = &pset->permitted_user[i];
4465 if (open_listen_match_tcpip(perm,
4466 listen_host, listen_port, 1)) {
4467 if (perm->downstream)
4468 return perm->downstream;
4469 if (perm->port_to_connect == 0)
4470 return rdynamic_connect_prepare(ssh,
4471 ctype, rname);
4472 return connect_to(ssh,
4473 perm->host_to_connect, perm->port_to_connect,
4474 ctype, rname);
4475 }
4476 }
4477 error("WARNING: Server requests forwarding for unknown listen_port %d",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4478
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "WARNING: Server requests forwarding for unknown listen_port %d"
, listen_port)
4478 listen_port)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4478
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "WARNING: Server requests forwarding for unknown listen_port %d"
, listen_port)
;
4479 return NULL((void *)0);
4480}
4481
4482Channel *
4483channel_connect_by_listen_path(struct ssh *ssh, const char *path,
4484 char *ctype, char *rname)
4485{
4486 struct ssh_channels *sc = ssh->chanctxt;
4487 struct permission_set *pset = &sc->local_perms;
4488 u_int i;
4489 struct permission *perm;
4490
4491 for (i = 0; i < pset->num_permitted_user; i++) {
4492 perm = &pset->permitted_user[i];
4493 if (open_listen_match_streamlocal(perm, path)) {
4494 return connect_to(ssh,
4495 perm->host_to_connect, perm->port_to_connect,
4496 ctype, rname);
4497 }
4498 }
4499 error("WARNING: Server requests forwarding for unknown path %.100s",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4500
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "WARNING: Server requests forwarding for unknown path %.100s"
, path)
4500 path)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4500
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "WARNING: Server requests forwarding for unknown path %.100s"
, path)
;
4501 return NULL((void *)0);
4502}
4503
4504/* Check if connecting to that port is permitted and connect. */
4505Channel *
4506channel_connect_to_port(struct ssh *ssh, const char *host, u_short port,
4507 char *ctype, char *rname, int *reason, const char **errmsg)
4508{
4509 struct ssh_channels *sc = ssh->chanctxt;
4510 struct permission_set *pset = &sc->local_perms;
4511 struct channel_connect cctx;
4512 Channel *c;
4513 u_int i, permit, permit_adm = 1;
4514 int sock;
4515 struct permission *perm;
4516
4517 permit = pset->all_permitted;
4518 if (!permit) {
4519 for (i = 0; i < pset->num_permitted_user; i++) {
4520 perm = &pset->permitted_user[i];
4521 if (open_match(perm, host, port)) {
4522 permit = 1;
4523 break;
4524 }
4525 }
4526 }
4527
4528 if (pset->num_permitted_admin > 0) {
4529 permit_adm = 0;
4530 for (i = 0; i < pset->num_permitted_admin; i++) {
4531 perm = &pset->permitted_admin[i];
4532 if (open_match(perm, host, port)) {
4533 permit_adm = 1;
4534 break;
4535 }
4536 }
4537 }
4538
4539 if (!permit || !permit_adm) {
4540 logit("Received request from %.100s port %d to connect to "sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4542
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Received request from %.100s port %d to connect to "
"host %.100s port %d, but the request was denied.", ssh_remote_ipaddr
(ssh), ssh_remote_port(ssh), host, port)
4541 "host %.100s port %d, but the request was denied.",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4542
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Received request from %.100s port %d to connect to "
"host %.100s port %d, but the request was denied.", ssh_remote_ipaddr
(ssh), ssh_remote_port(ssh), host, port)
4542 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), host, port)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4542
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Received request from %.100s port %d to connect to "
"host %.100s port %d, but the request was denied.", ssh_remote_ipaddr
(ssh), ssh_remote_port(ssh), host, port)
;
4543 if (reason != NULL((void *)0))
4544 *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED1;
4545 return NULL((void *)0);
4546 }
4547
4548 memset(&cctx, 0, sizeof(cctx));
4549 sock = connect_to_helper(ssh, host, port, SOCK_STREAM1, ctype, rname,
4550 &cctx, reason, errmsg);
4551 if (sock == -1) {
4552 channel_connect_ctx_free(&cctx);
4553 return NULL((void *)0);
4554 }
4555
4556 c = channel_new(ssh, ctype, SSH_CHANNEL_CONNECTING12, sock, sock, -1,
4557 CHAN_TCP_WINDOW_DEFAULT(64*(32*1024)), CHAN_TCP_PACKET_DEFAULT(32*1024), 0, rname, 1);
4558 c->host_port = port;
4559 c->path = xstrdup(host);
4560 c->connect_ctx = cctx;
4561
4562 return c;
4563}
4564
4565/* Check if connecting to that path is permitted and connect. */
4566Channel *
4567channel_connect_to_path(struct ssh *ssh, const char *path,
4568 char *ctype, char *rname)
4569{
4570 struct ssh_channels *sc = ssh->chanctxt;
4571 struct permission_set *pset = &sc->local_perms;
4572 u_int i, permit, permit_adm = 1;
4573 struct permission *perm;
4574
4575 permit = pset->all_permitted;
4576 if (!permit) {
4577 for (i = 0; i < pset->num_permitted_user; i++) {
4578 perm = &pset->permitted_user[i];
4579 if (open_match(perm, path, PORT_STREAMLOCAL-2)) {
4580 permit = 1;
4581 break;
4582 }
4583 }
4584 }
4585
4586 if (pset->num_permitted_admin > 0) {
4587 permit_adm = 0;
4588 for (i = 0; i < pset->num_permitted_admin; i++) {
4589 perm = &pset->permitted_admin[i];
4590 if (open_match(perm, path, PORT_STREAMLOCAL-2)) {
4591 permit_adm = 1;
4592 break;
4593 }
4594 }
4595 }
4596
4597 if (!permit || !permit_adm) {
4598 logit("Received request to connect to path %.100s, "sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4599
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Received request to connect to path %.100s, "
"but the request was denied.", path)
4599 "but the request was denied.", path)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4599
, 0, SYSLOG_LEVEL_INFO, ((void *)0), "Received request to connect to path %.100s, "
"but the request was denied.", path)
;
4600 return NULL((void *)0);
4601 }
4602 return connect_to(ssh, path, PORT_STREAMLOCAL-2, ctype, rname);
4603}
4604
4605void
4606channel_send_window_changes(struct ssh *ssh)
4607{
4608 struct ssh_channels *sc = ssh->chanctxt;
4609 struct winsize ws;
4610 int r;
4611 u_int i;
4612
4613 for (i = 0; i < sc->channels_alloc; i++) {
4614 if (sc->channels[i] == NULL((void *)0) || !sc->channels[i]->client_tty ||
4615 sc->channels[i]->type != SSH_CHANNEL_OPEN4)
4616 continue;
4617 if (ioctl(sc->channels[i]->rfd, TIOCGWINSZ((unsigned long)0x40000000 | ((sizeof(struct winsize) & 0x1fff
) << 16) | ((('t')) << 8) | ((104)))
, &ws) == -1)
4618 continue;
4619 channel_request_start(ssh, i, "window-change", 0);
4620 if ((r = sshpkt_put_u32(ssh, (u_int)ws.ws_col)) != 0 ||
4621 (r = sshpkt_put_u32(ssh, (u_int)ws.ws_row)) != 0 ||
4622 (r = sshpkt_put_u32(ssh, (u_int)ws.ws_xpixel)) != 0 ||
4623 (r = sshpkt_put_u32(ssh, (u_int)ws.ws_ypixel)) != 0 ||
4624 (r = sshpkt_send(ssh)) != 0)
4625 fatal_fr(r, "channel %u; send window-change", i)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4625
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %u; send window-change"
, i)
;
4626 }
4627}
4628
4629/* Return RDYNAMIC_OPEN channel: channel allows SOCKS, but is not connected */
4630static Channel *
4631rdynamic_connect_prepare(struct ssh *ssh, char *ctype, char *rname)
4632{
4633 Channel *c;
4634 int r;
4635
4636 c = channel_new(ssh, ctype, SSH_CHANNEL_RDYNAMIC_OPEN21, -1, -1, -1,
4637 CHAN_TCP_WINDOW_DEFAULT(64*(32*1024)), CHAN_TCP_PACKET_DEFAULT(32*1024), 0, rname, 1);
4638 c->host_port = 0;
4639 c->path = NULL((void *)0);
4640
4641 /*
4642 * We need to open the channel before we have a FD,
4643 * so that we can get SOCKS header from peer.
4644 */
4645 if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION91)) != 0 ||
4646 (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
4647 (r = sshpkt_put_u32(ssh, c->self)) != 0 ||
4648 (r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||
4649 (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0)
4650 fatal_fr(r, "channel %i; confirm", c->self)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4650
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "channel %i; confirm", c
->self)
;
4651 return c;
4652}
4653
4654/* Return CONNECTING socket to remote host:port or local socket path */
4655static int
4656rdynamic_connect_finish(struct ssh *ssh, Channel *c)
4657{
4658 struct ssh_channels *sc = ssh->chanctxt;
4659 struct permission_set *pset = &sc->local_perms;
4660 struct permission *perm;
4661 struct channel_connect cctx;
4662 u_int i, permit_adm = 1;
4663 int sock;
4664
4665 if (pset->num_permitted_admin > 0) {
4666 permit_adm = 0;
4667 for (i = 0; i < pset->num_permitted_admin; i++) {
4668 perm = &pset->permitted_admin[i];
4669 if (open_match(perm, c->path, c->host_port)) {
4670 permit_adm = 1;
4671 break;
4672 }
4673 }
4674 }
4675 if (!permit_adm) {
4676 debug_f("requested forward not permitted")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4676
, 1, SYSLOG_LEVEL_DEBUG1, ((void *)0), "requested forward not permitted"
)
;
4677 return -1;
4678 }
4679
4680 memset(&cctx, 0, sizeof(cctx));
4681 sock = connect_to_helper(ssh, c->path, c->host_port, SOCK_STREAM1, NULL((void *)0),
4682 NULL((void *)0), &cctx, NULL((void *)0), NULL((void *)0));
4683 if (sock == -1)
4684 channel_connect_ctx_free(&cctx);
4685 else {
4686 /* similar to SSH_CHANNEL_CONNECTING but we've already sent the open */
4687 c->type = SSH_CHANNEL_RDYNAMIC_FINISH22;
4688 c->connect_ctx = cctx;
4689 channel_register_fds(ssh, c, sock, sock, -1, 0, 1, 0);
4690 }
4691 return sock;
4692}
4693
4694/* -- X11 forwarding */
4695
4696/*
4697 * Creates an internet domain socket for listening for X11 connections.
4698 * Returns 0 and a suitable display number for the DISPLAY variable
4699 * stored in display_numberp , or -1 if an error occurs.
4700 */
4701int
4702x11_create_display_inet(struct ssh *ssh, int x11_display_offset,
4703 int x11_use_localhost, int single_connection,
4704 u_int *display_numberp, int **chanids)
4705{
4706 Channel *nc = NULL((void *)0);
4707 int display_number, sock;
4708 u_short port;
4709 struct addrinfo hints, *ai, *aitop;
4710 char strport[NI_MAXSERV32];
4711 int gaierr, n, num_socks = 0, socks[NUM_SOCKS10];
4712
4713 if (chanids == NULL((void *)0))
4714 return -1;
4715
4716 for (display_number = x11_display_offset;
4717 display_number < MAX_DISPLAYS1000;
4718 display_number++) {
4719 port = 6000 + display_number;
4720 memset(&hints, 0, sizeof(hints));
4721 hints.ai_family = ssh->chanctxt->IPv4or6;
4722 hints.ai_flags = x11_use_localhost ? 0: AI_PASSIVE1;
4723 hints.ai_socktype = SOCK_STREAM1;
4724 snprintf(strport, sizeof strport, "%d", port);
4725 if ((gaierr = getaddrinfo(NULL((void *)0), strport,
4726 &hints, &aitop)) != 0) {
4727 error("getaddrinfo: %.100s", ssh_gai_strerror(gaierr))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4727
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "getaddrinfo: %.100s", ssh_gai_strerror
(gaierr))
;
4728 return -1;
4729 }
4730 for (ai = aitop; ai; ai = ai->ai_next) {
4731 if (ai->ai_family != AF_INET2 &&
4732 ai->ai_family != AF_INET624)
4733 continue;
4734 sock = socket(ai->ai_family, ai->ai_socktype,
4735 ai->ai_protocol);
4736 if (sock == -1) {
4737 error("socket: %.100s", strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4737
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "socket: %.100s", strerror
((*__errno())))
;
4738 freeaddrinfo(aitop);
4739 return -1;
4740 }
4741 set_reuseaddr(sock);
4742 if (bind(sock, ai->ai_addr, ai->ai_addrlen) == -1) {
4743 debug2_f("bind port %d: %.100s", port,sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4744
, 1, SYSLOG_LEVEL_DEBUG2, ((void *)0), "bind port %d: %.100s"
, port, strerror((*__errno())))
4744 strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4744
, 1, SYSLOG_LEVEL_DEBUG2, ((void *)0), "bind port %d: %.100s"
, port, strerror((*__errno())))
;
4745 close(sock);
4746 for (n = 0; n < num_socks; n++)
4747 close(socks[n]);
4748 num_socks = 0;
4749 break;
4750 }
4751 socks[num_socks++] = sock;
4752 if (num_socks == NUM_SOCKS10)
4753 break;
4754 }
4755 freeaddrinfo(aitop);
4756 if (num_socks > 0)
4757 break;
4758 }
4759 if (display_number >= MAX_DISPLAYS1000) {
4760 error("Failed to allocate internet-domain X11 display socket.")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4760
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Failed to allocate internet-domain X11 display socket."
)
;
4761 return -1;
4762 }
4763 /* Start listening for connections on the socket. */
4764 for (n = 0; n < num_socks; n++) {
4765 sock = socks[n];
4766 if (listen(sock, SSH_LISTEN_BACKLOG128) == -1) {
4767 error("listen: %.100s", strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4767
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "listen: %.100s", strerror
((*__errno())))
;
4768 close(sock);
4769 return -1;
4770 }
4771 }
4772
4773 /* Allocate a channel for each socket. */
4774 *chanids = xcalloc(num_socks + 1, sizeof(**chanids));
4775 for (n = 0; n < num_socks; n++) {
4776 sock = socks[n];
4777 nc = channel_new(ssh, "x11 listener",
4778 SSH_CHANNEL_X11_LISTENER1, sock, sock, -1,
4779 CHAN_X11_WINDOW_DEFAULT(4*(16*1024)), CHAN_X11_PACKET_DEFAULT(16*1024),
4780 0, "X11 inet listener", 1);
4781 nc->single_connection = single_connection;
4782 (*chanids)[n] = nc->self;
4783 }
4784 (*chanids)[n] = -1;
4785
4786 /* Return the display number for the DISPLAY environment variable. */
4787 *display_numberp = display_number;
4788 return 0;
4789}
4790
4791static int
4792connect_local_xsocket(u_int dnr)
4793{
4794 int sock;
4795 struct sockaddr_un addr;
4796
4797 sock = socket(AF_UNIX1, SOCK_STREAM1, 0);
4798 if (sock == -1)
4799 error("socket: %.100s", strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4799
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "socket: %.100s", strerror
((*__errno())))
;
4800 memset(&addr, 0, sizeof(addr));
4801 addr.sun_family = AF_UNIX1;
4802 snprintf(addr.sun_path, sizeof addr.sun_path, _PATH_UNIX_X"/tmp/.X11-unix/X%u", dnr);
4803 if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0)
4804 return sock;
4805 close(sock);
4806 error("connect %.100s: %.100s", addr.sun_path, strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4806
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "connect %.100s: %.100s"
, addr.sun_path, strerror((*__errno())))
;
4807 return -1;
4808}
4809
4810int
4811x11_connect_display(struct ssh *ssh)
4812{
4813 u_int display_number;
4814 const char *display;
4815 char buf[1024], *cp;
4816 struct addrinfo hints, *ai, *aitop;
4817 char strport[NI_MAXSERV32];
4818 int gaierr, sock = 0;
4819
4820 /* Try to open a socket for the local X server. */
4821 display = getenv("DISPLAY");
4822 if (!display) {
4823 error("DISPLAY not set.")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4823
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "DISPLAY not set.")
;
4824 return -1;
4825 }
4826 /*
4827 * Now we decode the value of the DISPLAY variable and make a
4828 * connection to the real X server.
4829 */
4830
4831 /*
4832 * Check if it is a unix domain socket. Unix domain displays are in
4833 * one of the following formats: unix:d[.s], :d[.s], ::d[.s]
4834 */
4835 if (strncmp(display, "unix:", 5) == 0 ||
4836 display[0] == ':') {
4837 /* Connect to the unix domain socket. */
4838 if (sscanf(strrchr(display, ':') + 1, "%u",
4839 &display_number) != 1) {
4840 error("Could not parse display number from DISPLAY: "sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4841
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Could not parse display number from DISPLAY: "
"%.100s", display)
4841 "%.100s", display)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4841
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Could not parse display number from DISPLAY: "
"%.100s", display)
;
4842 return -1;
4843 }
4844 /* Create a socket. */
4845 sock = connect_local_xsocket(display_number);
4846 if (sock < 0)
4847 return -1;
4848
4849 /* OK, we now have a connection to the display. */
4850 return sock;
4851 }
4852 /*
4853 * Connect to an inet socket. The DISPLAY value is supposedly
4854 * hostname:d[.s], where hostname may also be numeric IP address.
4855 */
4856 strlcpy(buf, display, sizeof(buf));
4857 cp = strchr(buf, ':');
4858 if (!cp) {
4859 error("Could not find ':' in DISPLAY: %.100s", display)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4859
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Could not find ':' in DISPLAY: %.100s"
, display)
;
4860 return -1;
4861 }
4862 *cp = 0;
4863 /*
4864 * buf now contains the host name. But first we parse the
4865 * display number.
4866 */
4867 if (sscanf(cp + 1, "%u", &display_number) != 1) {
4868 error("Could not parse display number from DISPLAY: %.100s",sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4869
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Could not parse display number from DISPLAY: %.100s"
, display)
4869 display)sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4869
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "Could not parse display number from DISPLAY: %.100s"
, display)
;
4870 return -1;
4871 }
4872
4873 /* Look up the host address */
4874 memset(&hints, 0, sizeof(hints));
4875 hints.ai_family = ssh->chanctxt->IPv4or6;
4876 hints.ai_socktype = SOCK_STREAM1;
4877 snprintf(strport, sizeof strport, "%u", 6000 + display_number);
4878 if ((gaierr = getaddrinfo(buf, strport, &hints, &aitop)) != 0) {
4879 error("%.100s: unknown host. (%s)", buf,sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4880
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.100s: unknown host. (%s)"
, buf, ssh_gai_strerror(gaierr))
4880 ssh_gai_strerror(gaierr))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4880
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "%.100s: unknown host. (%s)"
, buf, ssh_gai_strerror(gaierr))
;
4881 return -1;
4882 }
4883 for (ai = aitop; ai; ai = ai->ai_next) {
4884 /* Create a socket. */
4885 sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
4886 if (sock == -1) {
4887 debug2("socket: %.100s", strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4887
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "socket: %.100s", strerror
((*__errno())))
;
4888 continue;
4889 }
4890 /* Connect it to the display. */
4891 if (connect(sock, ai->ai_addr, ai->ai_addrlen) == -1) {
4892 debug2("connect %.100s port %u: %.100s", buf,sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4893
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "connect %.100s port %u: %.100s"
, buf, 6000 + display_number, strerror((*__errno())))
4893 6000 + display_number, strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4893
, 0, SYSLOG_LEVEL_DEBUG2, ((void *)0), "connect %.100s port %u: %.100s"
, buf, 6000 + display_number, strerror((*__errno())))
;
4894 close(sock);
4895 continue;
4896 }
4897 /* Success */
4898 break;
4899 }
4900 freeaddrinfo(aitop);
4901 if (!ai) {
4902 error("connect %.100s port %u: %.100s", buf,sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4903
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "connect %.100s port %u: %.100s"
, buf, 6000 + display_number, strerror((*__errno())))
4903 6000 + display_number, strerror(errno))sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4903
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "connect %.100s port %u: %.100s"
, buf, 6000 + display_number, strerror((*__errno())))
;
4904 return -1;
4905 }
4906 set_nodelay(sock);
4907 return sock;
4908}
4909
4910/*
4911 * Requests forwarding of X11 connections, generates fake authentication
4912 * data, and enables authentication spoofing.
4913 * This should be called in the client only.
4914 */
4915void
4916x11_request_forwarding_with_spoofing(struct ssh *ssh, int client_session_id,
4917 const char *disp, const char *proto, const char *data, int want_reply)
4918{
4919 struct ssh_channels *sc = ssh->chanctxt;
4920 u_int data_len = (u_int) strlen(data) / 2;
4921 u_int i, value;
4922 const char *cp;
4923 char *new_data;
4924 int r, screen_number;
4925
4926 if (sc->x11_saved_display == NULL((void *)0))
4927 sc->x11_saved_display = xstrdup(disp);
4928 else if (strcmp(disp, sc->x11_saved_display) != 0) {
4929 error("x11_request_forwarding_with_spoofing: different "sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4930
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "x11_request_forwarding_with_spoofing: different "
"$DISPLAY already forwarded")
4930 "$DISPLAY already forwarded")sshlog("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4930
, 0, SYSLOG_LEVEL_ERROR, ((void *)0), "x11_request_forwarding_with_spoofing: different "
"$DISPLAY already forwarded")
;
4931 return;
4932 }
4933
4934 cp = strchr(disp, ':');
4935 if (cp)
4936 cp = strchr(cp, '.');
4937 if (cp)
4938 screen_number = (u_int)strtonum(cp + 1, 0, 400, NULL((void *)0));
4939 else
4940 screen_number = 0;
4941
4942 if (sc->x11_saved_proto == NULL((void *)0)) {
4943 /* Save protocol name. */
4944 sc->x11_saved_proto = xstrdup(proto);
4945
4946 /* Extract real authentication data. */
4947 sc->x11_saved_data = xmalloc(data_len);
4948 for (i = 0; i < data_len; i++) {
4949 if (sscanf(data + 2 * i, "%2x", &value) != 1) {
4950 fatal("x11_request_forwarding: bad "sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4951
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "x11_request_forwarding: bad "
"authentication data: %.100s", data)
4951 "authentication data: %.100s", data)sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4951
, 0, SYSLOG_LEVEL_FATAL, ((void *)0), "x11_request_forwarding: bad "
"authentication data: %.100s", data)
;
4952 }
4953 sc->x11_saved_data[i] = value;
4954 }
4955 sc->x11_saved_data_len = data_len;
4956
4957 /* Generate fake data of the same length. */
4958 sc->x11_fake_data = xmalloc(data_len);
4959 arc4random_buf(sc->x11_fake_data, data_len);
4960 sc->x11_fake_data_len = data_len;
4961 }
4962
4963 /* Convert the fake data into hex. */
4964 new_data = tohex(sc->x11_fake_data, data_len);
4965
4966 /* Send the request packet. */
4967 channel_request_start(ssh, client_session_id, "x11-req", want_reply);
4968 if ((r = sshpkt_put_u8(ssh, 0)) != 0 || /* bool: single connection */
4969 (r = sshpkt_put_cstring(ssh, proto)) != 0 ||
4970 (r = sshpkt_put_cstring(ssh, new_data)) != 0 ||
4971 (r = sshpkt_put_u32(ssh, screen_number)) != 0 ||
4972 (r = sshpkt_send(ssh)) != 0 ||
4973 (r = ssh_packet_write_wait(ssh)) != 0)
4974 fatal_fr(r, "send x11-req")sshfatal("/usr/src/usr.bin/ssh/ssh/../channels.c", __func__, 4974
, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), "send x11-req")
;
4975 free(new_data);
4976}