Branch data Line data Source code
1 : : /* $OpenBSD: channels.c,v 1.331 2014/02/26 20:29:29 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 "includes.h"
43 : :
44 : : #include <sys/types.h>
45 : : #include <sys/ioctl.h>
46 : : #include <sys/un.h>
47 : : #include <sys/socket.h>
48 : : #ifdef HAVE_SYS_TIME_H
49 : : # include <sys/time.h>
50 : : #endif
51 : :
52 : : #include <netinet/in.h>
53 : : #include <arpa/inet.h>
54 : :
55 : : #include <errno.h>
56 : : #include <fcntl.h>
57 : : #include <netdb.h>
58 : : #include <stdio.h>
59 : : #include <stdlib.h>
60 : : #include <string.h>
61 : : #include <termios.h>
62 : : #include <unistd.h>
63 : : #include <stdarg.h>
64 : :
65 : : #include "openbsd-compat/sys-queue.h"
66 : : #include "xmalloc.h"
67 : : #include "ssh.h"
68 : : #include "ssh1.h"
69 : : #include "ssh2.h"
70 : : #include "packet.h"
71 : : #include "log.h"
72 : : #include "misc.h"
73 : : #include "buffer.h"
74 : : #include "channels.h"
75 : : #include "compat.h"
76 : : #include "canohost.h"
77 : : #include "key.h"
78 : : #include "authfd.h"
79 : : #include "pathnames.h"
80 : :
81 : : /* -- channel core */
82 : :
83 : : /*
84 : : * Pointer to an array containing all allocated channels. The array is
85 : : * dynamically extended as needed.
86 : : */
87 : : static Channel **channels = NULL;
88 : :
89 : : /*
90 : : * Size of the channel array. All slots of the array must always be
91 : : * initialized (at least the type field); unused slots set to NULL
92 : : */
93 : : static u_int channels_alloc = 0;
94 : :
95 : : /*
96 : : * Maximum file descriptor value used in any of the channels. This is
97 : : * updated in channel_new.
98 : : */
99 : : static int channel_max_fd = 0;
100 : :
101 : :
102 : : /* -- tcp forwarding */
103 : :
104 : : /*
105 : : * Data structure for storing which hosts are permitted for forward requests.
106 : : * The local sides of any remote forwards are stored in this array to prevent
107 : : * a corrupt remote server from accessing arbitrary TCP/IP ports on our local
108 : : * network (which might be behind a firewall).
109 : : */
110 : : typedef struct {
111 : : char *host_to_connect; /* Connect to 'host'. */
112 : : u_short port_to_connect; /* Connect to 'port'. */
113 : : u_short listen_port; /* Remote side should listen port number. */
114 : : } ForwardPermission;
115 : :
116 : : /* List of all permitted host/port pairs to connect by the user. */
117 : : static ForwardPermission *permitted_opens = NULL;
118 : :
119 : : /* List of all permitted host/port pairs to connect by the admin. */
120 : : static ForwardPermission *permitted_adm_opens = NULL;
121 : :
122 : : /* Number of permitted host/port pairs in the array permitted by the user. */
123 : : static int num_permitted_opens = 0;
124 : :
125 : : /* Number of permitted host/port pair in the array permitted by the admin. */
126 : : static int num_adm_permitted_opens = 0;
127 : :
128 : : /* special-case port number meaning allow any port */
129 : : #define FWD_PERMIT_ANY_PORT 0
130 : :
131 : : /*
132 : : * If this is true, all opens are permitted. This is the case on the server
133 : : * on which we have to trust the client anyway, and the user could do
134 : : * anything after logging in anyway.
135 : : */
136 : : static int all_opens_permitted = 0;
137 : :
138 : :
139 : : /* -- X11 forwarding */
140 : :
141 : : /* Maximum number of fake X11 displays to try. */
142 : : #define MAX_DISPLAYS 1000
143 : :
144 : : /* Saved X11 local (client) display. */
145 : : static char *x11_saved_display = NULL;
146 : :
147 : : /* Saved X11 authentication protocol name. */
148 : : static char *x11_saved_proto = NULL;
149 : :
150 : : /* Saved X11 authentication data. This is the real data. */
151 : : static char *x11_saved_data = NULL;
152 : : static u_int x11_saved_data_len = 0;
153 : :
154 : : /*
155 : : * Fake X11 authentication data. This is what the server will be sending us;
156 : : * we should replace any occurrences of this by the real data.
157 : : */
158 : : static u_char *x11_fake_data = NULL;
159 : : static u_int x11_fake_data_len;
160 : :
161 : :
162 : : /* -- agent forwarding */
163 : :
164 : : #define NUM_SOCKS 10
165 : :
166 : : /* AF_UNSPEC or AF_INET or AF_INET6 */
167 : : static int IPv4or6 = AF_UNSPEC;
168 : :
169 : : /* helper */
170 : : static void port_open_helper(Channel *c, char *rtype);
171 : :
172 : : /* non-blocking connect helpers */
173 : : static int connect_next(struct channel_connect *);
174 : : static void channel_connect_ctx_free(struct channel_connect *);
175 : :
176 : : /* -- channel core */
177 : :
178 : : Channel *
179 : 15770 : channel_by_id(int id)
180 : : {
181 : : Channel *c;
182 : :
183 [ + - ][ - + ]: 15770 : if (id < 0 || (u_int)id >= channels_alloc) {
184 : 0 : logit("channel_by_id: %d: bad id", id);
185 : 0 : return NULL;
186 : : }
187 : 15770 : c = channels[id];
188 [ - + ]: 15770 : if (c == NULL) {
189 : 0 : logit("channel_by_id: %d: bad id: channel free", id);
190 : 0 : return NULL;
191 : : }
192 : : return c;
193 : : }
194 : :
195 : : /*
196 : : * Returns the channel if it is allowed to receive protocol messages.
197 : : * Private channels, like listening sockets, may not receive messages.
198 : : */
199 : : Channel *
200 : 13454 : channel_lookup(int id)
201 : : {
202 : : Channel *c;
203 : :
204 [ + - ]: 13454 : if ((c = channel_by_id(id)) == NULL)
205 : : return (NULL);
206 : :
207 [ + - ][ - + ]: 13454 : switch (c->type) {
208 : : case SSH_CHANNEL_X11_OPEN:
209 : : case SSH_CHANNEL_LARVAL:
210 : : case SSH_CHANNEL_CONNECTING:
211 : : case SSH_CHANNEL_DYNAMIC:
212 : : case SSH_CHANNEL_OPENING:
213 : : case SSH_CHANNEL_OPEN:
214 : : case SSH_CHANNEL_INPUT_DRAINING:
215 : : case SSH_CHANNEL_OUTPUT_DRAINING:
216 : : case SSH_CHANNEL_ABANDONED:
217 : : return (c);
218 : : }
219 : 0 : logit("Non-public channel %d, type %d.", id, c->type);
220 : 0 : return (NULL);
221 : : }
222 : :
223 : : /*
224 : : * Register filedescriptors for a channel, used when allocating a channel or
225 : : * when the channel consumer/producer is ready, e.g. shell exec'd
226 : : */
227 : : static void
228 : 1676 : channel_register_fds(Channel *c, int rfd, int wfd, int efd,
229 : : int extusage, int nonblock, int is_tty)
230 : : {
231 : : /* Update the maximum file descriptor value. */
232 : 1676 : channel_max_fd = MAX(channel_max_fd, rfd);
233 : 1676 : channel_max_fd = MAX(channel_max_fd, wfd);
234 : 1676 : channel_max_fd = MAX(channel_max_fd, efd);
235 : :
236 [ + + ]: 1676 : if (rfd != -1)
237 : 947 : fcntl(rfd, F_SETFD, FD_CLOEXEC);
238 [ + + ]: 1676 : if (wfd != -1 && wfd != rfd)
239 : 717 : fcntl(wfd, F_SETFD, FD_CLOEXEC);
240 [ + + ][ + - ]: 1676 : if (efd != -1 && efd != rfd && efd != wfd)
241 : 717 : fcntl(efd, F_SETFD, FD_CLOEXEC);
242 : :
243 : 1676 : c->rfd = rfd;
244 : 1676 : c->wfd = wfd;
245 [ + + ]: 1676 : c->sock = (rfd == wfd) ? rfd : -1;
246 : 1676 : c->efd = efd;
247 : 1676 : c->extended_usage = extusage;
248 : :
249 [ - + ]: 1676 : if ((c->isatty = is_tty) != 0)
250 : 0 : debug2("channel %d: rfd %d isatty", c->self, c->rfd);
251 : : #ifdef _AIX
252 : : /* XXX: Later AIX versions can't push as much data to tty */
253 : : c->wfd_isatty = is_tty || isatty(c->wfd);
254 : : #endif
255 : :
256 : : /* enable nonblocking mode */
257 [ + + ]: 1676 : if (nonblock) {
258 [ + + ]: 974 : if (rfd != -1)
259 : 245 : set_nonblock(rfd);
260 [ + + ]: 974 : if (wfd != -1)
261 : 245 : set_nonblock(wfd);
262 [ + + ]: 974 : if (efd != -1)
263 : 15 : set_nonblock(efd);
264 : : }
265 : 1676 : }
266 : :
267 : : /*
268 : : * Allocate a new channel object and set its type and socket. This will cause
269 : : * remote_name to be freed.
270 : : */
271 : : Channel *
272 : 1661 : channel_new(char *ctype, int type, int rfd, int wfd, int efd,
273 : : u_int window, u_int maxpack, int extusage, char *remote_name, int nonblock)
274 : : {
275 : : int found;
276 : : u_int i;
277 : : Channel *c;
278 : :
279 : : /* Do initial allocation if this is the first call. */
280 [ + + ]: 1661 : if (channels_alloc == 0) {
281 : 1422 : channels_alloc = 10;
282 : 1422 : channels = xcalloc(channels_alloc, sizeof(Channel *));
283 [ + + ]: 15642 : for (i = 0; i < channels_alloc; i++)
284 : 14220 : channels[i] = NULL;
285 : : }
286 : : /* Try to find a free slot where to put the new channel. */
287 [ + + ]: 3609 : for (found = -1, i = 0; i < channels_alloc; i++)
288 [ + + ]: 3600 : if (channels[i] == NULL) {
289 : : /* Found a free slot. */
290 : 1652 : found = (int)i;
291 : 1652 : break;
292 : : }
293 [ + + ]: 1661 : if (found < 0) {
294 : : /* There are no free slots. Take last+1 slot and expand the array. */
295 : 9 : found = channels_alloc;
296 [ - + ]: 9 : if (channels_alloc > 10000)
297 : 0 : fatal("channel_new: internal error: channels_alloc %d "
298 : : "too big.", channels_alloc);
299 : 9 : channels = xrealloc(channels, channels_alloc + 10,
300 : : sizeof(Channel *));
301 : 9 : channels_alloc += 10;
302 : 9 : debug2("channel: expanding %d", channels_alloc);
303 [ + + ]: 99 : for (i = found; i < channels_alloc; i++)
304 : 90 : channels[i] = NULL;
305 : : }
306 : : /* Initialize and return new channel. */
307 : 1661 : c = channels[found] = xcalloc(1, sizeof(Channel));
308 : 1661 : buffer_init(&c->input);
309 : 1661 : buffer_init(&c->output);
310 : 1661 : buffer_init(&c->extended);
311 : 1661 : c->path = NULL;
312 : 1661 : c->listening_addr = NULL;
313 : 1661 : c->listening_port = 0;
314 : 1661 : c->ostate = CHAN_OUTPUT_OPEN;
315 : 1661 : c->istate = CHAN_INPUT_OPEN;
316 : 1661 : c->flags = 0;
317 : 1661 : channel_register_fds(c, rfd, wfd, efd, extusage, nonblock, 0);
318 : 1661 : c->notbefore = 0;
319 : 1661 : c->self = found;
320 : 1661 : c->type = type;
321 : 1661 : c->ctype = ctype;
322 : 1661 : c->local_window = window;
323 : 1661 : c->local_window_max = window;
324 : 1661 : c->local_consumed = 0;
325 : 1661 : c->local_maxpacket = maxpack;
326 : 1661 : c->remote_id = -1;
327 : 1661 : c->remote_name = xstrdup(remote_name);
328 : 1661 : c->remote_window = 0;
329 : 1661 : c->remote_maxpacket = 0;
330 : 1661 : c->force_drain = 0;
331 : 1661 : c->single_connection = 0;
332 : 1661 : c->detach_user = NULL;
333 : 1661 : c->detach_close = 0;
334 : 1661 : c->open_confirm = NULL;
335 : 1661 : c->open_confirm_ctx = NULL;
336 : 1661 : c->input_filter = NULL;
337 : 1661 : c->output_filter = NULL;
338 : 1661 : c->filter_ctx = NULL;
339 : 1661 : c->filter_cleanup = NULL;
340 : 1661 : c->ctl_chan = -1;
341 : 1661 : c->mux_rcb = NULL;
342 : 1661 : c->mux_ctx = NULL;
343 : 1661 : c->mux_pause = 0;
344 : 1661 : c->delayed = 1; /* prevent call to channel_post handler */
345 : 1661 : TAILQ_INIT(&c->status_confirms);
346 : 1661 : debug("channel %d: new [%s]", found, remote_name);
347 : 1661 : return c;
348 : : }
349 : :
350 : : static int
351 : 1063 : channel_find_maxfd(void)
352 : : {
353 : : u_int i;
354 : 1063 : int max = 0;
355 : : Channel *c;
356 : :
357 [ + + ]: 14573 : for (i = 0; i < channels_alloc; i++) {
358 : 13510 : c = channels[i];
359 [ + + ]: 13510 : if (c != NULL) {
360 : 3687 : max = MAX(max, c->rfd);
361 : 3687 : max = MAX(max, c->wfd);
362 : 3687 : max = MAX(max, c->efd);
363 : : }
364 : : }
365 : 1063 : return max;
366 : : }
367 : :
368 : : int
369 : 8209 : channel_close_fd(int *fdp)
370 : : {
371 : 8209 : int ret = 0, fd = *fdp;
372 : :
373 [ + + ]: 8209 : if (fd != -1) {
374 : 2883 : ret = close(fd);
375 : 2883 : *fdp = -1;
376 [ + + ]: 2883 : if (fd == channel_max_fd)
377 : 1063 : channel_max_fd = channel_find_maxfd();
378 : : }
379 : 8209 : return ret;
380 : : }
381 : :
382 : : /* Close all channel fd/socket. */
383 : : static void
384 : 1690 : channel_close_fds(Channel *c)
385 : : {
386 : 1690 : channel_close_fd(&c->sock);
387 : 1690 : channel_close_fd(&c->rfd);
388 : 1690 : channel_close_fd(&c->wfd);
389 : 1690 : channel_close_fd(&c->efd);
390 : 1690 : }
391 : :
392 : : /* Free the channel and close its fd/socket. */
393 : : void
394 : 911 : channel_free(Channel *c)
395 : : {
396 : : char *s;
397 : : u_int i, n;
398 : : struct channel_confirm *cc;
399 : :
400 [ + + ]: 12751 : for (n = 0, i = 0; i < channels_alloc; i++)
401 [ + + ]: 11840 : if (channels[i])
402 : 2777 : n++;
403 [ + - ]: 911 : debug("channel %d: free: %s, nchannels %u", c->self,
404 : 911 : c->remote_name ? c->remote_name : "???", n);
405 : :
406 : 911 : s = channel_open_message();
407 : 911 : debug3("channel %d: status: %s", c->self, s);
408 : 911 : free(s);
409 : :
410 [ + + ]: 911 : if (c->sock != -1)
411 : 193 : shutdown(c->sock, SHUT_RDWR);
412 : 911 : channel_close_fds(c);
413 : 911 : buffer_free(&c->input);
414 : 911 : buffer_free(&c->output);
415 : 911 : buffer_free(&c->extended);
416 : 911 : free(c->remote_name);
417 : 911 : c->remote_name = NULL;
418 : 911 : free(c->path);
419 : 911 : c->path = NULL;
420 : 911 : free(c->listening_addr);
421 : 911 : c->listening_addr = NULL;
422 [ - + ]: 911 : while ((cc = TAILQ_FIRST(&c->status_confirms)) != NULL) {
423 [ # # ]: 0 : if (cc->abandon_cb != NULL)
424 : 0 : cc->abandon_cb(c, cc->ctx);
425 [ # # ]: 0 : TAILQ_REMOVE(&c->status_confirms, cc, entry);
426 : 0 : explicit_bzero(cc, sizeof(*cc));
427 : 0 : free(cc);
428 : : }
429 [ - + ][ # # ]: 911 : if (c->filter_cleanup != NULL && c->filter_ctx != NULL)
430 : 0 : c->filter_cleanup(c->self, c->filter_ctx);
431 : 911 : channels[c->self] = NULL;
432 : 911 : free(c);
433 : 911 : }
434 : :
435 : : void
436 : 775 : channel_free_all(void)
437 : : {
438 : : u_int i;
439 : :
440 [ + + ]: 7835 : for (i = 0; i < channels_alloc; i++)
441 [ + + ]: 7060 : if (channels[i] != NULL)
442 : 91 : channel_free(channels[i]);
443 : 775 : }
444 : :
445 : : /*
446 : : * Closes the sockets/fds of all channels. This is used to close extra file
447 : : * descriptors after a fork.
448 : : */
449 : : void
450 : 822 : channel_close_all(void)
451 : : {
452 : : u_int i;
453 : :
454 [ + + ]: 8252 : for (i = 0; i < channels_alloc; i++)
455 [ + + ]: 7430 : if (channels[i] != NULL)
456 : 779 : channel_close_fds(channels[i]);
457 : 822 : }
458 : :
459 : : /*
460 : : * Stop listening to channels.
461 : : */
462 : : void
463 : 0 : channel_stop_listening(void)
464 : : {
465 : : u_int i;
466 : : Channel *c;
467 : :
468 [ # # ]: 0 : for (i = 0; i < channels_alloc; i++) {
469 : 0 : c = channels[i];
470 [ # # ]: 0 : if (c != NULL) {
471 [ # # ][ # # ]: 0 : switch (c->type) {
472 : : case SSH_CHANNEL_AUTH_SOCKET:
473 : : case SSH_CHANNEL_PORT_LISTENER:
474 : : case SSH_CHANNEL_RPORT_LISTENER:
475 : : case SSH_CHANNEL_X11_LISTENER:
476 : 0 : channel_close_fd(&c->sock);
477 : 0 : channel_free(c);
478 : 0 : break;
479 : : }
480 : : }
481 : : }
482 : 0 : }
483 : :
484 : : /*
485 : : * Returns true if no channel has too much buffered data, and false if one or
486 : : * more channel is overfull.
487 : : */
488 : : int
489 : 6347 : channel_not_very_much_buffered_data(void)
490 : : {
491 : : u_int i;
492 : : Channel *c;
493 : :
494 [ + + ]: 75407 : for (i = 0; i < channels_alloc; i++) {
495 : 69060 : c = channels[i];
496 [ + + ][ + + ]: 69060 : if (c != NULL && c->type == SSH_CHANNEL_OPEN) {
497 : : #if 0
498 : : if (!compat20 &&
499 : : buffer_len(&c->input) > packet_get_maxsize()) {
500 : : debug2("channel %d: big input buffer %d",
501 : : c->self, buffer_len(&c->input));
502 : : return 0;
503 : : }
504 : : #endif
505 [ - + ]: 32842 : if (buffer_len(&c->output) > packet_get_maxsize()) {
506 : 0 : debug2("channel %d: big output buffer %u > %u",
507 : : c->self, buffer_len(&c->output),
508 : : packet_get_maxsize());
509 : 0 : return 0;
510 : : }
511 : : }
512 : : }
513 : : return 1;
514 : : }
515 : :
516 : : /* Returns true if any channel is still open. */
517 : : int
518 : 1442 : channel_still_open(void)
519 : : {
520 : : u_int i;
521 : : Channel *c;
522 : :
523 [ + + ]: 15346 : for (i = 0; i < channels_alloc; i++) {
524 : 13949 : c = channels[i];
525 [ + + ]: 13949 : if (c == NULL)
526 : 13786 : continue;
527 [ + - - - : 163 : switch (c->type) {
+ ]
528 : : case SSH_CHANNEL_X11_LISTENER:
529 : : case SSH_CHANNEL_PORT_LISTENER:
530 : : case SSH_CHANNEL_RPORT_LISTENER:
531 : : case SSH_CHANNEL_MUX_LISTENER:
532 : : case SSH_CHANNEL_CLOSED:
533 : : case SSH_CHANNEL_AUTH_SOCKET:
534 : : case SSH_CHANNEL_DYNAMIC:
535 : : case SSH_CHANNEL_CONNECTING:
536 : : case SSH_CHANNEL_ZOMBIE:
537 : : case SSH_CHANNEL_ABANDONED:
538 : 118 : continue;
539 : : case SSH_CHANNEL_LARVAL:
540 [ # # ]: 0 : if (!compat20)
541 : 0 : fatal("cannot happen: SSH_CHANNEL_LARVAL");
542 : 0 : continue;
543 : : case SSH_CHANNEL_OPENING:
544 : : case SSH_CHANNEL_OPEN:
545 : : case SSH_CHANNEL_X11_OPEN:
546 : : case SSH_CHANNEL_MUX_CLIENT:
547 : : return 1;
548 : : case SSH_CHANNEL_INPUT_DRAINING:
549 : : case SSH_CHANNEL_OUTPUT_DRAINING:
550 [ # # ]: 0 : if (!compat13)
551 : 0 : fatal("cannot happen: OUT_DRAIN");
552 : : return 1;
553 : : default:
554 : 0 : fatal("channel_still_open: bad channel type %d", c->type);
555 : : /* NOTREACHED */
556 : : }
557 : : }
558 : : return 0;
559 : : }
560 : :
561 : : /* Returns the id of an open channel suitable for keepaliving */
562 : : int
563 : 0 : channel_find_open(void)
564 : : {
565 : : u_int i;
566 : : Channel *c;
567 : :
568 [ # # ]: 0 : for (i = 0; i < channels_alloc; i++) {
569 : 0 : c = channels[i];
570 [ # # ][ # # ]: 0 : if (c == NULL || c->remote_id < 0)
571 : 0 : continue;
572 [ # # ][ # # ]: 0 : switch (c->type) {
[ # # ][ # # ]
573 : : case SSH_CHANNEL_CLOSED:
574 : : case SSH_CHANNEL_DYNAMIC:
575 : : case SSH_CHANNEL_X11_LISTENER:
576 : : case SSH_CHANNEL_PORT_LISTENER:
577 : : case SSH_CHANNEL_RPORT_LISTENER:
578 : : case SSH_CHANNEL_MUX_LISTENER:
579 : : case SSH_CHANNEL_MUX_CLIENT:
580 : : case SSH_CHANNEL_OPENING:
581 : : case SSH_CHANNEL_CONNECTING:
582 : : case SSH_CHANNEL_ZOMBIE:
583 : : case SSH_CHANNEL_ABANDONED:
584 : 0 : continue;
585 : : case SSH_CHANNEL_LARVAL:
586 : : case SSH_CHANNEL_AUTH_SOCKET:
587 : : case SSH_CHANNEL_OPEN:
588 : : case SSH_CHANNEL_X11_OPEN:
589 : 0 : return i;
590 : : case SSH_CHANNEL_INPUT_DRAINING:
591 : : case SSH_CHANNEL_OUTPUT_DRAINING:
592 [ # # ]: 0 : if (!compat13)
593 : 0 : fatal("cannot happen: OUT_DRAIN");
594 : 0 : return i;
595 : : default:
596 : 0 : fatal("channel_find_open: bad channel type %d", c->type);
597 : : /* NOTREACHED */
598 : : }
599 : : }
600 : : return -1;
601 : : }
602 : :
603 : :
604 : : /*
605 : : * Returns a message describing the currently open forwarded connections,
606 : : * suitable for sending to the client. The message contains crlf pairs for
607 : : * newlines.
608 : : */
609 : : char *
610 : 911 : channel_open_message(void)
611 : : {
612 : : Buffer buffer;
613 : : Channel *c;
614 : : char buf[1024], *cp;
615 : : u_int i;
616 : :
617 : 911 : buffer_init(&buffer);
618 : : snprintf(buf, sizeof buf, "The following connections are open:\r\n");
619 : 911 : buffer_append(&buffer, buf, strlen(buf));
620 [ + + ]: 12751 : for (i = 0; i < channels_alloc; i++) {
621 : 11840 : c = channels[i];
622 [ + + ]: 11840 : if (c == NULL)
623 : 9063 : continue;
624 [ + - ][ + + ]: 2777 : switch (c->type) {
[ + - ]
625 : : case SSH_CHANNEL_X11_LISTENER:
626 : : case SSH_CHANNEL_PORT_LISTENER:
627 : : case SSH_CHANNEL_RPORT_LISTENER:
628 : : case SSH_CHANNEL_CLOSED:
629 : : case SSH_CHANNEL_AUTH_SOCKET:
630 : : case SSH_CHANNEL_ZOMBIE:
631 : : case SSH_CHANNEL_ABANDONED:
632 : : case SSH_CHANNEL_MUX_CLIENT:
633 : : case SSH_CHANNEL_MUX_LISTENER:
634 : 1487 : continue;
635 : : case SSH_CHANNEL_LARVAL:
636 : : case SSH_CHANNEL_OPENING:
637 : : case SSH_CHANNEL_CONNECTING:
638 : : case SSH_CHANNEL_DYNAMIC:
639 : : case SSH_CHANNEL_OPEN:
640 : : case SSH_CHANNEL_X11_OPEN:
641 : : case SSH_CHANNEL_INPUT_DRAINING:
642 : : case SSH_CHANNEL_OUTPUT_DRAINING:
643 : 1290 : snprintf(buf, sizeof buf,
644 : : " #%d %.300s (t%d r%d i%d/%d o%d/%d fd %d/%d cc %d)\r\n",
645 : : c->self, c->remote_name,
646 : : c->type, c->remote_id,
647 : 1290 : c->istate, buffer_len(&c->input),
648 : 1290 : c->ostate, buffer_len(&c->output),
649 : : c->rfd, c->wfd, c->ctl_chan);
650 : 1290 : buffer_append(&buffer, buf, strlen(buf));
651 : 1290 : continue;
652 : : default:
653 : 0 : fatal("channel_open_message: bad channel type %d", c->type);
654 : : /* NOTREACHED */
655 : : }
656 : : }
657 : 911 : buffer_append(&buffer, "\0", 1);
658 : 911 : cp = xstrdup(buffer_ptr(&buffer));
659 : 911 : buffer_free(&buffer);
660 : 911 : return cp;
661 : : }
662 : :
663 : : void
664 : 702 : channel_send_open(int id)
665 : : {
666 : 702 : Channel *c = channel_lookup(id);
667 : :
668 [ - + ]: 702 : if (c == NULL) {
669 : 0 : logit("channel_send_open: %d: bad id", id);
670 : 0 : return;
671 : : }
672 : 702 : debug2("channel %d: send open", id);
673 : 702 : packet_start(SSH2_MSG_CHANNEL_OPEN);
674 : 702 : packet_put_cstring(c->ctype);
675 : 702 : packet_put_int(c->self);
676 : 702 : packet_put_int(c->local_window);
677 : 702 : packet_put_int(c->local_maxpacket);
678 : 702 : packet_send();
679 : : }
680 : :
681 : : void
682 : 779 : channel_request_start(int id, char *service, int wantconfirm)
683 : : {
684 : 779 : Channel *c = channel_lookup(id);
685 : :
686 [ - + ]: 779 : if (c == NULL) {
687 : 0 : logit("channel_request_start: %d: unknown channel id", id);
688 : 0 : return;
689 : : }
690 : 779 : debug2("channel %d: request %s confirm %d", id, service, wantconfirm);
691 : 779 : packet_start(SSH2_MSG_CHANNEL_REQUEST);
692 : 779 : packet_put_int(c->remote_id);
693 : 779 : packet_put_cstring(service);
694 : 779 : packet_put_char(wantconfirm);
695 : : }
696 : :
697 : : void
698 : 702 : channel_register_status_confirm(int id, channel_confirm_cb *cb,
699 : : channel_confirm_abandon_cb *abandon_cb, void *ctx)
700 : : {
701 : : struct channel_confirm *cc;
702 : : Channel *c;
703 : :
704 [ - + ]: 702 : if ((c = channel_lookup(id)) == NULL)
705 : 0 : fatal("channel_register_expect: %d: bad id", id);
706 : :
707 : 702 : cc = xcalloc(1, sizeof(*cc));
708 : 702 : cc->cb = cb;
709 : 702 : cc->abandon_cb = abandon_cb;
710 : 702 : cc->ctx = ctx;
711 : 702 : TAILQ_INSERT_TAIL(&c->status_confirms, cc, entry);
712 : 702 : }
713 : :
714 : : void
715 : 702 : channel_register_open_confirm(int id, channel_open_fn *fn, void *ctx)
716 : : {
717 : 702 : Channel *c = channel_lookup(id);
718 : :
719 [ - + ]: 702 : if (c == NULL) {
720 : 0 : logit("channel_register_open_confirm: %d: bad id", id);
721 : 0 : return;
722 : : }
723 : 702 : c->open_confirm = fn;
724 : 702 : c->open_confirm_ctx = ctx;
725 : : }
726 : :
727 : : void
728 : 1471 : channel_register_cleanup(int id, channel_callback_fn *fn, int do_close)
729 : : {
730 : 1471 : Channel *c = channel_by_id(id);
731 : :
732 [ - + ]: 1471 : if (c == NULL) {
733 : 0 : logit("channel_register_cleanup: %d: bad id", id);
734 : 0 : return;
735 : : }
736 : 1471 : c->detach_user = fn;
737 : 1471 : c->detach_close = do_close;
738 : : }
739 : :
740 : : void
741 : 740 : channel_cancel_cleanup(int id)
742 : : {
743 : 740 : Channel *c = channel_by_id(id);
744 : :
745 [ - + ]: 740 : if (c == NULL) {
746 : 0 : logit("channel_cancel_cleanup: %d: bad id", id);
747 : 0 : return;
748 : : }
749 : 740 : c->detach_user = NULL;
750 : 740 : c->detach_close = 0;
751 : : }
752 : :
753 : : void
754 : 0 : channel_register_filter(int id, channel_infilter_fn *ifn,
755 : : channel_outfilter_fn *ofn, channel_filter_cleanup_fn *cfn, void *ctx)
756 : : {
757 : 0 : Channel *c = channel_lookup(id);
758 : :
759 [ # # ]: 0 : if (c == NULL) {
760 : 0 : logit("channel_register_filter: %d: bad id", id);
761 : 0 : return;
762 : : }
763 : 0 : c->input_filter = ifn;
764 : 0 : c->output_filter = ofn;
765 : 0 : c->filter_ctx = ctx;
766 : 0 : c->filter_cleanup = cfn;
767 : : }
768 : :
769 : : void
770 : 15 : channel_set_fds(int id, int rfd, int wfd, int efd,
771 : : int extusage, int nonblock, int is_tty, u_int window_max)
772 : : {
773 : 15 : Channel *c = channel_lookup(id);
774 : :
775 [ + - ][ - + ]: 15 : if (c == NULL || c->type != SSH_CHANNEL_LARVAL)
776 : 0 : fatal("channel_activate for non-larval channel %d.", id);
777 : 15 : channel_register_fds(c, rfd, wfd, efd, extusage, nonblock, is_tty);
778 : 15 : c->type = SSH_CHANNEL_OPEN;
779 : 15 : c->local_window = c->local_window_max = window_max;
780 : 15 : packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
781 : 15 : packet_put_int(c->remote_id);
782 : 15 : packet_put_int(c->local_window);
783 : 15 : packet_send();
784 : 15 : }
785 : :
786 : : /*
787 : : * 'channel_pre*' are called just before select() to add any bits relevant to
788 : : * channels in the select bitmasks.
789 : : */
790 : : /*
791 : : * 'channel_post*': perform any appropriate operations for channels which
792 : : * have events pending.
793 : : */
794 : : typedef void chan_fn(Channel *c, fd_set *readset, fd_set *writeset);
795 : : chan_fn *channel_pre[SSH_CHANNEL_MAX_TYPE];
796 : : chan_fn *channel_post[SSH_CHANNEL_MAX_TYPE];
797 : :
798 : : /* ARGSUSED */
799 : : static void
800 : 45680 : channel_pre_listener(Channel *c, fd_set *readset, fd_set *writeset)
801 : : {
802 [ - + ][ # # ]: 45680 : FD_SET(c->sock, readset);
803 : 45680 : }
804 : :
805 : : /* ARGSUSED */
806 : : static void
807 : 33 : channel_pre_connecting(Channel *c, fd_set *readset, fd_set *writeset)
808 : : {
809 : 33 : debug3("channel %d: waiting for connection", c->self);
810 [ - + ][ # # ]: 33 : FD_SET(c->sock, writeset);
811 : 33 : }
812 : :
813 : : static void
814 : 0 : channel_pre_open_13(Channel *c, fd_set *readset, fd_set *writeset)
815 : : {
816 [ # # ]: 0 : if (buffer_len(&c->input) < packet_get_maxsize())
817 [ # # ][ # # ]: 0 : FD_SET(c->sock, readset);
818 [ # # ]: 0 : if (buffer_len(&c->output) > 0)
819 [ # # ][ # # ]: 0 : FD_SET(c->sock, writeset);
820 : 0 : }
821 : :
822 : : static void
823 : 77412 : channel_pre_open(Channel *c, fd_set *readset, fd_set *writeset)
824 : : {
825 [ + + ]: 77412 : u_int limit = compat20 ? c->remote_window : packet_get_maxsize();
826 : :
827 [ + + ][ + + ]: 77412 : if (c->istate == CHAN_INPUT_OPEN &&
828 [ + - ]: 66337 : limit > 0 &&
829 [ + - ]: 132674 : buffer_len(&c->input) < limit &&
830 : 66337 : buffer_check_alloc(&c->input, CHAN_RBUF))
831 [ - + ][ # # ]: 66337 : FD_SET(c->rfd, readset);
832 [ + + ]: 77412 : if (c->ostate == CHAN_OUTPUT_OPEN ||
833 : : c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
834 [ + + ]: 75489 : if (buffer_len(&c->output) > 0) {
835 [ - + ][ # # ]: 2416 : FD_SET(c->wfd, writeset);
836 [ + + ]: 73073 : } else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
837 [ + + ][ + + ]: 43 : if (CHANNEL_EFD_OUTPUT_ACTIVE(c))
[ + - ][ + - ]
[ + + ]
838 : 5 : debug2("channel %d: obuf_empty delayed efd %d/(%d)",
839 : 5 : c->self, c->efd, buffer_len(&c->extended));
840 : : else
841 : 38 : chan_obuf_empty(c);
842 : : }
843 : : }
844 : : /** XXX check close conditions, too */
845 [ + + ][ + + ]: 77412 : if (compat20 && c->efd != -1 &&
[ + + ]
846 [ + + ]: 5603 : !(c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED)) {
847 [ + + + + ]: 53619 : if (c->extended_usage == CHAN_EXTENDED_WRITE &&
848 : 26593 : buffer_len(&c->extended) > 0)
849 [ - + ][ # # ]: 289 : FD_SET(c->efd, writeset);
850 [ + - ][ + + ]: 26737 : else if (c->efd != -1 && !(c->flags & CHAN_EOF_SENT) &&
[ + + ]
851 : 22324 : (c->extended_usage == CHAN_EXTENDED_READ ||
852 [ + - ]: 433 : c->extended_usage == CHAN_EXTENDED_IGNORE) &&
853 : 433 : buffer_len(&c->extended) < c->remote_window)
854 [ - + ][ # # ]: 433 : FD_SET(c->efd, readset);
855 : : }
856 : : /* XXX: What about efd? races? */
857 : 77412 : }
858 : :
859 : : /* ARGSUSED */
860 : : static void
861 : 0 : channel_pre_input_draining(Channel *c, fd_set *readset, fd_set *writeset)
862 : : {
863 [ # # ]: 0 : if (buffer_len(&c->input) == 0) {
864 : 0 : packet_start(SSH_MSG_CHANNEL_CLOSE);
865 : 0 : packet_put_int(c->remote_id);
866 : 0 : packet_send();
867 : 0 : c->type = SSH_CHANNEL_CLOSED;
868 : 0 : debug2("channel %d: closing after input drain.", c->self);
869 : : }
870 : 0 : }
871 : :
872 : : /* ARGSUSED */
873 : : static void
874 : 0 : channel_pre_output_draining(Channel *c, fd_set *readset, fd_set *writeset)
875 : : {
876 [ # # ]: 0 : if (buffer_len(&c->output) == 0)
877 : 0 : chan_mark_dead(c);
878 : : else
879 [ # # ][ # # ]: 0 : FD_SET(c->sock, writeset);
880 : 0 : }
881 : :
882 : : /*
883 : : * This is a special state for X11 authentication spoofing. An opened X11
884 : : * connection (when authentication spoofing is being done) remains in this
885 : : * state until the first packet has been completely read. The authentication
886 : : * data in that packet is then substituted by the real data if it matches the
887 : : * fake data, and the channel is put into normal mode.
888 : : * XXX All this happens at the client side.
889 : : * Returns: 0 = need more data, -1 = wrong cookie, 1 = ok
890 : : */
891 : : static int
892 : 0 : x11_open_helper(Buffer *b)
893 : : {
894 : : u_char *ucp;
895 : : u_int proto_len, data_len;
896 : :
897 : : /* Check if the fixed size part of the packet is in buffer. */
898 [ # # ]: 0 : if (buffer_len(b) < 12)
899 : : return 0;
900 : :
901 : : /* Parse the lengths of variable-length fields. */
902 : 0 : ucp = buffer_ptr(b);
903 [ # # ]: 0 : if (ucp[0] == 0x42) { /* Byte order MSB first. */
904 : 0 : proto_len = 256 * ucp[6] + ucp[7];
905 : 0 : data_len = 256 * ucp[8] + ucp[9];
906 [ # # ]: 0 : } else if (ucp[0] == 0x6c) { /* Byte order LSB first. */
907 : 0 : proto_len = ucp[6] + 256 * ucp[7];
908 : 0 : data_len = ucp[8] + 256 * ucp[9];
909 : : } else {
910 : 0 : debug2("Initial X11 packet contains bad byte order byte: 0x%x",
911 : : ucp[0]);
912 : 0 : return -1;
913 : : }
914 : :
915 : : /* Check if the whole packet is in buffer. */
916 [ # # ]: 0 : if (buffer_len(b) <
917 : 0 : 12 + ((proto_len + 3) & ~3) + ((data_len + 3) & ~3))
918 : : return 0;
919 : :
920 : : /* Check if authentication protocol matches. */
921 [ # # ][ # # ]: 0 : if (proto_len != strlen(x11_saved_proto) ||
922 : 0 : memcmp(ucp + 12, x11_saved_proto, proto_len) != 0) {
923 : 0 : debug2("X11 connection uses different authentication protocol.");
924 : 0 : return -1;
925 : : }
926 : : /* Check if authentication data matches our fake data. */
927 [ # # # # ]: 0 : if (data_len != x11_fake_data_len ||
928 : 0 : timingsafe_bcmp(ucp + 12 + ((proto_len + 3) & ~3),
929 : : x11_fake_data, x11_fake_data_len) != 0) {
930 : 0 : debug2("X11 auth data does not match fake data.");
931 : 0 : return -1;
932 : : }
933 : : /* Check fake data length */
934 [ # # ]: 0 : if (x11_fake_data_len != x11_saved_data_len) {
935 : 0 : error("X11 fake_data_len %d != saved_data_len %d",
936 : : x11_fake_data_len, x11_saved_data_len);
937 : 0 : return -1;
938 : : }
939 : : /*
940 : : * Received authentication protocol and data match
941 : : * our fake data. Substitute the fake data with real
942 : : * data.
943 : : */
944 : 0 : memcpy(ucp + 12 + ((proto_len + 3) & ~3),
945 : : x11_saved_data, x11_saved_data_len);
946 : 0 : return 1;
947 : : }
948 : :
949 : : static void
950 : 0 : channel_pre_x11_open_13(Channel *c, fd_set *readset, fd_set *writeset)
951 : : {
952 : 0 : int ret = x11_open_helper(&c->output);
953 : :
954 [ # # ]: 0 : if (ret == 1) {
955 : : /* Start normal processing for the channel. */
956 : 0 : c->type = SSH_CHANNEL_OPEN;
957 : 0 : channel_pre_open_13(c, readset, writeset);
958 [ # # ]: 0 : } else if (ret == -1) {
959 : : /*
960 : : * We have received an X11 connection that has bad
961 : : * authentication information.
962 : : */
963 : 0 : logit("X11 connection rejected because of wrong authentication.");
964 : 0 : buffer_clear(&c->input);
965 : 0 : buffer_clear(&c->output);
966 : 0 : channel_close_fd(&c->sock);
967 : 0 : c->sock = -1;
968 : 0 : c->type = SSH_CHANNEL_CLOSED;
969 : 0 : packet_start(SSH_MSG_CHANNEL_CLOSE);
970 : 0 : packet_put_int(c->remote_id);
971 : 0 : packet_send();
972 : : }
973 : 0 : }
974 : :
975 : : static void
976 : 0 : channel_pre_x11_open(Channel *c, fd_set *readset, fd_set *writeset)
977 : : {
978 : 0 : int ret = x11_open_helper(&c->output);
979 : :
980 : : /* c->force_drain = 1; */
981 : :
982 [ # # ]: 0 : if (ret == 1) {
983 : 0 : c->type = SSH_CHANNEL_OPEN;
984 : 0 : channel_pre_open(c, readset, writeset);
985 [ # # ]: 0 : } else if (ret == -1) {
986 : 0 : logit("X11 connection rejected because of wrong authentication.");
987 : 0 : debug2("X11 rejected %d i%d/o%d", c->self, c->istate, c->ostate);
988 : 0 : chan_read_failed(c);
989 : 0 : buffer_clear(&c->input);
990 : 0 : chan_ibuf_empty(c);
991 : 0 : buffer_clear(&c->output);
992 : : /* for proto v1, the peer will send an IEOF */
993 [ # # ]: 0 : if (compat20)
994 : 0 : chan_write_failed(c);
995 : : else
996 : 0 : c->type = SSH_CHANNEL_OPEN;
997 : 0 : debug2("X11 closed %d i%d/o%d", c->self, c->istate, c->ostate);
998 : : }
999 : 0 : }
1000 : :
1001 : : static void
1002 : 925 : channel_pre_mux_client(Channel *c, fd_set *readset, fd_set *writeset)
1003 : : {
1004 [ + + ]: 1792 : if (c->istate == CHAN_INPUT_OPEN && !c->mux_pause &&
[ + + + - ]
1005 : 867 : buffer_check_alloc(&c->input, CHAN_RBUF))
1006 [ - + ][ # # ]: 867 : FD_SET(c->rfd, readset);
1007 [ + + ]: 925 : if (c->istate == CHAN_INPUT_WAIT_DRAIN) {
1008 : : /* clear buffer immediately (discard any partial packet) */
1009 : 8 : buffer_clear(&c->input);
1010 : 8 : chan_ibuf_empty(c);
1011 : : /* Start output drain. XXX just kill chan? */
1012 : 8 : chan_rcvd_oclose(c);
1013 : : }
1014 [ + - ]: 925 : if (c->ostate == CHAN_OUTPUT_OPEN ||
1015 : : c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
1016 [ + + ]: 925 : if (buffer_len(&c->output) > 0)
1017 [ - + ][ # # ]: 81 : FD_SET(c->wfd, writeset);
1018 [ + + ]: 844 : else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN)
1019 : 24 : chan_obuf_empty(c);
1020 : : }
1021 : 925 : }
1022 : :
1023 : : /* try to decode a socks4 header */
1024 : : /* ARGSUSED */
1025 : : static int
1026 : 2 : channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset)
1027 : : {
1028 : : char *p, *host;
1029 : : u_int len, have, i, found, need;
1030 : : char username[256];
1031 : : struct {
1032 : : u_int8_t version;
1033 : : u_int8_t command;
1034 : : u_int16_t dest_port;
1035 : : struct in_addr dest_addr;
1036 : : } s4_req, s4_rsp;
1037 : :
1038 : 2 : debug2("channel %d: decode socks4", c->self);
1039 : :
1040 : 2 : have = buffer_len(&c->input);
1041 : 2 : len = sizeof(s4_req);
1042 [ + - ]: 2 : if (have < len)
1043 : : return 0;
1044 : 2 : p = buffer_ptr(&c->input);
1045 : :
1046 : 2 : need = 1;
1047 : : /* SOCKS4A uses an invalid IP address 0.0.0.x */
1048 [ - + ][ # # ]: 2 : if (p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] != 0) {
[ # # ][ # # ]
1049 : 0 : debug2("channel %d: socks4a request", c->self);
1050 : : /* ... and needs an extra string (the hostname) */
1051 : 0 : need = 2;
1052 : : }
1053 : : /* Check for terminating NUL on the string(s) */
1054 [ + - ]: 2 : for (found = 0, i = len; i < have; i++) {
1055 [ + - ]: 2 : if (p[i] == '\0') {
1056 : 2 : found++;
1057 [ - + ]: 2 : if (found == need)
1058 : : break;
1059 : : }
1060 [ # # ]: 0 : if (i > 1024) {
1061 : : /* the peer is probably sending garbage */
1062 : 0 : debug("channel %d: decode socks4: too long",
1063 : : c->self);
1064 : : return -1;
1065 : : }
1066 : : }
1067 [ + - ]: 2 : if (found < need)
1068 : : return 0;
1069 : 2 : buffer_get(&c->input, (char *)&s4_req.version, 1);
1070 : 2 : buffer_get(&c->input, (char *)&s4_req.command, 1);
1071 : 2 : buffer_get(&c->input, (char *)&s4_req.dest_port, 2);
1072 : 2 : buffer_get(&c->input, (char *)&s4_req.dest_addr, 4);
1073 : 2 : have = buffer_len(&c->input);
1074 : 2 : p = buffer_ptr(&c->input);
1075 [ - + ]: 2 : if (memchr(p, '\0', have) == NULL)
1076 : 0 : fatal("channel %d: decode socks4: user not nul terminated",
1077 : : c->self);
1078 : 2 : len = strlen(p);
1079 : 2 : debug2("channel %d: decode socks4: user %s/%d", c->self, p, len);
1080 : 2 : len++; /* trailing '\0' */
1081 [ - + ]: 2 : if (len > have)
1082 : 0 : fatal("channel %d: decode socks4: len %d > have %d",
1083 : : c->self, len, have);
1084 : 2 : strlcpy(username, p, sizeof(username));
1085 : 2 : buffer_consume(&c->input, len);
1086 : :
1087 : 2 : free(c->path);
1088 : 2 : c->path = NULL;
1089 [ + - ]: 2 : if (need == 1) { /* SOCKS4: one string */
1090 : 2 : host = inet_ntoa(s4_req.dest_addr);
1091 : 2 : c->path = xstrdup(host);
1092 : : } else { /* SOCKS4A: two strings */
1093 : 0 : have = buffer_len(&c->input);
1094 : 0 : p = buffer_ptr(&c->input);
1095 : 0 : len = strlen(p);
1096 : 0 : debug2("channel %d: decode socks4a: host %s/%d",
1097 : : c->self, p, len);
1098 : 0 : len++; /* trailing '\0' */
1099 [ # # ]: 0 : if (len > have)
1100 : 0 : fatal("channel %d: decode socks4a: len %d > have %d",
1101 : : c->self, len, have);
1102 [ # # ]: 0 : if (len > NI_MAXHOST) {
1103 : 0 : error("channel %d: hostname \"%.100s\" too long",
1104 : : c->self, p);
1105 : : return -1;
1106 : : }
1107 : 0 : c->path = xstrdup(p);
1108 : 0 : buffer_consume(&c->input, len);
1109 : : }
1110 [ - + ]: 2 : c->host_port = ntohs(s4_req.dest_port);
1111 : :
1112 : 2 : debug2("channel %d: dynamic request: socks4 host %s port %u command %u",
1113 : 2 : c->self, c->path, c->host_port, s4_req.command);
1114 : :
1115 [ - + ]: 2 : if (s4_req.command != 1) {
1116 [ # # ]: 0 : debug("channel %d: cannot handle: %s cn %d",
1117 : : c->self, need == 1 ? "SOCKS4" : "SOCKS4A", s4_req.command);
1118 : : return -1;
1119 : : }
1120 : 2 : s4_rsp.version = 0; /* vn: 0 for reply */
1121 : 2 : s4_rsp.command = 90; /* cd: req granted */
1122 : 2 : s4_rsp.dest_port = 0; /* ignored */
1123 : 2 : s4_rsp.dest_addr.s_addr = INADDR_ANY; /* ignored */
1124 : 2 : buffer_append(&c->output, &s4_rsp, sizeof(s4_rsp));
1125 : : return 1;
1126 : : }
1127 : :
1128 : : /* try to decode a socks5 header */
1129 : : #define SSH_SOCKS5_AUTHDONE 0x1000
1130 : : #define SSH_SOCKS5_NOAUTH 0x00
1131 : : #define SSH_SOCKS5_IPV4 0x01
1132 : : #define SSH_SOCKS5_DOMAIN 0x03
1133 : : #define SSH_SOCKS5_IPV6 0x04
1134 : : #define SSH_SOCKS5_CONNECT 0x01
1135 : : #define SSH_SOCKS5_SUCCESS 0x00
1136 : :
1137 : : /* ARGSUSED */
1138 : : static int
1139 : 4 : channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset)
1140 : : {
1141 : : struct {
1142 : : u_int8_t version;
1143 : : u_int8_t command;
1144 : : u_int8_t reserved;
1145 : : u_int8_t atyp;
1146 : : } s5_req, s5_rsp;
1147 : : u_int16_t dest_port;
1148 : : char dest_addr[255+1], ntop[INET6_ADDRSTRLEN];
1149 : : u_char *p;
1150 : : u_int have, need, i, found, nmethods, addrlen, af;
1151 : :
1152 : 4 : debug2("channel %d: decode socks5", c->self);
1153 : 4 : p = buffer_ptr(&c->input);
1154 [ + - ]: 4 : if (p[0] != 0x05)
1155 : : return -1;
1156 : 4 : have = buffer_len(&c->input);
1157 [ + + ]: 4 : if (!(c->flags & SSH_SOCKS5_AUTHDONE)) {
1158 : : /* format: ver | nmethods | methods */
1159 [ + - ]: 2 : if (have < 2)
1160 : : return 0;
1161 : 2 : nmethods = p[1];
1162 [ + - ]: 2 : if (have < nmethods + 2)
1163 : : return 0;
1164 : : /* look for method: "NO AUTHENTICATION REQUIRED" */
1165 [ + - ]: 2 : for (found = 0, i = 2; i < nmethods + 2; i++) {
1166 [ - + ]: 2 : if (p[i] == SSH_SOCKS5_NOAUTH) {
1167 : : found = 1;
1168 : : break;
1169 : : }
1170 : : }
1171 [ - + ]: 2 : if (!found) {
1172 : 0 : debug("channel %d: method SSH_SOCKS5_NOAUTH not found",
1173 : : c->self);
1174 : : return -1;
1175 : : }
1176 : 2 : buffer_consume(&c->input, nmethods + 2);
1177 : 2 : buffer_put_char(&c->output, 0x05); /* version */
1178 : 2 : buffer_put_char(&c->output, SSH_SOCKS5_NOAUTH); /* method */
1179 [ - + ][ # # ]: 2 : FD_SET(c->sock, writeset);
1180 : 2 : c->flags |= SSH_SOCKS5_AUTHDONE;
1181 : 2 : debug2("channel %d: socks5 auth done", c->self);
1182 : : return 0; /* need more */
1183 : : }
1184 : 2 : debug2("channel %d: socks5 post auth", c->self);
1185 [ + - ]: 2 : if (have < sizeof(s5_req)+1)
1186 : : return 0; /* need more */
1187 : : memcpy(&s5_req, p, sizeof(s5_req));
1188 [ + - ][ + - ]: 2 : if (s5_req.version != 0x05 ||
1189 [ - + ]: 2 : s5_req.command != SSH_SOCKS5_CONNECT ||
1190 : 2 : s5_req.reserved != 0x00) {
1191 : 0 : debug2("channel %d: only socks5 connect supported", c->self);
1192 : : return -1;
1193 : : }
1194 [ + - - + ]: 2 : switch (s5_req.atyp){
1195 : : case SSH_SOCKS5_IPV4:
1196 : : addrlen = 4;
1197 : : af = AF_INET;
1198 : : break;
1199 : : case SSH_SOCKS5_DOMAIN:
1200 : 1 : addrlen = p[sizeof(s5_req)];
1201 : 1 : af = -1;
1202 : : break;
1203 : : case SSH_SOCKS5_IPV6:
1204 : 0 : addrlen = 16;
1205 : 0 : af = AF_INET6;
1206 : : break;
1207 : : default:
1208 : 0 : debug2("channel %d: bad socks5 atyp %d", c->self, s5_req.atyp);
1209 : : return -1;
1210 : : }
1211 : 2 : need = sizeof(s5_req) + addrlen + 2;
1212 [ + + ]: 2 : if (s5_req.atyp == SSH_SOCKS5_DOMAIN)
1213 : 1 : need++;
1214 [ + - ]: 2 : if (have < need)
1215 : : return 0;
1216 : 2 : buffer_consume(&c->input, sizeof(s5_req));
1217 [ + + ]: 2 : if (s5_req.atyp == SSH_SOCKS5_DOMAIN)
1218 : 1 : buffer_consume(&c->input, 1); /* host string length */
1219 : 2 : buffer_get(&c->input, &dest_addr, addrlen);
1220 : 2 : buffer_get(&c->input, (char *)&dest_port, 2);
1221 : 2 : dest_addr[addrlen] = '\0';
1222 : 2 : free(c->path);
1223 : 2 : c->path = NULL;
1224 [ + + ]: 2 : if (s5_req.atyp == SSH_SOCKS5_DOMAIN) {
1225 [ - + ]: 1 : if (addrlen >= NI_MAXHOST) {
1226 : 0 : error("channel %d: dynamic request: socks5 hostname "
1227 : : "\"%.100s\" too long", c->self, dest_addr);
1228 : : return -1;
1229 : : }
1230 : 1 : c->path = xstrdup(dest_addr);
1231 : : } else {
1232 [ + - ]: 1 : if (inet_ntop(af, dest_addr, ntop, sizeof(ntop)) == NULL)
1233 : : return -1;
1234 : 1 : c->path = xstrdup(ntop);
1235 : : }
1236 [ - + ]: 2 : c->host_port = ntohs(dest_port);
1237 : :
1238 : 2 : debug2("channel %d: dynamic request: socks5 host %s port %u command %u",
1239 : 2 : c->self, c->path, c->host_port, s5_req.command);
1240 : :
1241 : 2 : s5_rsp.version = 0x05;
1242 : 2 : s5_rsp.command = SSH_SOCKS5_SUCCESS;
1243 : 2 : s5_rsp.reserved = 0; /* ignored */
1244 : 2 : s5_rsp.atyp = SSH_SOCKS5_IPV4;
1245 : 2 : dest_port = 0; /* ignored */
1246 : :
1247 : 2 : buffer_append(&c->output, &s5_rsp, sizeof(s5_rsp));
1248 : 2 : buffer_put_int(&c->output, ntohl(INADDR_ANY)); /* bind address */
1249 : 2 : buffer_append(&c->output, &dest_port, sizeof(dest_port));
1250 : : return 1;
1251 : : }
1252 : :
1253 : : Channel *
1254 : 0 : channel_connect_stdio_fwd(const char *host_to_connect, u_short port_to_connect,
1255 : : int in, int out)
1256 : : {
1257 : : Channel *c;
1258 : :
1259 : 0 : debug("channel_connect_stdio_fwd %s:%d", host_to_connect,
1260 : : port_to_connect);
1261 : :
1262 : 0 : c = channel_new("stdio-forward", SSH_CHANNEL_OPENING, in, out,
1263 : : -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
1264 : : 0, "stdio-forward", /*nonblock*/0);
1265 : :
1266 : 0 : c->path = xstrdup(host_to_connect);
1267 : 0 : c->host_port = port_to_connect;
1268 : 0 : c->listening_port = 0;
1269 : 0 : c->force_drain = 1;
1270 : :
1271 : 0 : channel_register_fds(c, in, out, -1, 0, 1, 0);
1272 : 0 : port_open_helper(c, "direct-tcpip");
1273 : :
1274 : 0 : return c;
1275 : : }
1276 : :
1277 : : /* dynamic port forwarding */
1278 : : static void
1279 : 12 : channel_pre_dynamic(Channel *c, fd_set *readset, fd_set *writeset)
1280 : : {
1281 : : u_char *p;
1282 : : u_int have;
1283 : : int ret;
1284 : :
1285 : 12 : have = buffer_len(&c->input);
1286 : 12 : debug2("channel %d: pre_dynamic: have %d", c->self, have);
1287 : : /* buffer_dump(&c->input); */
1288 : : /* check if the fixed size part of the packet is in buffer. */
1289 [ + + ]: 12 : if (have < 3) {
1290 : : /* need more */
1291 [ - + ][ # # ]: 6 : FD_SET(c->sock, readset);
1292 : 6 : return;
1293 : : }
1294 : : /* try to guess the protocol */
1295 : 6 : p = buffer_ptr(&c->input);
1296 [ + + - ]: 6 : switch (p[0]) {
1297 : : case 0x04:
1298 : 2 : ret = channel_decode_socks4(c, readset, writeset);
1299 : 2 : break;
1300 : : case 0x05:
1301 : 4 : ret = channel_decode_socks5(c, readset, writeset);
1302 : 4 : break;
1303 : : default:
1304 : : ret = -1;
1305 : : break;
1306 : : }
1307 [ - + ]: 6 : if (ret < 0) {
1308 : 0 : chan_mark_dead(c);
1309 [ + + ]: 6 : } else if (ret == 0) {
1310 : 2 : debug2("channel %d: pre_dynamic: need more", c->self);
1311 : : /* need more */
1312 [ - + ][ # # ]: 2 : FD_SET(c->sock, readset);
1313 : : } else {
1314 : : /* switch to the next state */
1315 : 4 : c->type = SSH_CHANNEL_OPENING;
1316 : 4 : port_open_helper(c, "direct-tcpip");
1317 : : }
1318 : : }
1319 : :
1320 : : /* This is our fake X11 server socket. */
1321 : : /* ARGSUSED */
1322 : : static void
1323 : 0 : channel_post_x11_listener(Channel *c, fd_set *readset, fd_set *writeset)
1324 : : {
1325 : : Channel *nc;
1326 : : struct sockaddr_storage addr;
1327 : : int newsock, oerrno;
1328 : : socklen_t addrlen;
1329 : : char buf[16384], *remote_ipaddr;
1330 : : int remote_port;
1331 : :
1332 [ # # ][ # # ]: 0 : if (FD_ISSET(c->sock, readset)) {
[ # # ]
1333 : 0 : debug("X11 connection requested.");
1334 : 0 : addrlen = sizeof(addr);
1335 : 0 : newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen);
1336 [ # # ]: 0 : if (c->single_connection) {
1337 : 0 : oerrno = errno;
1338 : 0 : debug2("single_connection: closing X11 listener.");
1339 : 0 : channel_close_fd(&c->sock);
1340 : 0 : chan_mark_dead(c);
1341 : 0 : errno = oerrno;
1342 : : }
1343 [ # # ]: 0 : if (newsock < 0) {
1344 [ # # ][ # # ]: 0 : if (errno != EINTR && errno != EWOULDBLOCK &&
1345 : : errno != ECONNABORTED)
1346 : 0 : error("accept: %.100s", strerror(errno));
1347 [ # # ]: 0 : if (errno == EMFILE || errno == ENFILE)
1348 : 0 : c->notbefore = monotime() + 1;
1349 : 0 : return;
1350 : : }
1351 : 0 : set_nodelay(newsock);
1352 : 0 : remote_ipaddr = get_peer_ipaddr(newsock);
1353 : 0 : remote_port = get_peer_port(newsock);
1354 : : snprintf(buf, sizeof buf, "X11 connection from %.200s port %d",
1355 : : remote_ipaddr, remote_port);
1356 : :
1357 : 0 : nc = channel_new("accepted x11 socket",
1358 : : SSH_CHANNEL_OPENING, newsock, newsock, -1,
1359 : : c->local_window_max, c->local_maxpacket, 0, buf, 1);
1360 [ # # ]: 0 : if (compat20) {
1361 : 0 : packet_start(SSH2_MSG_CHANNEL_OPEN);
1362 : 0 : packet_put_cstring("x11");
1363 : 0 : packet_put_int(nc->self);
1364 : 0 : packet_put_int(nc->local_window_max);
1365 : 0 : packet_put_int(nc->local_maxpacket);
1366 : : /* originator ipaddr and port */
1367 : 0 : packet_put_cstring(remote_ipaddr);
1368 [ # # ]: 0 : if (datafellows & SSH_BUG_X11FWD) {
1369 : 0 : debug2("ssh2 x11 bug compat mode");
1370 : : } else {
1371 : 0 : packet_put_int(remote_port);
1372 : : }
1373 : 0 : packet_send();
1374 : : } else {
1375 : 0 : packet_start(SSH_SMSG_X11_OPEN);
1376 : 0 : packet_put_int(nc->self);
1377 [ # # ]: 0 : if (packet_get_protocol_flags() &
1378 : : SSH_PROTOFLAG_HOST_IN_FWD_OPEN)
1379 : 0 : packet_put_cstring(buf);
1380 : 0 : packet_send();
1381 : : }
1382 : 0 : free(remote_ipaddr);
1383 : : }
1384 : : }
1385 : :
1386 : : static void
1387 : 43 : port_open_helper(Channel *c, char *rtype)
1388 : : {
1389 : : int direct;
1390 : : char buf[1024];
1391 : 43 : char *local_ipaddr = get_local_ipaddr(c->sock);
1392 [ + - ]: 43 : int local_port = c->sock == -1 ? 65536 : get_sock_port(c->sock, 1);
1393 : 43 : char *remote_ipaddr = get_peer_ipaddr(c->sock);
1394 : 43 : int remote_port = get_peer_port(c->sock);
1395 : :
1396 [ - + ]: 43 : if (remote_port == -1) {
1397 : : /* Fake addr/port to appease peers that validate it (Tectia) */
1398 : 0 : free(remote_ipaddr);
1399 : 0 : remote_ipaddr = xstrdup("127.0.0.1");
1400 : 0 : remote_port = 65535;
1401 : : }
1402 : :
1403 : 43 : direct = (strcmp(rtype, "direct-tcpip") == 0);
1404 : :
1405 : 43 : snprintf(buf, sizeof buf,
1406 : : "%s: listening port %d for %.100s port %d, "
1407 : : "connect from %.200s port %d to %.100s port %d",
1408 : : rtype, c->listening_port, c->path, c->host_port,
1409 : : remote_ipaddr, remote_port, local_ipaddr, local_port);
1410 : :
1411 : 43 : free(c->remote_name);
1412 : 43 : c->remote_name = xstrdup(buf);
1413 : :
1414 [ + + ]: 43 : if (compat20) {
1415 : 21 : packet_start(SSH2_MSG_CHANNEL_OPEN);
1416 : 21 : packet_put_cstring(rtype);
1417 : 21 : packet_put_int(c->self);
1418 : 21 : packet_put_int(c->local_window_max);
1419 : 21 : packet_put_int(c->local_maxpacket);
1420 [ + + ]: 21 : if (direct) {
1421 : : /* target host, port */
1422 : 20 : packet_put_cstring(c->path);
1423 : 20 : packet_put_int(c->host_port);
1424 : : } else {
1425 : : /* listen address, port */
1426 : 1 : packet_put_cstring(c->path);
1427 : 1 : packet_put_int(local_port);
1428 : : }
1429 : : /* originator host and port */
1430 : 21 : packet_put_cstring(remote_ipaddr);
1431 : 21 : packet_put_int((u_int)remote_port);
1432 : 21 : packet_send();
1433 : : } else {
1434 : 22 : packet_start(SSH_MSG_PORT_OPEN);
1435 : 22 : packet_put_int(c->self);
1436 : 22 : packet_put_cstring(c->path);
1437 : 22 : packet_put_int(c->host_port);
1438 [ + - ]: 22 : if (packet_get_protocol_flags() &
1439 : : SSH_PROTOFLAG_HOST_IN_FWD_OPEN)
1440 : 22 : packet_put_cstring(c->remote_name);
1441 : 22 : packet_send();
1442 : : }
1443 : 43 : free(remote_ipaddr);
1444 : 43 : free(local_ipaddr);
1445 : 43 : }
1446 : :
1447 : : static void
1448 : 141 : channel_set_reuseaddr(int fd)
1449 : : {
1450 : 141 : int on = 1;
1451 : :
1452 : : /*
1453 : : * Set socket options.
1454 : : * Allow local port reuse in TIME_WAIT.
1455 : : */
1456 [ - + ]: 141 : if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)
1457 : 0 : error("setsockopt SO_REUSEADDR fd %d: %s", fd, strerror(errno));
1458 : 141 : }
1459 : :
1460 : : /*
1461 : : * This socket is listening for connections to a forwarded TCP/IP port.
1462 : : */
1463 : : /* ARGSUSED */
1464 : : static void
1465 : 44677 : channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset)
1466 : : {
1467 : : Channel *nc;
1468 : : struct sockaddr_storage addr;
1469 : : int newsock, nextstate;
1470 : : socklen_t addrlen;
1471 : : char *rtype;
1472 : :
1473 [ - + ][ # # ]: 44677 : if (FD_ISSET(c->sock, readset)) {
[ + + ]
1474 : 43 : debug("Connection to port %d forwarding "
1475 : : "to %.100s port %d requested.",
1476 : : c->listening_port, c->path, c->host_port);
1477 : :
1478 [ + + ]: 43 : if (c->type == SSH_CHANNEL_RPORT_LISTENER) {
1479 : : nextstate = SSH_CHANNEL_OPENING;
1480 : : rtype = "forwarded-tcpip";
1481 : : } else {
1482 [ + + ]: 42 : if (c->host_port == 0) {
1483 : : nextstate = SSH_CHANNEL_DYNAMIC;
1484 : : rtype = "dynamic-tcpip";
1485 : : } else {
1486 : 38 : nextstate = SSH_CHANNEL_OPENING;
1487 : 38 : rtype = "direct-tcpip";
1488 : : }
1489 : : }
1490 : :
1491 : 43 : addrlen = sizeof(addr);
1492 : 43 : newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen);
1493 [ - + ]: 43 : if (newsock < 0) {
1494 [ # # ][ # # ]: 0 : if (errno != EINTR && errno != EWOULDBLOCK &&
1495 : : errno != ECONNABORTED)
1496 : 0 : error("accept: %.100s", strerror(errno));
1497 [ # # ]: 0 : if (errno == EMFILE || errno == ENFILE)
1498 : 0 : c->notbefore = monotime() + 1;
1499 : 0 : return;
1500 : : }
1501 : 43 : set_nodelay(newsock);
1502 : 43 : nc = channel_new(rtype, nextstate, newsock, newsock, -1,
1503 : : c->local_window_max, c->local_maxpacket, 0, rtype, 1);
1504 : 43 : nc->listening_port = c->listening_port;
1505 : 43 : nc->host_port = c->host_port;
1506 [ + - ]: 43 : if (c->path != NULL)
1507 : 43 : nc->path = xstrdup(c->path);
1508 : :
1509 [ + + ]: 43 : if (nextstate != SSH_CHANNEL_DYNAMIC)
1510 : 44677 : port_open_helper(nc, rtype);
1511 : : }
1512 : : }
1513 : :
1514 : : /*
1515 : : * This is the authentication agent socket listening for connections from
1516 : : * clients.
1517 : : */
1518 : : /* ARGSUSED */
1519 : : static void
1520 : 0 : channel_post_auth_listener(Channel *c, fd_set *readset, fd_set *writeset)
1521 : : {
1522 : : Channel *nc;
1523 : : int newsock;
1524 : : struct sockaddr_storage addr;
1525 : : socklen_t addrlen;
1526 : :
1527 [ # # ][ # # ]: 0 : if (FD_ISSET(c->sock, readset)) {
[ # # ]
1528 : 0 : addrlen = sizeof(addr);
1529 : 0 : newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen);
1530 [ # # ]: 0 : if (newsock < 0) {
1531 : 0 : error("accept from auth socket: %.100s",
1532 : 0 : strerror(errno));
1533 [ # # ]: 0 : if (errno == EMFILE || errno == ENFILE)
1534 : 0 : c->notbefore = monotime() + 1;
1535 : 0 : return;
1536 : : }
1537 : 0 : nc = channel_new("accepted auth socket",
1538 : : SSH_CHANNEL_OPENING, newsock, newsock, -1,
1539 : : c->local_window_max, c->local_maxpacket,
1540 : : 0, "accepted auth socket", 1);
1541 [ # # ]: 0 : if (compat20) {
1542 : 0 : packet_start(SSH2_MSG_CHANNEL_OPEN);
1543 : 0 : packet_put_cstring("auth-agent@openssh.com");
1544 : 0 : packet_put_int(nc->self);
1545 : 0 : packet_put_int(c->local_window_max);
1546 : 0 : packet_put_int(c->local_maxpacket);
1547 : : } else {
1548 : 0 : packet_start(SSH_SMSG_AGENT_OPEN);
1549 : 0 : packet_put_int(nc->self);
1550 : : }
1551 : 0 : packet_send();
1552 : : }
1553 : : }
1554 : :
1555 : : /* ARGSUSED */
1556 : : static void
1557 : 33 : channel_post_connecting(Channel *c, fd_set *readset, fd_set *writeset)
1558 : : {
1559 : 33 : int err = 0, sock;
1560 : 33 : socklen_t sz = sizeof(err);
1561 : :
1562 [ - + ][ # # ]: 33 : if (FD_ISSET(c->sock, writeset)) {
[ + - ]
1563 [ - + ]: 33 : if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, &err, &sz) < 0) {
1564 : 0 : err = errno;
1565 : 0 : error("getsockopt SO_ERROR failed");
1566 : : }
1567 [ + - ]: 33 : if (err == 0) {
1568 : 33 : debug("channel %d: connected to %s port %d",
1569 : : c->self, c->connect_ctx.host, c->connect_ctx.port);
1570 : 33 : channel_connect_ctx_free(&c->connect_ctx);
1571 : 33 : c->type = SSH_CHANNEL_OPEN;
1572 [ + + ]: 33 : if (compat20) {
1573 : 11 : packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
1574 : 11 : packet_put_int(c->remote_id);
1575 : 11 : packet_put_int(c->self);
1576 : 11 : packet_put_int(c->local_window);
1577 : 11 : packet_put_int(c->local_maxpacket);
1578 : : } else {
1579 : 22 : packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
1580 : 22 : packet_put_int(c->remote_id);
1581 : 22 : packet_put_int(c->self);
1582 : : }
1583 : : } else {
1584 : 0 : debug("channel %d: connection failed: %s",
1585 : : c->self, strerror(err));
1586 : : /* Try next address, if any */
1587 [ # # ]: 0 : if ((sock = connect_next(&c->connect_ctx)) > 0) {
1588 : 0 : close(c->sock);
1589 : 0 : c->sock = c->rfd = c->wfd = sock;
1590 : 0 : channel_max_fd = channel_find_maxfd();
1591 : 0 : return;
1592 : : }
1593 : : /* Exhausted all addresses */
1594 : 0 : error("connect_to %.100s port %d: failed.",
1595 : : c->connect_ctx.host, c->connect_ctx.port);
1596 : 0 : channel_connect_ctx_free(&c->connect_ctx);
1597 [ # # ]: 0 : if (compat20) {
1598 : 0 : packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
1599 : 0 : packet_put_int(c->remote_id);
1600 : 0 : packet_put_int(SSH2_OPEN_CONNECT_FAILED);
1601 [ # # ]: 0 : if (!(datafellows & SSH_BUG_OPENFAILURE)) {
1602 : 0 : packet_put_cstring(strerror(err));
1603 : 0 : packet_put_cstring("");
1604 : : }
1605 : : } else {
1606 : 0 : packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
1607 : 0 : packet_put_int(c->remote_id);
1608 : : }
1609 : 0 : chan_mark_dead(c);
1610 : : }
1611 : 33 : packet_send();
1612 : : }
1613 : : }
1614 : :
1615 : : /* ARGSUSED */
1616 : : static int
1617 : 76634 : channel_handle_rfd(Channel *c, fd_set *readset, fd_set *writeset)
1618 : : {
1619 : : char buf[CHAN_RBUF];
1620 : : int len, force;
1621 : :
1622 [ - + ][ # # ]: 76634 : force = c->isatty && c->detach_close && c->istate != CHAN_INPUT_CLOSED;
[ # # ]
1623 [ + + ][ + - ]: 76634 : if (c->rfd != -1 && (force || FD_ISSET(c->rfd, readset))) {
[ - + ][ # # ]
[ + + ]
1624 : 12071 : errno = 0;
1625 : 24142 : len = read(c->rfd, buf, sizeof(buf));
1626 [ - + ][ # # ]: 12071 : if (len < 0 && (errno == EINTR ||
[ # # ]
1627 [ # # ]: 0 : ((errno == EAGAIN || errno == EWOULDBLOCK) && !force)))
1628 : : return 1;
1629 : : #ifndef PTY_ZEROREAD
1630 [ + + ]: 12071 : if (len <= 0) {
1631 : : #else
1632 : : if ((!c->isatty && len <= 0) ||
1633 : : (c->isatty && (len < 0 || (len == 0 && errno != 0)))) {
1634 : : #endif
1635 : 204 : debug2("channel %d: read<=0 rfd %d len %d",
1636 : : c->self, c->rfd, len);
1637 [ - + ]: 204 : if (c->type != SSH_CHANNEL_OPEN) {
1638 : 0 : debug2("channel %d: not open", c->self);
1639 : 0 : chan_mark_dead(c);
1640 : : return -1;
1641 [ - + ]: 204 : } else if (compat13) {
1642 : 0 : buffer_clear(&c->output);
1643 : 0 : c->type = SSH_CHANNEL_INPUT_DRAINING;
1644 : 0 : debug2("channel %d: input draining.", c->self);
1645 : : } else {
1646 : 204 : chan_read_failed(c);
1647 : : }
1648 : : return -1;
1649 : : }
1650 [ - + ]: 11867 : if (c->input_filter != NULL) {
1651 [ # # ]: 0 : if (c->input_filter(c, buf, len) == -1) {
1652 : 0 : debug2("channel %d: filter stops", c->self);
1653 : 0 : chan_read_failed(c);
1654 : : }
1655 [ - + ]: 11867 : } else if (c->datagram) {
1656 : 0 : buffer_put_string(&c->input, buf, len);
1657 : : } else {
1658 : 11867 : buffer_append(&c->input, buf, len);
1659 : : }
1660 : : }
1661 : : return 1;
1662 : : }
1663 : :
1664 : : /* ARGSUSED */
1665 : : static int
1666 : 76634 : channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset)
1667 : : {
1668 : : struct termios tio;
1669 : 76634 : u_char *data = NULL, *buf;
1670 : 76634 : u_int dlen, olen = 0;
1671 : : int len;
1672 : :
1673 : : /* Send buffered output data to the socket. */
1674 [ + + ][ + + ]: 153192 : if (c->wfd != -1 &&
1675 [ - + ][ # # ]: 78880 : FD_ISSET(c->wfd, writeset) &&
[ + - ]
1676 : 2322 : buffer_len(&c->output) > 0) {
1677 : 2322 : olen = buffer_len(&c->output);
1678 [ - + ]: 2322 : if (c->output_filter != NULL) {
1679 [ # # ]: 0 : if ((buf = c->output_filter(c, &data, &dlen)) == NULL) {
1680 : 0 : debug2("channel %d: filter stops", c->self);
1681 [ # # ]: 0 : if (c->type != SSH_CHANNEL_OPEN)
1682 : 0 : chan_mark_dead(c);
1683 : : else
1684 : 0 : chan_write_failed(c);
1685 : : return -1;
1686 : : }
1687 [ - + ]: 2322 : } else if (c->datagram) {
1688 : 0 : buf = data = buffer_get_string(&c->output, &dlen);
1689 : : } else {
1690 : 2322 : buf = data = buffer_ptr(&c->output);
1691 : 2322 : dlen = buffer_len(&c->output);
1692 : : }
1693 : :
1694 [ - + ]: 2322 : if (c->datagram) {
1695 : : /* ignore truncated writes, datagrams might get lost */
1696 : 0 : len = write(c->wfd, buf, dlen);
1697 : 0 : free(data);
1698 [ # # ][ # # ]: 0 : if (len < 0 && (errno == EINTR || errno == EAGAIN ||
[ # # ]
1699 : : errno == EWOULDBLOCK))
1700 : : return 1;
1701 [ # # ]: 0 : if (len <= 0) {
1702 [ # # ]: 0 : if (c->type != SSH_CHANNEL_OPEN)
1703 : 0 : chan_mark_dead(c);
1704 : : else
1705 : 0 : chan_write_failed(c);
1706 : : return -1;
1707 : : }
1708 : : goto out;
1709 : : }
1710 : : #ifdef _AIX
1711 : : /* XXX: Later AIX versions can't push as much data to tty */
1712 : : if (compat20 && c->wfd_isatty)
1713 : : dlen = MIN(dlen, 8*1024);
1714 : : #endif
1715 : :
1716 : 2322 : len = write(c->wfd, buf, dlen);
1717 [ - + # # ]: 2322 : if (len < 0 &&
1718 [ # # ]: 0 : (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))
1719 : : return 1;
1720 [ - + ]: 2322 : if (len <= 0) {
1721 [ # # ]: 0 : if (c->type != SSH_CHANNEL_OPEN) {
1722 : 0 : debug2("channel %d: not open", c->self);
1723 : 0 : chan_mark_dead(c);
1724 : : return -1;
1725 [ # # ]: 0 : } else if (compat13) {
1726 : 0 : buffer_clear(&c->output);
1727 : 0 : debug2("channel %d: input draining.", c->self);
1728 : 0 : c->type = SSH_CHANNEL_INPUT_DRAINING;
1729 : : } else {
1730 : 0 : chan_write_failed(c);
1731 : : }
1732 : : return -1;
1733 : : }
1734 : : #ifndef BROKEN_TCGETATTR_ICANON
1735 [ + + ][ - + ]: 2322 : if (compat20 && c->isatty && dlen >= 1 && buf[0] != '\r') {
[ # # ][ # # ]
1736 [ # # ]: 0 : if (tcgetattr(c->wfd, &tio) == 0 &&
1737 [ # # ]: 0 : !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) {
1738 : : /*
1739 : : * Simulate echo to reduce the impact of
1740 : : * traffic analysis. We need to match the
1741 : : * size of a SSH2_MSG_CHANNEL_DATA message
1742 : : * (4 byte channel id + buf)
1743 : : */
1744 : 0 : packet_send_ignore(4 + len);
1745 : 0 : packet_send();
1746 : : }
1747 : : }
1748 : : #endif
1749 : 2322 : buffer_consume(&c->output, len);
1750 : : }
1751 : : out:
1752 [ + + ][ + + ]: 76634 : if (compat20 && olen > 0)
1753 : 1708 : c->local_consumed += olen - buffer_len(&c->output);
1754 : : return 1;
1755 : : }
1756 : :
1757 : : static int
1758 : 43792 : channel_handle_efd(Channel *c, fd_set *readset, fd_set *writeset)
1759 : : {
1760 : : char buf[CHAN_RBUF];
1761 : : int len;
1762 : :
1763 : : /** XXX handle drain efd, too */
1764 [ + + ]: 43792 : if (c->efd != -1) {
1765 [ + + ][ + + ]: 53649 : if (c->extended_usage == CHAN_EXTENDED_WRITE &&
1766 [ - + ][ # # ]: 26897 : FD_ISSET(c->efd, writeset) &&
[ + - ]
1767 : 289 : buffer_len(&c->extended) > 0) {
1768 : 289 : len = write(c->efd, buffer_ptr(&c->extended),
1769 : 289 : buffer_len(&c->extended));
1770 : 289 : debug2("channel %d: written %d to efd %d",
1771 : : c->self, len, c->efd);
1772 [ - + ][ # # ]: 289 : if (len < 0 && (errno == EINTR || errno == EAGAIN ||
[ # # ]
1773 : : errno == EWOULDBLOCK))
1774 : : return 1;
1775 [ - + ]: 289 : if (len <= 0) {
1776 : 0 : debug2("channel %d: closing write-efd %d",
1777 : : c->self, c->efd);
1778 : 0 : channel_close_fd(&c->efd);
1779 : : } else {
1780 : 289 : buffer_consume(&c->extended, len);
1781 : 289 : c->local_consumed += len;
1782 : : }
1783 [ + - ][ + + ]: 26752 : } else if (c->efd != -1 &&
1784 : 26752 : (c->extended_usage == CHAN_EXTENDED_READ ||
1785 [ + + ]: 433 : c->extended_usage == CHAN_EXTENDED_IGNORE) &&
1786 [ - + ][ # # ]: 422 : (c->detach_close || FD_ISSET(c->efd, readset))) {
[ + + ]
1787 : 30 : len = read(c->efd, buf, sizeof(buf));
1788 : 15 : debug2("channel %d: read %d from efd %d",
1789 : : c->self, len, c->efd);
1790 [ - + ][ # # ]: 15 : if (len < 0 && (errno == EINTR || ((errno == EAGAIN ||
[ # # ]
1791 [ # # ]: 0 : errno == EWOULDBLOCK) && !c->detach_close)))
1792 : : return 1;
1793 [ + - ]: 15 : if (len <= 0) {
1794 : 15 : debug2("channel %d: closing read-efd %d",
1795 : : c->self, c->efd);
1796 : 15 : channel_close_fd(&c->efd);
1797 : : } else {
1798 [ # # ]: 0 : if (c->extended_usage == CHAN_EXTENDED_IGNORE) {
1799 : 0 : debug3("channel %d: discard efd",
1800 : : c->self);
1801 : : } else
1802 : 0 : buffer_append(&c->extended, buf, len);
1803 : : }
1804 : : }
1805 : : }
1806 : : return 1;
1807 : : }
1808 : :
1809 : : static int
1810 : 43792 : channel_check_window(Channel *c)
1811 : : {
1812 [ + + ][ + + ]: 43792 : if (c->type == SSH_CHANNEL_OPEN &&
1813 [ + + ]: 43701 : !(c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD)) &&
1814 : 43701 : ((c->local_window_max - c->local_window >
1815 [ - + ]: 43200 : c->local_maxpacket*3) ||
1816 [ + + ]: 501 : c->local_window < c->local_window_max/2) &&
1817 : 501 : c->local_consumed > 0) {
1818 : 255 : packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
1819 : 255 : packet_put_int(c->remote_id);
1820 : 255 : packet_put_int(c->local_consumed);
1821 : 255 : packet_send();
1822 : 255 : debug2("channel %d: window %d sent adjust %d",
1823 : : c->self, c->local_window,
1824 : : c->local_consumed);
1825 : 255 : c->local_window += c->local_consumed;
1826 : 255 : c->local_consumed = 0;
1827 : : }
1828 : 43792 : return 1;
1829 : : }
1830 : :
1831 : : static void
1832 : 76634 : channel_post_open(Channel *c, fd_set *readset, fd_set *writeset)
1833 : : {
1834 : 76634 : channel_handle_rfd(c, readset, writeset);
1835 : 76634 : channel_handle_wfd(c, readset, writeset);
1836 [ + + ]: 76634 : if (!compat20)
1837 : 76634 : return;
1838 : 43792 : channel_handle_efd(c, readset, writeset);
1839 : 43792 : channel_check_window(c);
1840 : : }
1841 : :
1842 : : static u_int
1843 : 140 : read_mux(Channel *c, u_int need)
1844 : : {
1845 : : char buf[CHAN_RBUF];
1846 : : int len;
1847 : : u_int rlen;
1848 : :
1849 [ + - ]: 140 : if (buffer_len(&c->input) < need) {
1850 : 140 : rlen = need - buffer_len(&c->input);
1851 : 280 : len = read(c->rfd, buf, MIN(rlen, CHAN_RBUF));
1852 [ + + ]: 140 : if (len <= 0) {
1853 [ + - ]: 8 : if (errno != EINTR && errno != EAGAIN) {
1854 : 8 : debug2("channel %d: ctl read<=0 rfd %d len %d",
1855 : : c->self, c->rfd, len);
1856 : 8 : chan_read_failed(c);
1857 : 8 : return 0;
1858 : : }
1859 : : } else
1860 : 132 : buffer_append(&c->input, buf, len);
1861 : : }
1862 : 132 : return buffer_len(&c->input);
1863 : : }
1864 : :
1865 : : static void
1866 : 901 : channel_post_mux_client(Channel *c, fd_set *readset, fd_set *writeset)
1867 : : {
1868 : : u_int need;
1869 : : ssize_t len;
1870 : :
1871 [ - + ]: 901 : if (!compat20)
1872 : 0 : fatal("%s: entered with !compat20", __func__);
1873 : :
1874 [ + - ][ + + ]: 901 : if (c->rfd != -1 && !c->mux_pause && FD_ISSET(c->rfd, readset) &&
[ - + ][ # # ]
[ + + ][ + + ]
1875 : 89 : (c->istate == CHAN_INPUT_OPEN ||
1876 : : c->istate == CHAN_INPUT_WAIT_DRAIN)) {
1877 : : /*
1878 : : * Don't not read past the precise end of packets to
1879 : : * avoid disrupting fd passing.
1880 : : */
1881 [ + + ]: 74 : if (read_mux(c, 4) < 4) /* read header */
1882 : : return;
1883 : 66 : need = get_u32(buffer_ptr(&c->input));
1884 : : #define CHANNEL_MUX_MAX_PACKET (256 * 1024)
1885 [ - + ]: 66 : if (need > CHANNEL_MUX_MAX_PACKET) {
1886 : 0 : debug2("channel %d: packet too big %u > %u",
1887 : : c->self, CHANNEL_MUX_MAX_PACKET, need);
1888 : 0 : chan_rcvd_oclose(c);
1889 : 0 : return;
1890 : : }
1891 [ + - ]: 66 : if (read_mux(c, need + 4) < need + 4) /* read body */
1892 : : return;
1893 [ - + ]: 66 : if (c->mux_rcb(c) != 0) {
1894 : 0 : debug("channel %d: mux_rcb failed", c->self);
1895 : 0 : chan_mark_dead(c);
1896 : 0 : return;
1897 : : }
1898 : : }
1899 : :
1900 [ + - ][ - + ]: 974 : if (c->wfd != -1 && FD_ISSET(c->wfd, writeset) &&
[ # # ]
[ + + + - ]
1901 : 81 : buffer_len(&c->output) > 0) {
1902 : 81 : len = write(c->wfd, buffer_ptr(&c->output),
1903 : 81 : buffer_len(&c->output));
1904 [ - + ][ # # ]: 81 : if (len < 0 && (errno == EINTR || errno == EAGAIN))
1905 : : return;
1906 [ - + ]: 81 : if (len <= 0) {
1907 : 0 : chan_mark_dead(c);
1908 : 0 : return;
1909 : : }
1910 : 81 : buffer_consume(&c->output, len);
1911 : : }
1912 : : }
1913 : :
1914 : : static void
1915 : 1001 : channel_post_mux_listener(Channel *c, fd_set *readset, fd_set *writeset)
1916 : : {
1917 : : Channel *nc;
1918 : : struct sockaddr_storage addr;
1919 : : socklen_t addrlen;
1920 : : int newsock;
1921 : : uid_t euid;
1922 : : gid_t egid;
1923 : :
1924 [ - + ][ # # ]: 1001 : if (!FD_ISSET(c->sock, readset))
[ + + ]
1925 : 976 : return;
1926 : :
1927 : 25 : debug("multiplexing control connection");
1928 : :
1929 : : /*
1930 : : * Accept connection on control socket
1931 : : */
1932 : : memset(&addr, 0, sizeof(addr));
1933 : 25 : addrlen = sizeof(addr);
1934 [ - + ]: 25 : if ((newsock = accept(c->sock, (struct sockaddr*)&addr,
1935 : : &addrlen)) == -1) {
1936 : 0 : error("%s accept: %s", __func__, strerror(errno));
1937 [ # # ]: 0 : if (errno == EMFILE || errno == ENFILE)
1938 : 0 : c->notbefore = monotime() + 1;
1939 : : return;
1940 : : }
1941 : :
1942 [ - + ]: 25 : if (getpeereid(newsock, &euid, &egid) < 0) {
1943 : 0 : error("%s getpeereid failed: %s", __func__,
1944 : 0 : strerror(errno));
1945 : 0 : close(newsock);
1946 : 0 : return;
1947 : : }
1948 [ + - ][ - + ]: 25 : if ((euid != 0) && (getuid() != euid)) {
1949 : 0 : error("multiplex uid mismatch: peer euid %u != uid %u",
1950 : : (u_int)euid, (u_int)getuid());
1951 : 0 : close(newsock);
1952 : 0 : return;
1953 : : }
1954 : 25 : nc = channel_new("multiplex client", SSH_CHANNEL_MUX_CLIENT,
1955 : : newsock, newsock, -1, c->local_window_max,
1956 : : c->local_maxpacket, 0, "mux-control", 1);
1957 : 25 : nc->mux_rcb = c->mux_rcb;
1958 : 25 : debug3("%s: new mux channel %d fd %d", __func__,
1959 : : nc->self, nc->sock);
1960 : : /* establish state */
1961 : 25 : nc->mux_rcb(nc);
1962 : : /* mux state transitions must not elicit protocol messages */
1963 : 25 : nc->flags |= CHAN_LOCAL;
1964 : : }
1965 : :
1966 : : /* ARGSUSED */
1967 : : static void
1968 : 0 : channel_post_output_drain_13(Channel *c, fd_set *readset, fd_set *writeset)
1969 : : {
1970 : : int len;
1971 : :
1972 : : /* Send buffered output data to the socket. */
1973 [ # # ][ # # ]: 0 : if (FD_ISSET(c->sock, writeset) && buffer_len(&c->output) > 0) {
[ # # ][ # # ]
1974 : 0 : len = write(c->sock, buffer_ptr(&c->output),
1975 : 0 : buffer_len(&c->output));
1976 [ # # ]: 0 : if (len <= 0)
1977 : 0 : buffer_clear(&c->output);
1978 : : else
1979 : 0 : buffer_consume(&c->output, len);
1980 : : }
1981 : 0 : }
1982 : :
1983 : : static void
1984 : 1404 : channel_handler_init_20(void)
1985 : : {
1986 : 1404 : channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open;
1987 : 1404 : channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open;
1988 : 1404 : channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener;
1989 : 1404 : channel_pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener;
1990 : 1404 : channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener;
1991 : 1404 : channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
1992 : 1404 : channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
1993 : 1404 : channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic;
1994 : 1404 : channel_pre[SSH_CHANNEL_MUX_LISTENER] = &channel_pre_listener;
1995 : 1404 : channel_pre[SSH_CHANNEL_MUX_CLIENT] = &channel_pre_mux_client;
1996 : :
1997 : 1404 : channel_post[SSH_CHANNEL_OPEN] = &channel_post_open;
1998 : 1404 : channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
1999 : 1404 : channel_post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener;
2000 : 1404 : channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
2001 : 1404 : channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
2002 : 1404 : channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
2003 : 1404 : channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open;
2004 : 1404 : channel_post[SSH_CHANNEL_MUX_LISTENER] = &channel_post_mux_listener;
2005 : 1404 : channel_post[SSH_CHANNEL_MUX_CLIENT] = &channel_post_mux_client;
2006 : 1404 : }
2007 : :
2008 : : static void
2009 : 0 : channel_handler_init_13(void)
2010 : : {
2011 : 0 : channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open_13;
2012 : 0 : channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open_13;
2013 : 0 : channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener;
2014 : 0 : channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener;
2015 : 0 : channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
2016 : 0 : channel_pre[SSH_CHANNEL_INPUT_DRAINING] = &channel_pre_input_draining;
2017 : 0 : channel_pre[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_pre_output_draining;
2018 : 0 : channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
2019 : 0 : channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic;
2020 : :
2021 : 0 : channel_post[SSH_CHANNEL_OPEN] = &channel_post_open;
2022 : 0 : channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
2023 : 0 : channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
2024 : 0 : channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
2025 : 0 : channel_post[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_post_output_drain_13;
2026 : 0 : channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
2027 : 0 : channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open;
2028 : 0 : }
2029 : :
2030 : : static void
2031 : 84 : channel_handler_init_15(void)
2032 : : {
2033 : 84 : channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open;
2034 : 84 : channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open;
2035 : 84 : channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener;
2036 : 84 : channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener;
2037 : 84 : channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
2038 : 84 : channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
2039 : 84 : channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic;
2040 : :
2041 : 84 : channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
2042 : 84 : channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
2043 : 84 : channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
2044 : 84 : channel_post[SSH_CHANNEL_OPEN] = &channel_post_open;
2045 : 84 : channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
2046 : 84 : channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open;
2047 : 84 : }
2048 : :
2049 : : static void
2050 : 1488 : channel_handler_init(void)
2051 : : {
2052 : : int i;
2053 : :
2054 [ + + ]: 28272 : for (i = 0; i < SSH_CHANNEL_MAX_TYPE; i++) {
2055 : 26784 : channel_pre[i] = NULL;
2056 : 26784 : channel_post[i] = NULL;
2057 : : }
2058 [ + + ]: 1488 : if (compat20)
2059 : 1404 : channel_handler_init_20();
2060 [ - + ]: 84 : else if (compat13)
2061 : 0 : channel_handler_init_13();
2062 : : else
2063 : 84 : channel_handler_init_15();
2064 : 1488 : }
2065 : :
2066 : : /* gc dead channels */
2067 : : static void
2068 : 253387 : channel_garbage_collect(Channel *c)
2069 : : {
2070 [ + - ]: 253387 : if (c == NULL)
2071 : : return;
2072 [ + + ]: 253387 : if (c->detach_user != NULL) {
2073 [ + + ]: 62588 : if (!chan_is_dead(c, c->detach_close))
2074 : : return;
2075 : 744 : debug2("channel %d: gc: notify user", c->self);
2076 : 744 : c->detach_user(c->self, NULL);
2077 : : /* if we still have a callback */
2078 [ + + ]: 744 : if (c->detach_user != NULL)
2079 : : return;
2080 : 740 : debug2("channel %d: gc: user detached", c->self);
2081 : : }
2082 [ + + ]: 191539 : if (!chan_is_dead(c, 1))
2083 : : return;
2084 : 817 : debug2("channel %d: garbage collecting", c->self);
2085 : 817 : channel_free(c);
2086 : : }
2087 : :
2088 : : static void
2089 : 76140 : channel_handler(chan_fn *ftab[], fd_set *readset, fd_set *writeset,
2090 : : time_t *unpause_secs)
2091 : : {
2092 : : static int did_init = 0;
2093 : : u_int i, oalloc;
2094 : : Channel *c;
2095 : : time_t now;
2096 : :
2097 [ + + ]: 76140 : if (!did_init) {
2098 : 1488 : channel_handler_init();
2099 : 1488 : did_init = 1;
2100 : : }
2101 : 76140 : now = monotime();
2102 [ + + ]: 76140 : if (unpause_secs != NULL)
2103 : 38070 : *unpause_secs = 0;
2104 [ + + ]: 885760 : for (i = 0, oalloc = channels_alloc; i < oalloc; i++) {
2105 : 809620 : c = channels[i];
2106 [ + + ]: 809620 : if (c == NULL)
2107 : 556153 : continue;
2108 [ + + ]: 253467 : if (c->delayed) {
2109 [ + + ]: 1726 : if (ftab == channel_pre)
2110 : 1646 : c->delayed = 0;
2111 : : else
2112 : 80 : continue;
2113 : : }
2114 [ + + ]: 253387 : if (ftab[c->type] != NULL) {
2115 : : /*
2116 : : * Run handlers that are not paused.
2117 : : */
2118 [ + - ]: 247308 : if (c->notbefore <= now)
2119 : 247308 : (*ftab[c->type])(c, readset, writeset);
2120 [ # # ]: 0 : else if (unpause_secs != NULL) {
2121 : : /*
2122 : : * Collect the time that the earliest
2123 : : * channel comes off pause.
2124 : : */
2125 : 0 : debug3("%s: chan %d: skip for %d more seconds",
2126 : : __func__, c->self,
2127 : : (int)(c->notbefore - now));
2128 [ # # ][ # # ]: 0 : if (*unpause_secs == 0 ||
2129 : 0 : (c->notbefore - now) < *unpause_secs)
2130 : 0 : *unpause_secs = c->notbefore - now;
2131 : : }
2132 : : }
2133 : 253387 : channel_garbage_collect(c);
2134 : : }
2135 [ + + ][ - + ]: 76140 : if (unpause_secs != NULL && *unpause_secs != 0)
2136 : 0 : debug3("%s: first channel unpauses in %d seconds",
2137 : : __func__, (int)*unpause_secs);
2138 : 76140 : }
2139 : :
2140 : : /*
2141 : : * Allocate/update select bitmasks and add any bits relevant to channels in
2142 : : * select bitmasks.
2143 : : */
2144 : : void
2145 : 40149 : channel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
2146 : : u_int *nallocp, time_t *minwait_secs, int rekeying)
2147 : : {
2148 : : u_int n, sz, nfdset;
2149 : :
2150 : 40149 : n = MAX(*maxfdp, channel_max_fd);
2151 : :
2152 : 40149 : nfdset = howmany(n+1, NFDBITS);
2153 : : /* Explicitly test here, because xrealloc isn't always called */
2154 [ + - ][ - + ]: 40149 : if (nfdset && SIZE_T_MAX / nfdset < sizeof(fd_mask))
2155 : 0 : fatal("channel_prepare_select: max_fd (%d) is too large", n);
2156 : 40149 : sz = nfdset * sizeof(fd_mask);
2157 : :
2158 : : /* perhaps check sz < nalloc/2 and shrink? */
2159 [ + + ][ - + ]: 40149 : if (*readsetp == NULL || sz > *nallocp) {
2160 : 1488 : *readsetp = xrealloc(*readsetp, nfdset, sizeof(fd_mask));
2161 : 1488 : *writesetp = xrealloc(*writesetp, nfdset, sizeof(fd_mask));
2162 : 1488 : *nallocp = sz;
2163 : : }
2164 : 40149 : *maxfdp = n;
2165 : 40149 : memset(*readsetp, 0, sz);
2166 : 40149 : memset(*writesetp, 0, sz);
2167 : :
2168 [ + + ]: 40149 : if (!rekeying)
2169 : 38070 : channel_handler(channel_pre, *readsetp, *writesetp,
2170 : : minwait_secs);
2171 : 40149 : }
2172 : :
2173 : : /*
2174 : : * After select, perform any appropriate operations for channels which have
2175 : : * events pending.
2176 : : */
2177 : : void
2178 : 38070 : channel_after_select(fd_set *readset, fd_set *writeset)
2179 : : {
2180 : 38070 : channel_handler(channel_post, readset, writeset, NULL);
2181 : 38070 : }
2182 : :
2183 : :
2184 : : /* If there is data to send to the connection, enqueue some of it now. */
2185 : : void
2186 : 32031 : channel_output_poll(void)
2187 : : {
2188 : : Channel *c;
2189 : : u_int i, len;
2190 : :
2191 [ + + ]: 376681 : for (i = 0; i < channels_alloc; i++) {
2192 : 344650 : c = channels[i];
2193 [ + + ]: 344650 : if (c == NULL)
2194 : 223535 : continue;
2195 : :
2196 : : /*
2197 : : * We are only interested in channels that can have buffered
2198 : : * incoming data.
2199 : : */
2200 [ - + ]: 121115 : if (compat13) {
2201 [ # # ]: 0 : if (c->type != SSH_CHANNEL_OPEN &&
2202 : : c->type != SSH_CHANNEL_INPUT_DRAINING)
2203 : 0 : continue;
2204 : : } else {
2205 [ + + ]: 121115 : if (c->type != SSH_CHANNEL_OPEN)
2206 : 49731 : continue;
2207 : : }
2208 [ + + ][ + + ]: 71384 : if (compat20 &&
2209 : 38496 : (c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) {
2210 : : /* XXX is this true? */
2211 : 796 : debug3("channel %d: will not send data after close", c->self);
2212 : 796 : continue;
2213 : : }
2214 : :
2215 : : /* Get the amount of buffered data for this channel. */
2216 [ + + ]: 70588 : if ((c->istate == CHAN_INPUT_OPEN ||
2217 [ + + ]: 64675 : c->istate == CHAN_INPUT_WAIT_DRAIN) &&
2218 : 64675 : (len = buffer_len(&c->input)) > 0) {
2219 [ - + ]: 8595 : if (c->datagram) {
2220 [ # # ]: 0 : if (len > 0) {
2221 : : u_char *data;
2222 : : u_int dlen;
2223 : :
2224 : 0 : data = buffer_get_string(&c->input,
2225 : : &dlen);
2226 [ # # ][ # # ]: 0 : if (dlen > c->remote_window ||
2227 : 0 : dlen > c->remote_maxpacket) {
2228 : 0 : debug("channel %d: datagram "
2229 : : "too big for channel",
2230 : : c->self);
2231 : 0 : free(data);
2232 : 0 : continue;
2233 : : }
2234 : 0 : packet_start(SSH2_MSG_CHANNEL_DATA);
2235 : 0 : packet_put_int(c->remote_id);
2236 : 0 : packet_put_string(data, dlen);
2237 : 0 : packet_send();
2238 : 0 : c->remote_window -= dlen + 4;
2239 : 0 : free(data);
2240 : : }
2241 : 0 : continue;
2242 : : }
2243 : : /*
2244 : : * Send some data for the other side over the secure
2245 : : * connection.
2246 : : */
2247 [ + + ]: 8595 : if (compat20) {
2248 [ - + ]: 7961 : if (len > c->remote_window)
2249 : 0 : len = c->remote_window;
2250 [ + + ]: 7961 : if (len > c->remote_maxpacket)
2251 : 2291 : len = c->remote_maxpacket;
2252 : : } else {
2253 [ - + ]: 634 : if (packet_is_interactive()) {
2254 [ # # ]: 0 : if (len > 1024)
2255 : 0 : len = 512;
2256 : : } else {
2257 : : /* Keep the packets at reasonable size. */
2258 [ - + ]: 634 : if (len > packet_get_maxsize()/2)
2259 : 0 : len = packet_get_maxsize()/2;
2260 : : }
2261 : : }
2262 [ + - ]: 8595 : if (len > 0) {
2263 [ + + ]: 8595 : packet_start(compat20 ?
2264 : : SSH2_MSG_CHANNEL_DATA : SSH_MSG_CHANNEL_DATA);
2265 : 8595 : packet_put_int(c->remote_id);
2266 : 8595 : packet_put_string(buffer_ptr(&c->input), len);
2267 : 8595 : packet_send();
2268 : 8595 : buffer_consume(&c->input, len);
2269 : 8595 : c->remote_window -= len;
2270 : : }
2271 [ + + ]: 61993 : } else if (c->istate == CHAN_INPUT_WAIT_DRAIN) {
2272 [ - + ]: 204 : if (compat13)
2273 : 0 : fatal("cannot happen: istate == INPUT_WAIT_DRAIN for proto 1.3");
2274 : : /*
2275 : : * input-buffer is empty and read-socket shutdown:
2276 : : * tell peer, that we will not send more data: send IEOF.
2277 : : * hack for extended data: delay EOF if EFD still in use.
2278 : : */
2279 [ + + ][ + + ]: 204 : if (CHANNEL_EFD_INPUT_ACTIVE(c))
[ + - ][ - + ]
2280 : 0 : debug2("channel %d: ibuf_empty delayed efd %d/(%d)",
2281 : 0 : c->self, c->efd, buffer_len(&c->extended));
2282 : : else
2283 : 204 : chan_ibuf_empty(c);
2284 : : }
2285 : : /* Send extended data, i.e. stderr */
2286 [ + + ][ + + ]: 70588 : if (compat20 &&
2287 [ + + ]: 32742 : !(c->flags & CHAN_EOF_SENT) &&
2288 [ + + ]: 31340 : c->remote_window > 0 &&
2289 [ - + ]: 142 : (len = buffer_len(&c->extended)) > 0 &&
2290 : 142 : c->extended_usage == CHAN_EXTENDED_READ) {
2291 : 0 : debug2("channel %d: rwin %u elen %u euse %d",
2292 : : c->self, c->remote_window, buffer_len(&c->extended),
2293 : : c->extended_usage);
2294 [ # # ]: 0 : if (len > c->remote_window)
2295 : 0 : len = c->remote_window;
2296 [ # # ]: 0 : if (len > c->remote_maxpacket)
2297 : 0 : len = c->remote_maxpacket;
2298 : 0 : packet_start(SSH2_MSG_CHANNEL_EXTENDED_DATA);
2299 : 0 : packet_put_int(c->remote_id);
2300 : 0 : packet_put_int(SSH2_EXTENDED_DATA_STDERR);
2301 : 0 : packet_put_string(buffer_ptr(&c->extended), len);
2302 : 0 : packet_send();
2303 : 0 : buffer_consume(&c->extended, len);
2304 : 0 : c->remote_window -= len;
2305 : 0 : debug2("channel %d: sent ext data %d", c->self, len);
2306 : : }
2307 : : }
2308 : 32031 : }
2309 : :
2310 : :
2311 : : /* -- protocol input */
2312 : :
2313 : : /* ARGSUSED */
2314 : : void
2315 : 2697 : channel_input_data(int type, u_int32_t seq, void *ctxt)
2316 : : {
2317 : : int id;
2318 : : char *data;
2319 : : u_int data_len, win_len;
2320 : : Channel *c;
2321 : :
2322 : : /* Get the channel number and verify it. */
2323 : 2697 : id = packet_get_int();
2324 : 2697 : c = channel_lookup(id);
2325 [ - + ]: 2697 : if (c == NULL)
2326 : 0 : packet_disconnect("Received data for nonexistent channel %d.", id);
2327 : :
2328 : : /* Ignore any data for non-open channels (might happen on close) */
2329 [ + - ]: 2697 : if (c->type != SSH_CHANNEL_OPEN &&
2330 : : c->type != SSH_CHANNEL_X11_OPEN)
2331 : 0 : return;
2332 : :
2333 : : /* Get the data. */
2334 : 2697 : data = packet_get_string_ptr(&data_len);
2335 : 2697 : win_len = data_len;
2336 [ - + ]: 2697 : if (c->datagram)
2337 : 0 : win_len += 4; /* string length header */
2338 : :
2339 : : /*
2340 : : * Ignore data for protocol > 1.3 if output end is no longer open.
2341 : : * For protocol 2 the sending side is reducing its window as it sends
2342 : : * data, so we must 'fake' consumption of the data in order to ensure
2343 : : * that window updates are sent back. Otherwise the connection might
2344 : : * deadlock.
2345 : : */
2346 [ + - ][ - + ]: 2697 : if (!compat13 && c->ostate != CHAN_OUTPUT_OPEN) {
2347 [ # # ]: 0 : if (compat20) {
2348 : 0 : c->local_window -= win_len;
2349 : 0 : c->local_consumed += win_len;
2350 : : }
2351 : : return;
2352 : : }
2353 : :
2354 [ + + ]: 2697 : if (compat20) {
2355 [ - + ]: 2061 : if (win_len > c->local_maxpacket) {
2356 : 0 : logit("channel %d: rcvd big packet %d, maxpack %d",
2357 : : c->self, win_len, c->local_maxpacket);
2358 : : }
2359 [ - + ]: 2061 : if (win_len > c->local_window) {
2360 : 0 : logit("channel %d: rcvd too much data %d, win %d",
2361 : : c->self, win_len, c->local_window);
2362 : 0 : return;
2363 : : }
2364 : 2061 : c->local_window -= win_len;
2365 : : }
2366 [ - + ]: 2697 : if (c->datagram)
2367 : 0 : buffer_put_string(&c->output, data, data_len);
2368 : : else
2369 : 2697 : buffer_append(&c->output, data, data_len);
2370 [ - + ]: 2697 : packet_check_eom();
2371 : : }
2372 : :
2373 : : /* ARGSUSED */
2374 : : void
2375 : 289 : channel_input_extended_data(int type, u_int32_t seq, void *ctxt)
2376 : : {
2377 : : int id;
2378 : : char *data;
2379 : : u_int data_len, tcode;
2380 : : Channel *c;
2381 : :
2382 : : /* Get the channel number and verify it. */
2383 : 289 : id = packet_get_int();
2384 : 289 : c = channel_lookup(id);
2385 : :
2386 [ - + ]: 289 : if (c == NULL)
2387 : 0 : packet_disconnect("Received extended_data for bad channel %d.", id);
2388 [ - + ]: 289 : if (c->type != SSH_CHANNEL_OPEN) {
2389 : 0 : logit("channel %d: ext data for non open", id);
2390 : 0 : return;
2391 : : }
2392 [ - + ]: 289 : if (c->flags & CHAN_EOF_RCVD) {
2393 [ # # ]: 0 : if (datafellows & SSH_BUG_EXTEOF)
2394 : 0 : debug("channel %d: accepting ext data after eof", id);
2395 : : else
2396 : 0 : packet_disconnect("Received extended_data after EOF "
2397 : : "on channel %d.", id);
2398 : : }
2399 : 289 : tcode = packet_get_int();
2400 [ + - ][ + - ]: 289 : if (c->efd == -1 ||
2401 [ - + ]: 289 : c->extended_usage != CHAN_EXTENDED_WRITE ||
2402 : : tcode != SSH2_EXTENDED_DATA_STDERR) {
2403 : 0 : logit("channel %d: bad ext data", c->self);
2404 : 0 : return;
2405 : : }
2406 : 289 : data = packet_get_string(&data_len);
2407 [ - + ]: 289 : packet_check_eom();
2408 [ - + ]: 289 : if (data_len > c->local_window) {
2409 : 0 : logit("channel %d: rcvd too much extended_data %d, win %d",
2410 : : c->self, data_len, c->local_window);
2411 : 0 : free(data);
2412 : 0 : return;
2413 : : }
2414 : 289 : debug2("channel %d: rcvd ext data %d", c->self, data_len);
2415 : 289 : c->local_window -= data_len;
2416 : 289 : buffer_append(&c->extended, data, data_len);
2417 : 289 : free(data);
2418 : : }
2419 : :
2420 : : /* ARGSUSED */
2421 : : void
2422 : 783 : channel_input_ieof(int type, u_int32_t seq, void *ctxt)
2423 : : {
2424 : : int id;
2425 : : Channel *c;
2426 : :
2427 : 783 : id = packet_get_int();
2428 [ - + ]: 783 : packet_check_eom();
2429 : 783 : c = channel_lookup(id);
2430 [ - + ]: 783 : if (c == NULL)
2431 : 0 : packet_disconnect("Received ieof for nonexistent channel %d.", id);
2432 : 783 : chan_rcvd_ieof(c);
2433 : :
2434 : : /* XXX force input close */
2435 [ + + ][ + - ]: 783 : if (c->force_drain && c->istate == CHAN_INPUT_OPEN) {
2436 : 4 : debug("channel %d: FORCE input drain", c->self);
2437 : 4 : c->istate = CHAN_INPUT_WAIT_DRAIN;
2438 [ + - ]: 4 : if (buffer_len(&c->input) == 0)
2439 : 4 : chan_ibuf_empty(c);
2440 : : }
2441 : :
2442 : 783 : }
2443 : :
2444 : : /* ARGSUSED */
2445 : : void
2446 : 0 : channel_input_close(int type, u_int32_t seq, void *ctxt)
2447 : : {
2448 : : int id;
2449 : : Channel *c;
2450 : :
2451 : 0 : id = packet_get_int();
2452 [ # # ]: 0 : packet_check_eom();
2453 : 0 : c = channel_lookup(id);
2454 [ # # ]: 0 : if (c == NULL)
2455 : 0 : packet_disconnect("Received close for nonexistent channel %d.", id);
2456 : :
2457 : : /*
2458 : : * Send a confirmation that we have closed the channel and no more
2459 : : * data is coming for it.
2460 : : */
2461 : 0 : packet_start(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION);
2462 : 0 : packet_put_int(c->remote_id);
2463 : 0 : packet_send();
2464 : :
2465 : : /*
2466 : : * If the channel is in closed state, we have sent a close request,
2467 : : * and the other side will eventually respond with a confirmation.
2468 : : * Thus, we cannot free the channel here, because then there would be
2469 : : * no-one to receive the confirmation. The channel gets freed when
2470 : : * the confirmation arrives.
2471 : : */
2472 [ # # ]: 0 : if (c->type != SSH_CHANNEL_CLOSED) {
2473 : : /*
2474 : : * Not a closed channel - mark it as draining, which will
2475 : : * cause it to be freed later.
2476 : : */
2477 : 0 : buffer_clear(&c->input);
2478 : 0 : c->type = SSH_CHANNEL_OUTPUT_DRAINING;
2479 : : }
2480 : 0 : }
2481 : :
2482 : : /* proto version 1.5 overloads CLOSE_CONFIRMATION with OCLOSE */
2483 : : /* ARGSUSED */
2484 : : void
2485 : 791 : channel_input_oclose(int type, u_int32_t seq, void *ctxt)
2486 : : {
2487 : 791 : int id = packet_get_int();
2488 : 791 : Channel *c = channel_lookup(id);
2489 : :
2490 [ - + ]: 791 : packet_check_eom();
2491 [ - + ]: 791 : if (c == NULL)
2492 : 0 : packet_disconnect("Received oclose for nonexistent channel %d.", id);
2493 : 791 : chan_rcvd_oclose(c);
2494 : 791 : }
2495 : :
2496 : : /* ARGSUSED */
2497 : : void
2498 : 0 : channel_input_close_confirmation(int type, u_int32_t seq, void *ctxt)
2499 : : {
2500 : 0 : int id = packet_get_int();
2501 : 0 : Channel *c = channel_lookup(id);
2502 : :
2503 [ # # ]: 0 : packet_check_eom();
2504 [ # # ]: 0 : if (c == NULL)
2505 : 0 : packet_disconnect("Received close confirmation for "
2506 : : "out-of-range channel %d.", id);
2507 [ # # ]: 0 : if (c->type != SSH_CHANNEL_CLOSED && c->type != SSH_CHANNEL_ABANDONED)
2508 : 0 : packet_disconnect("Received close confirmation for "
2509 : : "non-closed channel %d (type %d).", id, c->type);
2510 : 0 : channel_free(c);
2511 : 0 : }
2512 : :
2513 : : /* ARGSUSED */
2514 : : void
2515 : 741 : channel_input_open_confirmation(int type, u_int32_t seq, void *ctxt)
2516 : : {
2517 : : int id, remote_id;
2518 : : Channel *c;
2519 : :
2520 : 741 : id = packet_get_int();
2521 : 741 : c = channel_lookup(id);
2522 : :
2523 [ + - ][ - + ]: 741 : if (c==NULL || c->type != SSH_CHANNEL_OPENING)
2524 : 0 : packet_disconnect("Received open confirmation for "
2525 : : "non-opening channel %d.", id);
2526 : 741 : remote_id = packet_get_int();
2527 : : /* Record the remote channel number and mark that the channel is now open. */
2528 : 741 : c->remote_id = remote_id;
2529 : 741 : c->type = SSH_CHANNEL_OPEN;
2530 : :
2531 [ + + ]: 741 : if (compat20) {
2532 : 719 : c->remote_window = packet_get_int();
2533 : 719 : c->remote_maxpacket = packet_get_int();
2534 [ + + ]: 719 : if (c->open_confirm) {
2535 : 702 : debug2("callback start");
2536 : 702 : c->open_confirm(c->self, 1, c->open_confirm_ctx);
2537 : 702 : debug2("callback done");
2538 : : }
2539 : 719 : debug2("channel %d: open confirm rwindow %u rmax %u", c->self,
2540 : : c->remote_window, c->remote_maxpacket);
2541 : : }
2542 [ - + ]: 741 : packet_check_eom();
2543 : 741 : }
2544 : :
2545 : : static char *
2546 : : reason2txt(int reason)
2547 : : {
2548 [ - - - - : 3 : switch (reason) {
+ ]
2549 : : case SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED:
2550 : : return "administratively prohibited";
2551 : : case SSH2_OPEN_CONNECT_FAILED:
2552 : : return "connect failed";
2553 : : case SSH2_OPEN_UNKNOWN_CHANNEL_TYPE:
2554 : : return "unknown channel type";
2555 : : case SSH2_OPEN_RESOURCE_SHORTAGE:
2556 : : return "resource shortage";
2557 : : }
2558 : : return "unknown reason";
2559 : : }
2560 : :
2561 : : /* ARGSUSED */
2562 : : void
2563 : 3 : channel_input_open_failure(int type, u_int32_t seq, void *ctxt)
2564 : : {
2565 : : int id, reason;
2566 : 3 : char *msg = NULL, *lang = NULL;
2567 : : Channel *c;
2568 : :
2569 : 3 : id = packet_get_int();
2570 : 3 : c = channel_lookup(id);
2571 : :
2572 [ + - ][ - + ]: 3 : if (c==NULL || c->type != SSH_CHANNEL_OPENING)
2573 : 0 : packet_disconnect("Received open failure for "
2574 : : "non-opening channel %d.", id);
2575 [ + - ]: 3 : if (compat20) {
2576 : 3 : reason = packet_get_int();
2577 [ + - ]: 3 : if (!(datafellows & SSH_BUG_OPENFAILURE)) {
2578 : 3 : msg = packet_get_string(NULL);
2579 : 3 : lang = packet_get_string(NULL);
2580 : : }
2581 [ + - ][ - + ]: 6 : logit("channel %d: open failed: %s%s%s", id,
2582 : : reason2txt(reason), msg ? ": ": "", msg ? msg : "");
2583 : 3 : free(msg);
2584 : 3 : free(lang);
2585 [ - + ]: 3 : if (c->open_confirm) {
2586 : 0 : debug2("callback start");
2587 : 0 : c->open_confirm(c->self, 0, c->open_confirm_ctx);
2588 : 0 : debug2("callback done");
2589 : : }
2590 : : }
2591 [ - + ]: 3 : packet_check_eom();
2592 : : /* Schedule the channel for cleanup/deletion. */
2593 : 3 : chan_mark_dead(c);
2594 : 3 : }
2595 : :
2596 : : /* ARGSUSED */
2597 : : void
2598 : 1755 : channel_input_window_adjust(int type, u_int32_t seq, void *ctxt)
2599 : : {
2600 : : Channel *c;
2601 : : int id;
2602 : : u_int adjust;
2603 : :
2604 [ + - ]: 1755 : if (!compat20)
2605 : : return;
2606 : :
2607 : : /* Get the channel number and verify it. */
2608 : 1755 : id = packet_get_int();
2609 : 1755 : c = channel_lookup(id);
2610 : :
2611 [ - + ]: 1755 : if (c == NULL) {
2612 : 0 : logit("Received window adjust for non-open channel %d.", id);
2613 : 0 : return;
2614 : : }
2615 : 1755 : adjust = packet_get_int();
2616 [ - + ]: 1755 : packet_check_eom();
2617 : 1755 : debug2("channel %d: rcvd adjust %u", id, adjust);
2618 : 1755 : c->remote_window += adjust;
2619 : : }
2620 : :
2621 : : /* ARGSUSED */
2622 : : void
2623 : 22 : channel_input_port_open(int type, u_int32_t seq, void *ctxt)
2624 : : {
2625 : 22 : Channel *c = NULL;
2626 : : u_short host_port;
2627 : : char *host, *originator_string;
2628 : : int remote_id;
2629 : :
2630 : 22 : remote_id = packet_get_int();
2631 : 22 : host = packet_get_string(NULL);
2632 : 22 : host_port = packet_get_int();
2633 : :
2634 [ + - ]: 22 : if (packet_get_protocol_flags() & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) {
2635 : 22 : originator_string = packet_get_string(NULL);
2636 : : } else {
2637 : 0 : originator_string = xstrdup("unknown (remote did not supply name)");
2638 : : }
2639 [ - + ]: 22 : packet_check_eom();
2640 : 22 : c = channel_connect_to(host, host_port,
2641 : : "connected socket", originator_string);
2642 : 22 : free(originator_string);
2643 : 22 : free(host);
2644 [ - + ]: 22 : if (c == NULL) {
2645 : 0 : packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
2646 : 0 : packet_put_int(remote_id);
2647 : 0 : packet_send();
2648 : : } else
2649 : 22 : c->remote_id = remote_id;
2650 : 22 : }
2651 : :
2652 : : /* ARGSUSED */
2653 : : void
2654 : 702 : channel_input_status_confirm(int type, u_int32_t seq, void *ctxt)
2655 : : {
2656 : : Channel *c;
2657 : : struct channel_confirm *cc;
2658 : : int id;
2659 : :
2660 : : /* Reset keepalive timeout */
2661 : 702 : packet_set_alive_timeouts(0);
2662 : :
2663 : 702 : id = packet_get_int();
2664 [ - + ]: 702 : packet_check_eom();
2665 : :
2666 : 702 : debug2("channel_input_status_confirm: type %d id %d", type, id);
2667 : :
2668 [ - + ]: 702 : if ((c = channel_lookup(id)) == NULL) {
2669 : 0 : logit("channel_input_status_confirm: %d: unknown", id);
2670 : 0 : return;
2671 : : }
2672 : : ;
2673 [ + - ]: 702 : if ((cc = TAILQ_FIRST(&c->status_confirms)) == NULL)
2674 : : return;
2675 : 702 : cc->cb(type, c, cc->ctx);
2676 [ - + ]: 702 : TAILQ_REMOVE(&c->status_confirms, cc, entry);
2677 : 702 : explicit_bzero(cc, sizeof(*cc));
2678 : 702 : free(cc);
2679 : : }
2680 : :
2681 : : /* -- tcp forwarding */
2682 : :
2683 : : void
2684 : 2743 : channel_set_af(int af)
2685 : : {
2686 : 2743 : IPv4or6 = af;
2687 : 2743 : }
2688 : :
2689 : :
2690 : : /*
2691 : : * Determine whether or not a port forward listens to loopback, the
2692 : : * specified address or wildcard. On the client, a specified bind
2693 : : * address will always override gateway_ports. On the server, a
2694 : : * gateway_ports of 1 (``yes'') will override the client's specification
2695 : : * and force a wildcard bind, whereas a value of 2 (``clientspecified'')
2696 : : * will bind to whatever address the client asked for.
2697 : : *
2698 : : * Special-case listen_addrs are:
2699 : : *
2700 : : * "0.0.0.0" -> wildcard v4/v6 if SSH_OLD_FORWARD_ADDR
2701 : : * "" (empty string), "*" -> wildcard v4/v6
2702 : : * "localhost" -> loopback v4/v6
2703 : : */
2704 : : static const char *
2705 : 100 : channel_fwd_bind_addr(const char *listen_addr, int *wildcardp,
2706 : : int is_client, int gateway_ports)
2707 : : {
2708 : 100 : const char *addr = NULL;
2709 : 100 : int wildcard = 0;
2710 : :
2711 [ + + ]: 100 : if (listen_addr == NULL) {
2712 : : /* No address specified: default to gateway_ports setting */
2713 [ - + ]: 67 : if (gateway_ports)
2714 : 0 : wildcard = 1;
2715 [ - + ]: 33 : } else if (gateway_ports || is_client) {
2716 [ # # ][ # # ]: 0 : if (((datafellows & SSH_OLD_FORWARD_ADDR) &&
2717 [ # # ][ # # ]: 0 : strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) ||
2718 [ # # ][ # # ]: 0 : *listen_addr == '\0' || strcmp(listen_addr, "*") == 0 ||
[ # # ]
2719 : 0 : (!is_client && gateway_ports == 1)) {
2720 : 0 : wildcard = 1;
2721 : : /*
2722 : : * Notify client if they requested a specific listen
2723 : : * address and it was overridden.
2724 : : */
2725 [ # # ][ # # ]: 0 : if (*listen_addr != '\0' &&
2726 [ # # ]: 0 : strcmp(listen_addr, "0.0.0.0") != 0 &&
2727 [ # # ]: 0 : strcmp(listen_addr, "*") != 0) {
2728 : 0 : packet_send_debug("Forwarding listen address "
2729 : : "\"%s\" overridden by server "
2730 : : "GatewayPorts", listen_addr);
2731 : : }
2732 : : }
2733 [ # # ]: 0 : else if (strcmp(listen_addr, "localhost") != 0)
2734 : 0 : addr = listen_addr;
2735 : : }
2736 [ + + ]: 100 : if (wildcardp != NULL)
2737 : 99 : *wildcardp = wildcard;
2738 : 100 : return addr;
2739 : : }
2740 : :
2741 : : static int
2742 : 99 : channel_setup_fwd_listener(int type, const char *listen_addr,
2743 : : u_short listen_port, int *allocated_listen_port,
2744 : : const char *host_to_connect, u_short port_to_connect, int gateway_ports)
2745 : : {
2746 : : Channel *c;
2747 : 99 : int sock, r, success = 0, wildcard = 0, is_client;
2748 : : struct addrinfo hints, *ai, *aitop;
2749 : : const char *host, *addr;
2750 : : char ntop[NI_MAXHOST], strport[NI_MAXSERV];
2751 : : in_port_t *lport_p;
2752 : :
2753 : 99 : host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
2754 [ + + ]: 99 : listen_addr : host_to_connect;
2755 : 99 : is_client = (type == SSH_CHANNEL_PORT_LISTENER);
2756 : :
2757 [ - + ]: 99 : if (host == NULL) {
2758 : 0 : error("No forward host name.");
2759 : 0 : return 0;
2760 : : }
2761 [ - + ]: 99 : if (strlen(host) >= NI_MAXHOST) {
2762 : 0 : error("Forward host name too long.");
2763 : 0 : return 0;
2764 : : }
2765 : :
2766 : : /* Determine the bind address, cf. channel_fwd_bind_addr() comment */
2767 : 99 : addr = channel_fwd_bind_addr(listen_addr, &wildcard,
2768 : : is_client, gateway_ports);
2769 [ - + ]: 99 : debug3("channel_setup_fwd_listener: type %d wildcard %d addr %s",
2770 : : type, wildcard, (addr == NULL) ? "NULL" : addr);
2771 : :
2772 : : /*
2773 : : * getaddrinfo returns a loopback address if the hostname is
2774 : : * set to NULL and hints.ai_flags is not AI_PASSIVE
2775 : : */
2776 : : memset(&hints, 0, sizeof(hints));
2777 : 99 : hints.ai_family = IPv4or6;
2778 : 99 : hints.ai_flags = wildcard ? AI_PASSIVE : 0;
2779 : 99 : hints.ai_socktype = SOCK_STREAM;
2780 : 99 : snprintf(strport, sizeof strport, "%d", listen_port);
2781 [ - + ]: 99 : if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) {
2782 [ # # ]: 0 : if (addr == NULL) {
2783 : : /* This really shouldn't happen */
2784 : 0 : packet_disconnect("getaddrinfo: fatal error: %s",
2785 : : ssh_gai_strerror(r));
2786 : : } else {
2787 : 0 : error("channel_setup_fwd_listener: "
2788 : : "getaddrinfo(%.64s): %s", addr,
2789 : : ssh_gai_strerror(r));
2790 : : }
2791 : 0 : return 0;
2792 : : }
2793 [ + + ]: 99 : if (allocated_listen_port != NULL)
2794 : 33 : *allocated_listen_port = 0;
2795 [ + + ]: 240 : for (ai = aitop; ai; ai = ai->ai_next) {
2796 [ + + - ]: 141 : switch (ai->ai_family) {
2797 : : case AF_INET:
2798 : 99 : lport_p = &((struct sockaddr_in *)ai->ai_addr)->
2799 : : sin_port;
2800 : 99 : break;
2801 : : case AF_INET6:
2802 : 42 : lport_p = &((struct sockaddr_in6 *)ai->ai_addr)->
2803 : : sin6_port;
2804 : 42 : break;
2805 : : default:
2806 : 0 : continue;
2807 : : }
2808 : : /*
2809 : : * If allocating a port for -R forwards, then use the
2810 : : * same port for all address families.
2811 : : */
2812 [ - + ][ # # ]: 141 : if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 &&
2813 [ # # ]: 0 : allocated_listen_port != NULL && *allocated_listen_port > 0)
2814 [ # # ]: 0 : *lport_p = htons(*allocated_listen_port);
2815 : :
2816 [ - + ]: 141 : if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
2817 : : strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
2818 : 0 : error("channel_setup_fwd_listener: getnameinfo failed");
2819 : 0 : continue;
2820 : : }
2821 : : /* Create a port to listen for the host. */
2822 : 141 : sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
2823 [ - + ]: 141 : if (sock < 0) {
2824 : : /* this is no error since kernel may not support ipv6 */
2825 : 0 : verbose("socket: %.100s", strerror(errno));
2826 : 0 : continue;
2827 : : }
2828 : :
2829 : 141 : channel_set_reuseaddr(sock);
2830 [ + + ]: 141 : if (ai->ai_family == AF_INET6)
2831 : 42 : sock_set_v6only(sock);
2832 : :
2833 : 141 : debug("Local forwarding listening on %s port %s.",
2834 : : ntop, strport);
2835 : :
2836 : : /* Bind the socket to the address. */
2837 [ + + ]: 141 : if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
2838 : : /* address can be in use ipv6 address is already bound */
2839 [ + + ]: 22 : if (!ai->ai_next)
2840 : 15 : error("bind: %.100s", strerror(errno));
2841 : : else
2842 : 7 : verbose("bind: %.100s", strerror(errno));
2843 : :
2844 : 22 : close(sock);
2845 : 22 : continue;
2846 : : }
2847 : : /* Start listening for connections on the socket. */
2848 [ - + ]: 119 : if (listen(sock, SSH_LISTEN_BACKLOG) < 0) {
2849 : 0 : error("listen: %.100s", strerror(errno));
2850 : 0 : close(sock);
2851 : 0 : continue;
2852 : : }
2853 : :
2854 : : /*
2855 : : * listen_port == 0 requests a dynamically allocated port -
2856 : : * record what we got.
2857 : : */
2858 [ - + ][ # # ]: 119 : if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 &&
2859 [ # # ]: 0 : allocated_listen_port != NULL &&
2860 : 0 : *allocated_listen_port == 0) {
2861 : 0 : *allocated_listen_port = get_sock_port(sock, 1);
2862 : 0 : debug("Allocated listen port %d",
2863 : : *allocated_listen_port);
2864 : : }
2865 : :
2866 : : /* Allocate a channel number for the socket. */
2867 : 119 : c = channel_new("port listener", type, sock, sock, -1,
2868 : : CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
2869 : : 0, "port listener", 1);
2870 : 119 : c->path = xstrdup(host);
2871 : 119 : c->host_port = port_to_connect;
2872 [ - + ]: 119 : c->listening_addr = addr == NULL ? NULL : xstrdup(addr);
2873 [ - + ][ # # ]: 119 : if (listen_port == 0 && allocated_listen_port != NULL &&
2874 : 0 : !(datafellows & SSH_BUG_DYNAMIC_RPORT))
2875 : 0 : c->listening_port = *allocated_listen_port;
2876 : : else
2877 : 119 : c->listening_port = listen_port;
2878 : : success = 1;
2879 : : }
2880 [ + + ]: 99 : if (success == 0)
2881 : 15 : error("channel_setup_fwd_listener: cannot listen to port: %d",
2882 : : listen_port);
2883 : 99 : freeaddrinfo(aitop);
2884 : 99 : return success;
2885 : : }
2886 : :
2887 : : int
2888 : 0 : channel_cancel_rport_listener(const char *host, u_short port)
2889 : : {
2890 : : u_int i;
2891 : 0 : int found = 0;
2892 : :
2893 [ # # ]: 0 : for (i = 0; i < channels_alloc; i++) {
2894 : 0 : Channel *c = channels[i];
2895 [ # # ][ # # ]: 0 : if (c == NULL || c->type != SSH_CHANNEL_RPORT_LISTENER)
2896 : 0 : continue;
2897 [ # # ][ # # ]: 0 : if (strcmp(c->path, host) == 0 && c->listening_port == port) {
2898 : 0 : debug2("%s: close channel %d", __func__, i);
2899 : 0 : channel_free(c);
2900 : 0 : found = 1;
2901 : : }
2902 : : }
2903 : :
2904 : 0 : return (found);
2905 : : }
2906 : :
2907 : : int
2908 : 1 : channel_cancel_lport_listener(const char *lhost, u_short lport,
2909 : : int cport, int gateway_ports)
2910 : : {
2911 : : u_int i;
2912 : 1 : int found = 0;
2913 : 1 : const char *addr = channel_fwd_bind_addr(lhost, NULL, 1, gateway_ports);
2914 : :
2915 [ + + ]: 11 : for (i = 0; i < channels_alloc; i++) {
2916 : 10 : Channel *c = channels[i];
2917 [ + + ][ + + ]: 10 : if (c == NULL || c->type != SSH_CHANNEL_PORT_LISTENER)
2918 : 8 : continue;
2919 [ - + ]: 2 : if (c->listening_port != lport)
2920 : 0 : continue;
2921 [ - + ]: 2 : if (cport == CHANNEL_CANCEL_PORT_STATIC) {
2922 : : /* skip dynamic forwardings */
2923 [ # # ]: 0 : if (c->host_port == 0)
2924 : 0 : continue;
2925 : : } else {
2926 [ - + ]: 2 : if (c->host_port != cport)
2927 : 0 : continue;
2928 : : }
2929 [ + - ][ + - ]: 2 : if ((c->listening_addr == NULL && addr != NULL) ||
[ - + ]
2930 [ # # ]: 0 : (c->listening_addr != NULL && addr == NULL))
2931 : 0 : continue;
2932 [ - + ][ # # ]: 2 : if (addr == NULL || strcmp(c->listening_addr, addr) == 0) {
2933 : 2 : debug2("%s: close channel %d", __func__, i);
2934 : 2 : channel_free(c);
2935 : 2 : found = 1;
2936 : : }
2937 : : }
2938 : :
2939 : 1 : return (found);
2940 : : }
2941 : :
2942 : : /* protocol local port fwd, used by ssh (and sshd in v1) */
2943 : : int
2944 : 42 : channel_setup_local_fwd_listener(const char *listen_host, u_short listen_port,
2945 : : const char *host_to_connect, u_short port_to_connect, int gateway_ports)
2946 : : {
2947 : 66 : return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER,
2948 : : listen_host, listen_port, NULL, host_to_connect, port_to_connect,
2949 : : gateway_ports);
2950 : : }
2951 : :
2952 : : /* protocol v2 remote port fwd, used by sshd */
2953 : : int
2954 : 33 : channel_setup_remote_fwd_listener(const char *listen_address,
2955 : : u_short listen_port, int *allocated_listen_port, int gateway_ports)
2956 : : {
2957 : 33 : return channel_setup_fwd_listener(SSH_CHANNEL_RPORT_LISTENER,
2958 : : listen_address, listen_port, allocated_listen_port,
2959 : : NULL, 0, gateway_ports);
2960 : : }
2961 : :
2962 : : /*
2963 : : * Translate the requested rfwd listen host to something usable for
2964 : : * this server.
2965 : : */
2966 : : static const char *
2967 : 21 : channel_rfwd_bind_host(const char *listen_host)
2968 : : {
2969 [ + - ]: 21 : if (listen_host == NULL) {
2970 [ + - ]: 21 : if (datafellows & SSH_BUG_RFWD_ADDR)
2971 : : return "127.0.0.1";
2972 : : else
2973 : 21 : return "localhost";
2974 [ # # ][ # # ]: 0 : } else if (*listen_host == '\0' || strcmp(listen_host, "*") == 0) {
[ # # ]
2975 [ # # ]: 0 : if (datafellows & SSH_BUG_RFWD_ADDR)
2976 : : return "0.0.0.0";
2977 : : else
2978 : 0 : return "";
2979 : : } else
2980 : : return listen_host;
2981 : : }
2982 : :
2983 : : /*
2984 : : * Initiate forwarding of connections to port "port" on remote host through
2985 : : * the secure channel to host:port from local side.
2986 : : * Returns handle (index) for updating the dynamic listen port with
2987 : : * channel_update_permitted_opens().
2988 : : */
2989 : : int
2990 : 35 : channel_request_remote_forwarding(const char *listen_host, u_short listen_port,
2991 : : const char *host_to_connect, u_short port_to_connect)
2992 : : {
2993 : 35 : int type, success = 0, idx = -1;
2994 : :
2995 : : /* Send the forward request to the remote side. */
2996 [ + + ]: 35 : if (compat20) {
2997 : 20 : packet_start(SSH2_MSG_GLOBAL_REQUEST);
2998 : 20 : packet_put_cstring("tcpip-forward");
2999 : 20 : packet_put_char(1); /* boolean: want reply */
3000 : 20 : packet_put_cstring(channel_rfwd_bind_host(listen_host));
3001 : 20 : packet_put_int(listen_port);
3002 : 20 : packet_send();
3003 : 20 : packet_write_wait();
3004 : : /* Assume that server accepts the request */
3005 : 20 : success = 1;
3006 : : } else {
3007 : 15 : packet_start(SSH_CMSG_PORT_FORWARD_REQUEST);
3008 : 15 : packet_put_int(listen_port);
3009 : 15 : packet_put_cstring(host_to_connect);
3010 : 15 : packet_put_int(port_to_connect);
3011 : 15 : packet_send();
3012 : 15 : packet_write_wait();
3013 : :
3014 : : /* Wait for response from the remote side. */
3015 : 15 : type = packet_read();
3016 [ + - + ]: 15 : switch (type) {
3017 : : case SSH_SMSG_SUCCESS:
3018 : 14 : success = 1;
3019 : 14 : break;
3020 : : case SSH_SMSG_FAILURE:
3021 : : break;
3022 : : default:
3023 : : /* Unknown packet */
3024 : 0 : packet_disconnect("Protocol error for port forward request:"
3025 : : "received packet type %d.", type);
3026 : : }
3027 : : }
3028 [ + + ]: 35 : if (success) {
3029 : : /* Record that connection to this host/port is permitted. */
3030 : 34 : permitted_opens = xrealloc(permitted_opens,
3031 : 34 : num_permitted_opens + 1, sizeof(*permitted_opens));
3032 : 34 : idx = num_permitted_opens++;
3033 : 34 : permitted_opens[idx].host_to_connect = xstrdup(host_to_connect);
3034 : 34 : permitted_opens[idx].port_to_connect = port_to_connect;
3035 : 34 : permitted_opens[idx].listen_port = listen_port;
3036 : : }
3037 : 35 : return (idx);
3038 : : }
3039 : :
3040 : : /*
3041 : : * Request cancellation of remote forwarding of connection host:port from
3042 : : * local side.
3043 : : */
3044 : : int
3045 : 1 : channel_request_rforward_cancel(const char *host, u_short port)
3046 : : {
3047 : : int i;
3048 : :
3049 [ + - ]: 1 : if (!compat20)
3050 : : return -1;
3051 : :
3052 [ + - ]: 1 : for (i = 0; i < num_permitted_opens; i++) {
3053 [ + - ][ - + ]: 1 : if (permitted_opens[i].host_to_connect != NULL &&
3054 : 1 : permitted_opens[i].listen_port == port)
3055 : : break;
3056 : : }
3057 [ - + ]: 1 : if (i >= num_permitted_opens) {
3058 : 0 : debug("%s: requested forward not found", __func__);
3059 : 0 : return -1;
3060 : : }
3061 : 1 : packet_start(SSH2_MSG_GLOBAL_REQUEST);
3062 : 1 : packet_put_cstring("cancel-tcpip-forward");
3063 : 1 : packet_put_char(0);
3064 : 1 : packet_put_cstring(channel_rfwd_bind_host(host));
3065 : 1 : packet_put_int(port);
3066 : 1 : packet_send();
3067 : :
3068 : 1 : permitted_opens[i].listen_port = 0;
3069 : 1 : permitted_opens[i].port_to_connect = 0;
3070 : 1 : free(permitted_opens[i].host_to_connect);
3071 : 1 : permitted_opens[i].host_to_connect = NULL;
3072 : :
3073 : 1 : return 0;
3074 : : }
3075 : :
3076 : : /*
3077 : : * This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates
3078 : : * listening for the port, and sends back a success reply (or disconnect
3079 : : * message if there was an error).
3080 : : */
3081 : : int
3082 : 24 : channel_input_port_forward_request(int is_root, int gateway_ports)
3083 : : {
3084 : : u_short port, host_port;
3085 : 24 : int success = 0;
3086 : : char *hostname;
3087 : :
3088 : : /* Get arguments from the packet. */
3089 : 24 : port = packet_get_int();
3090 : 24 : hostname = packet_get_string(NULL);
3091 : 24 : host_port = packet_get_int();
3092 : :
3093 : : #ifndef HAVE_CYGWIN
3094 : : /*
3095 : : * Check that an unprivileged user is not trying to forward a
3096 : : * privileged port.
3097 : : */
3098 [ - + ]: 24 : if (port < IPPORT_RESERVED && !is_root)
3099 : 0 : packet_disconnect(
3100 : : "Requested forwarding of port %d but user is not root.",
3101 : : port);
3102 [ - + ]: 24 : if (host_port == 0)
3103 : 0 : packet_disconnect("Dynamic forwarding denied.");
3104 : : #endif
3105 : :
3106 : : /* Initiate forwarding */
3107 : 48 : success = channel_setup_local_fwd_listener(NULL, port, hostname,
3108 : : host_port, gateway_ports);
3109 : :
3110 : : /* Free the argument string. */
3111 : 24 : free(hostname);
3112 : :
3113 [ + + ]: 24 : return (success ? 0 : -1);
3114 : : }
3115 : :
3116 : : /*
3117 : : * Permits opening to any host/port if permitted_opens[] is empty. This is
3118 : : * usually called by the server, because the user could connect to any port
3119 : : * anyway, and the server has no way to know but to trust the client anyway.
3120 : : */
3121 : : void
3122 : 786 : channel_permit_all_opens(void)
3123 : : {
3124 [ + + ]: 786 : if (num_permitted_opens == 0)
3125 : 750 : all_opens_permitted = 1;
3126 : 786 : }
3127 : :
3128 : : void
3129 : 94 : channel_add_permitted_opens(char *host, int port)
3130 : : {
3131 : 94 : debug("allow port forwarding to host %s port %d", host, port);
3132 : :
3133 : 94 : permitted_opens = xrealloc(permitted_opens,
3134 : 94 : num_permitted_opens + 1, sizeof(*permitted_opens));
3135 : 94 : permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host);
3136 : 94 : permitted_opens[num_permitted_opens].port_to_connect = port;
3137 : 94 : num_permitted_opens++;
3138 : :
3139 : 94 : all_opens_permitted = 0;
3140 : 94 : }
3141 : :
3142 : : /*
3143 : : * Update the listen port for a dynamic remote forward, after
3144 : : * the actual 'newport' has been allocated. If 'newport' < 0 is
3145 : : * passed then they entry will be invalidated.
3146 : : */
3147 : : void
3148 : 0 : channel_update_permitted_opens(int idx, int newport)
3149 : : {
3150 [ # # ][ # # ]: 0 : if (idx < 0 || idx >= num_permitted_opens) {
3151 : 0 : debug("channel_update_permitted_opens: index out of range:"
3152 : : " %d num_permitted_opens %d", idx, num_permitted_opens);
3153 : 0 : return;
3154 : : }
3155 [ # # ]: 0 : debug("%s allowed port %d for forwarding to host %s port %d",
3156 : : newport > 0 ? "Updating" : "Removing",
3157 : : newport,
3158 : : permitted_opens[idx].host_to_connect,
3159 : 0 : permitted_opens[idx].port_to_connect);
3160 [ # # ]: 0 : if (newport >= 0) {
3161 [ # # ]: 0 : permitted_opens[idx].listen_port =
3162 : 0 : (datafellows & SSH_BUG_DYNAMIC_RPORT) ? 0 : newport;
3163 : : } else {
3164 : 0 : permitted_opens[idx].listen_port = 0;
3165 : 0 : permitted_opens[idx].port_to_connect = 0;
3166 : 0 : free(permitted_opens[idx].host_to_connect);
3167 : 0 : permitted_opens[idx].host_to_connect = NULL;
3168 : : }
3169 : : }
3170 : :
3171 : : int
3172 : 58 : channel_add_adm_permitted_opens(char *host, int port)
3173 : : {
3174 : 58 : debug("config allows port forwarding to host %s port %d", host, port);
3175 : :
3176 : 58 : permitted_adm_opens = xrealloc(permitted_adm_opens,
3177 : 58 : num_adm_permitted_opens + 1, sizeof(*permitted_adm_opens));
3178 : 58 : permitted_adm_opens[num_adm_permitted_opens].host_to_connect
3179 : 58 : = xstrdup(host);
3180 : 58 : permitted_adm_opens[num_adm_permitted_opens].port_to_connect = port;
3181 : 58 : return ++num_adm_permitted_opens;
3182 : : }
3183 : :
3184 : : void
3185 : 24 : channel_disable_adm_local_opens(void)
3186 : : {
3187 : 24 : channel_clear_adm_permitted_opens();
3188 : 24 : permitted_adm_opens = xmalloc(sizeof(*permitted_adm_opens));
3189 : 24 : permitted_adm_opens[num_adm_permitted_opens].host_to_connect = NULL;
3190 : 24 : num_adm_permitted_opens = 1;
3191 : 24 : }
3192 : :
3193 : : void
3194 : 5341 : channel_clear_permitted_opens(void)
3195 : : {
3196 : : int i;
3197 : :
3198 [ + + ]: 5379 : for (i = 0; i < num_permitted_opens; i++)
3199 : 38 : free(permitted_opens[i].host_to_connect);
3200 : 5341 : free(permitted_opens);
3201 : 5341 : permitted_opens = NULL;
3202 : 5341 : num_permitted_opens = 0;
3203 : 5341 : }
3204 : :
3205 : : void
3206 : 72 : channel_clear_adm_permitted_opens(void)
3207 : : {
3208 : : int i;
3209 : :
3210 [ + + ]: 94 : for (i = 0; i < num_adm_permitted_opens; i++)
3211 : 22 : free(permitted_adm_opens[i].host_to_connect);
3212 : 72 : free(permitted_adm_opens);
3213 : 72 : permitted_adm_opens = NULL;
3214 : 72 : num_adm_permitted_opens = 0;
3215 : 72 : }
3216 : :
3217 : : void
3218 : 142 : channel_print_adm_permitted_opens(void)
3219 : : {
3220 : : int i;
3221 : :
3222 : : printf("permitopen");
3223 [ - + ]: 142 : if (num_adm_permitted_opens == 0) {
3224 : : printf(" any\n");
3225 : 142 : return;
3226 : : }
3227 [ # # ]: 0 : for (i = 0; i < num_adm_permitted_opens; i++)
3228 [ # # ]: 0 : if (permitted_adm_opens[i].host_to_connect == NULL)
3229 : : printf(" none");
3230 : : else
3231 : 0 : printf(" %s:%d", permitted_adm_opens[i].host_to_connect,
3232 : 0 : permitted_adm_opens[i].port_to_connect);
3233 : : printf("\n");
3234 : : }
3235 : :
3236 : : /* returns port number, FWD_PERMIT_ANY_PORT or -1 on error */
3237 : : int
3238 : 262 : permitopen_port(const char *p)
3239 : : {
3240 : : int port;
3241 : :
3242 [ - + ][ + - ]: 262 : if (strcmp(p, "*") == 0)
3243 : : return FWD_PERMIT_ANY_PORT;
3244 [ + - ]: 262 : if ((port = a2port(p)) > 0)
3245 : 262 : return port;
3246 : : return -1;
3247 : : }
3248 : :
3249 : : static int
3250 : : port_match(u_short allowedport, u_short requestedport)
3251 : : {
3252 [ + + ][ # # ]: 129 : if (allowedport == FWD_PERMIT_ANY_PORT ||
[ + + ]
3253 : 129 : allowedport == requestedport)
3254 : : return 1;
3255 : : return 0;
3256 : : }
3257 : :
3258 : : /* Try to start non-blocking connect to next host in cctx list */
3259 : : static int
3260 : 66 : connect_next(struct channel_connect *cctx)
3261 : : {
3262 : : int sock, saved_errno;
3263 : : char ntop[NI_MAXHOST], strport[NI_MAXSERV];
3264 : :
3265 [ + - ]: 33 : for (; cctx->ai; cctx->ai = cctx->ai->ai_next) {
3266 [ - + ]: 33 : if (cctx->ai->ai_family != AF_INET &&
3267 : : cctx->ai->ai_family != AF_INET6)
3268 : 0 : continue;
3269 [ - + ]: 33 : if (getnameinfo(cctx->ai->ai_addr, cctx->ai->ai_addrlen,
3270 : : ntop, sizeof(ntop), strport, sizeof(strport),
3271 : : NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
3272 : 0 : error("connect_next: getnameinfo failed");
3273 : 0 : continue;
3274 : : }
3275 [ - + ]: 33 : if ((sock = socket(cctx->ai->ai_family, cctx->ai->ai_socktype,
3276 : 33 : cctx->ai->ai_protocol)) == -1) {
3277 [ # # ]: 0 : if (cctx->ai->ai_next == NULL)
3278 : 0 : error("socket: %.100s", strerror(errno));
3279 : : else
3280 : 0 : verbose("socket: %.100s", strerror(errno));
3281 : 0 : continue;
3282 : : }
3283 [ - + ]: 33 : if (set_nonblock(sock) == -1)
3284 : 0 : fatal("%s: set_nonblock(%d)", __func__, sock);
3285 [ + - ]: 33 : if (connect(sock, cctx->ai->ai_addr,
3286 [ - + ]: 33 : cctx->ai->ai_addrlen) == -1 && errno != EINPROGRESS) {
3287 : 0 : debug("connect_next: host %.100s ([%.100s]:%s): "
3288 : : "%.100s", cctx->host, ntop, strport,
3289 : : strerror(errno));
3290 : 0 : saved_errno = errno;
3291 : 0 : close(sock);
3292 : 0 : errno = saved_errno;
3293 : 0 : continue; /* fail -- try next */
3294 : : }
3295 : 33 : debug("connect_next: host %.100s ([%.100s]:%s) "
3296 : : "in progress, fd=%d", cctx->host, ntop, strport, sock);
3297 : 33 : cctx->ai = cctx->ai->ai_next;
3298 : 33 : set_nodelay(sock);
3299 : : return sock;
3300 : : }
3301 : : return -1;
3302 : : }
3303 : :
3304 : : static void
3305 : 33 : channel_connect_ctx_free(struct channel_connect *cctx)
3306 : : {
3307 : 33 : free(cctx->host);
3308 [ + - ]: 33 : if (cctx->aitop)
3309 : 33 : freeaddrinfo(cctx->aitop);
3310 : : memset(cctx, 0, sizeof(*cctx));
3311 : 33 : }
3312 : :
3313 : : /* Return CONNECTING channel to remote host, port */
3314 : : static Channel *
3315 : 33 : connect_to(const char *host, u_short port, char *ctype, char *rname)
3316 : : {
3317 : : struct addrinfo hints;
3318 : : int gaierr;
3319 : 33 : int sock = -1;
3320 : : char strport[NI_MAXSERV];
3321 : : struct channel_connect cctx;
3322 : : Channel *c;
3323 : :
3324 : : memset(&cctx, 0, sizeof(cctx));
3325 : : memset(&hints, 0, sizeof(hints));
3326 : 33 : hints.ai_family = IPv4or6;
3327 : 33 : hints.ai_socktype = SOCK_STREAM;
3328 : 33 : snprintf(strport, sizeof strport, "%d", port);
3329 [ - + ]: 33 : if ((gaierr = getaddrinfo(host, strport, &hints, &cctx.aitop)) != 0) {
3330 : 0 : error("connect_to %.100s: unknown host (%s)", host,
3331 : : ssh_gai_strerror(gaierr));
3332 : 0 : return NULL;
3333 : : }
3334 : :
3335 : 33 : cctx.host = xstrdup(host);
3336 : 33 : cctx.port = port;
3337 : 33 : cctx.ai = cctx.aitop;
3338 : :
3339 [ - + ]: 33 : if ((sock = connect_next(&cctx)) == -1) {
3340 : 0 : error("connect to %.100s port %d failed: %s",
3341 : 0 : host, port, strerror(errno));
3342 : 0 : channel_connect_ctx_free(&cctx);
3343 : 0 : return NULL;
3344 : : }
3345 : 33 : c = channel_new(ctype, SSH_CHANNEL_CONNECTING, sock, sock, -1,
3346 : : CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1);
3347 : 33 : c->connect_ctx = cctx;
3348 : 33 : return c;
3349 : : }
3350 : :
3351 : : Channel *
3352 : 10 : channel_connect_by_listen_address(u_short listen_port, char *ctype, char *rname)
3353 : : {
3354 : : int i;
3355 : :
3356 [ + - ]: 46 : for (i = 0; i < num_permitted_opens; i++) {
3357 [ + - ][ + + ]: 92 : if (permitted_opens[i].host_to_connect != NULL &&
3358 : 46 : port_match(permitted_opens[i].listen_port, listen_port)) {
3359 : 10 : return connect_to(
3360 : : permitted_opens[i].host_to_connect,
3361 : 10 : permitted_opens[i].port_to_connect, ctype, rname);
3362 : : }
3363 : : }
3364 : 0 : error("WARNING: Server requests forwarding for unknown listen_port %d",
3365 : : listen_port);
3366 : 0 : return NULL;
3367 : : }
3368 : :
3369 : : /* Check if connecting to that port is permitted and connect. */
3370 : : Channel *
3371 : 23 : channel_connect_to(const char *host, u_short port, char *ctype, char *rname)
3372 : : {
3373 : 23 : int i, permit, permit_adm = 1;
3374 : :
3375 : 23 : permit = all_opens_permitted;
3376 [ + + ]: 23 : if (!permit) {
3377 [ + + ]: 94 : for (i = 0; i < num_permitted_opens; i++)
3378 [ + - ][ + + ]: 166 : if (permitted_opens[i].host_to_connect != NULL &&
3379 [ + - ]: 11 : port_match(permitted_opens[i].port_to_connect, port) &&
3380 : 11 : strcmp(permitted_opens[i].host_to_connect, host) == 0)
3381 : 11 : permit = 1;
3382 : : }
3383 : :
3384 [ - + ]: 23 : if (num_adm_permitted_opens > 0) {
3385 : : permit_adm = 0;
3386 [ # # ]: 0 : for (i = 0; i < num_adm_permitted_opens; i++)
3387 [ # # ][ # # ]: 0 : if (permitted_adm_opens[i].host_to_connect != NULL &&
3388 [ # # ]: 0 : port_match(permitted_adm_opens[i].port_to_connect, port) &&
3389 : 0 : strcmp(permitted_adm_opens[i].host_to_connect, host)
3390 : : == 0)
3391 : 0 : permit_adm = 1;
3392 : : }
3393 : :
3394 [ - + ]: 23 : if (!permit || !permit_adm) {
3395 : 0 : logit("Received request to connect to host %.100s port %d, "
3396 : : "but the request was denied.", host, port);
3397 : 0 : return NULL;
3398 : : }
3399 : 23 : return connect_to(host, port, ctype, rname);
3400 : : }
3401 : :
3402 : : void
3403 : 0 : channel_send_window_changes(void)
3404 : : {
3405 : : u_int i;
3406 : : struct winsize ws;
3407 : :
3408 [ # # ]: 0 : for (i = 0; i < channels_alloc; i++) {
3409 [ # # ][ # # ]: 0 : if (channels[i] == NULL || !channels[i]->client_tty ||
[ # # ]
3410 : 0 : channels[i]->type != SSH_CHANNEL_OPEN)
3411 : 0 : continue;
3412 [ # # ]: 0 : if (ioctl(channels[i]->rfd, TIOCGWINSZ, &ws) < 0)
3413 : 0 : continue;
3414 : 0 : channel_request_start(i, "window-change", 0);
3415 : 0 : packet_put_int((u_int)ws.ws_col);
3416 : 0 : packet_put_int((u_int)ws.ws_row);
3417 : 0 : packet_put_int((u_int)ws.ws_xpixel);
3418 : 0 : packet_put_int((u_int)ws.ws_ypixel);
3419 : 0 : packet_send();
3420 : : }
3421 : 0 : }
3422 : :
3423 : : /* -- X11 forwarding */
3424 : :
3425 : : /*
3426 : : * Creates an internet domain socket for listening for X11 connections.
3427 : : * Returns 0 and a suitable display number for the DISPLAY variable
3428 : : * stored in display_numberp , or -1 if an error occurs.
3429 : : */
3430 : : int
3431 : 0 : x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
3432 : : int single_connection, u_int *display_numberp, int **chanids)
3433 : : {
3434 : 0 : Channel *nc = NULL;
3435 : : int display_number, sock;
3436 : : u_short port;
3437 : : struct addrinfo hints, *ai, *aitop;
3438 : : char strport[NI_MAXSERV];
3439 : 0 : int gaierr, n, num_socks = 0, socks[NUM_SOCKS];
3440 : :
3441 [ # # ]: 0 : if (chanids == NULL)
3442 : : return -1;
3443 : :
3444 [ # # ]: 0 : for (display_number = x11_display_offset;
3445 : : display_number < MAX_DISPLAYS;
3446 : 0 : display_number++) {
3447 : 0 : port = 6000 + display_number;
3448 : : memset(&hints, 0, sizeof(hints));
3449 : 0 : hints.ai_family = IPv4or6;
3450 : 0 : hints.ai_flags = x11_use_localhost ? 0: AI_PASSIVE;
3451 : 0 : hints.ai_socktype = SOCK_STREAM;
3452 : 0 : snprintf(strport, sizeof strport, "%d", port);
3453 [ # # ]: 0 : if ((gaierr = getaddrinfo(NULL, strport, &hints, &aitop)) != 0) {
3454 : 0 : error("getaddrinfo: %.100s", ssh_gai_strerror(gaierr));
3455 : 0 : return -1;
3456 : : }
3457 [ # # ]: 0 : for (ai = aitop; ai; ai = ai->ai_next) {
3458 [ # # ]: 0 : if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
3459 : 0 : continue;
3460 : 0 : sock = socket(ai->ai_family, ai->ai_socktype,
3461 : : ai->ai_protocol);
3462 [ # # ]: 0 : if (sock < 0) {
3463 [ # # ]: 0 : if ((errno != EINVAL) && (errno != EAFNOSUPPORT)
3464 : : #ifdef EPFNOSUPPORT
3465 [ # # ]: 0 : && (errno != EPFNOSUPPORT)
3466 : : #endif
3467 : : ) {
3468 : 0 : error("socket: %.100s", strerror(errno));
3469 : 0 : freeaddrinfo(aitop);
3470 : 0 : return -1;
3471 : : } else {
3472 : 0 : debug("x11_create_display_inet: Socket family %d not supported",
3473 : : ai->ai_family);
3474 : 0 : continue;
3475 : : }
3476 : : }
3477 [ # # ]: 0 : if (ai->ai_family == AF_INET6)
3478 : 0 : sock_set_v6only(sock);
3479 [ # # ]: 0 : if (x11_use_localhost)
3480 : 0 : channel_set_reuseaddr(sock);
3481 [ # # ]: 0 : if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
3482 : 0 : debug2("bind port %d: %.100s", port, strerror(errno));
3483 : 0 : close(sock);
3484 : :
3485 [ # # ]: 0 : for (n = 0; n < num_socks; n++) {
3486 : 0 : close(socks[n]);
3487 : : }
3488 : : num_socks = 0;
3489 : : break;
3490 : : }
3491 : 0 : socks[num_socks++] = sock;
3492 [ # # ]: 0 : if (num_socks == NUM_SOCKS)
3493 : : break;
3494 : : }
3495 : 0 : freeaddrinfo(aitop);
3496 [ # # ]: 0 : if (num_socks > 0)
3497 : : break;
3498 : : }
3499 [ # # ]: 0 : if (display_number >= MAX_DISPLAYS) {
3500 : 0 : error("Failed to allocate internet-domain X11 display socket.");
3501 : 0 : return -1;
3502 : : }
3503 : : /* Start listening for connections on the socket. */
3504 [ # # ]: 0 : for (n = 0; n < num_socks; n++) {
3505 : 0 : sock = socks[n];
3506 [ # # ]: 0 : if (listen(sock, SSH_LISTEN_BACKLOG) < 0) {
3507 : 0 : error("listen: %.100s", strerror(errno));
3508 : 0 : close(sock);
3509 : 0 : return -1;
3510 : : }
3511 : : }
3512 : :
3513 : : /* Allocate a channel for each socket. */
3514 : 0 : *chanids = xcalloc(num_socks + 1, sizeof(**chanids));
3515 [ # # ]: 0 : for (n = 0; n < num_socks; n++) {
3516 : 0 : sock = socks[n];
3517 : 0 : nc = channel_new("x11 listener",
3518 : : SSH_CHANNEL_X11_LISTENER, sock, sock, -1,
3519 : : CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
3520 : : 0, "X11 inet listener", 1);
3521 : 0 : nc->single_connection = single_connection;
3522 : 0 : (*chanids)[n] = nc->self;
3523 : : }
3524 : 0 : (*chanids)[n] = -1;
3525 : :
3526 : : /* Return the display number for the DISPLAY environment variable. */
3527 : 0 : *display_numberp = display_number;
3528 : 0 : return (0);
3529 : : }
3530 : :
3531 : : static int
3532 : 0 : connect_local_xsocket_path(const char *pathname)
3533 : : {
3534 : : int sock;
3535 : : struct sockaddr_un addr;
3536 : :
3537 : 0 : sock = socket(AF_UNIX, SOCK_STREAM, 0);
3538 [ # # ]: 0 : if (sock < 0)
3539 : 0 : error("socket: %.100s", strerror(errno));
3540 : : memset(&addr, 0, sizeof(addr));
3541 : 0 : addr.sun_family = AF_UNIX;
3542 : 0 : strlcpy(addr.sun_path, pathname, sizeof addr.sun_path);
3543 [ # # ]: 0 : if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0)
3544 : : return sock;
3545 : 0 : close(sock);
3546 : 0 : error("connect %.100s: %.100s", addr.sun_path, strerror(errno));
3547 : 0 : return -1;
3548 : : }
3549 : :
3550 : : static int
3551 : 0 : connect_local_xsocket(u_int dnr)
3552 : : {
3553 : : char buf[1024];
3554 : : snprintf(buf, sizeof buf, _PATH_UNIX_X, dnr);
3555 : 0 : return connect_local_xsocket_path(buf);
3556 : : }
3557 : :
3558 : : int
3559 : 0 : x11_connect_display(void)
3560 : : {
3561 : : u_int display_number;
3562 : : const char *display;
3563 : : char buf[1024], *cp;
3564 : : struct addrinfo hints, *ai, *aitop;
3565 : : char strport[NI_MAXSERV];
3566 : 0 : int gaierr, sock = 0;
3567 : :
3568 : : /* Try to open a socket for the local X server. */
3569 : 0 : display = getenv("DISPLAY");
3570 [ # # ]: 0 : if (!display) {
3571 : 0 : error("DISPLAY not set.");
3572 : 0 : return -1;
3573 : : }
3574 : : /*
3575 : : * Now we decode the value of the DISPLAY variable and make a
3576 : : * connection to the real X server.
3577 : : */
3578 : :
3579 : : /* Check if the display is from launchd. */
3580 : : #ifdef __APPLE__
3581 : : if (strncmp(display, "/tmp/launch", 11) == 0) {
3582 : : sock = connect_local_xsocket_path(display);
3583 : : if (sock < 0)
3584 : : return -1;
3585 : :
3586 : : /* OK, we now have a connection to the display. */
3587 : : return sock;
3588 : : }
3589 : : #endif
3590 : : /*
3591 : : * Check if it is a unix domain socket. Unix domain displays are in
3592 : : * one of the following formats: unix:d[.s], :d[.s], ::d[.s]
3593 : : */
3594 [ # # ][ # # ]: 0 : if (strncmp(display, "unix:", 5) == 0 ||
3595 : 0 : display[0] == ':') {
3596 : : /* Connect to the unix domain socket. */
3597 [ # # ]: 0 : if (sscanf(strrchr(display, ':') + 1, "%u", &display_number) != 1) {
3598 : 0 : error("Could not parse display number from DISPLAY: %.100s",
3599 : : display);
3600 : 0 : return -1;
3601 : : }
3602 : : /* Create a socket. */
3603 : 0 : sock = connect_local_xsocket(display_number);
3604 [ # # ]: 0 : if (sock < 0)
3605 : : return -1;
3606 : :
3607 : : /* OK, we now have a connection to the display. */
3608 : 0 : return sock;
3609 : : }
3610 : : /*
3611 : : * Connect to an inet socket. The DISPLAY value is supposedly
3612 : : * hostname:d[.s], where hostname may also be numeric IP address.
3613 : : */
3614 : 0 : strlcpy(buf, display, sizeof(buf));
3615 : 0 : cp = strchr(buf, ':');
3616 [ # # ]: 0 : if (!cp) {
3617 : 0 : error("Could not find ':' in DISPLAY: %.100s", display);
3618 : 0 : return -1;
3619 : : }
3620 : 0 : *cp = 0;
3621 : : /* buf now contains the host name. But first we parse the display number. */
3622 [ # # ]: 0 : if (sscanf(cp + 1, "%u", &display_number) != 1) {
3623 : 0 : error("Could not parse display number from DISPLAY: %.100s",
3624 : : display);
3625 : 0 : return -1;
3626 : : }
3627 : :
3628 : : /* Look up the host address */
3629 : : memset(&hints, 0, sizeof(hints));
3630 : 0 : hints.ai_family = IPv4or6;
3631 : 0 : hints.ai_socktype = SOCK_STREAM;
3632 : 0 : snprintf(strport, sizeof strport, "%u", 6000 + display_number);
3633 [ # # ]: 0 : if ((gaierr = getaddrinfo(buf, strport, &hints, &aitop)) != 0) {
3634 : 0 : error("%.100s: unknown host. (%s)", buf,
3635 : : ssh_gai_strerror(gaierr));
3636 : 0 : return -1;
3637 : : }
3638 [ # # ]: 0 : for (ai = aitop; ai; ai = ai->ai_next) {
3639 : : /* Create a socket. */
3640 : 0 : sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
3641 [ # # ]: 0 : if (sock < 0) {
3642 : 0 : debug2("socket: %.100s", strerror(errno));
3643 : 0 : continue;
3644 : : }
3645 : : /* Connect it to the display. */
3646 [ # # ]: 0 : if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
3647 : 0 : debug2("connect %.100s port %u: %.100s", buf,
3648 : 0 : 6000 + display_number, strerror(errno));
3649 : 0 : close(sock);
3650 : 0 : continue;
3651 : : }
3652 : : /* Success */
3653 : : break;
3654 : : }
3655 : 0 : freeaddrinfo(aitop);
3656 [ # # ]: 0 : if (!ai) {
3657 : 0 : error("connect %.100s port %u: %.100s", buf, 6000 + display_number,
3658 : 0 : strerror(errno));
3659 : 0 : return -1;
3660 : : }
3661 : 0 : set_nodelay(sock);
3662 : 0 : return sock;
3663 : : }
3664 : :
3665 : : /*
3666 : : * This is called when SSH_SMSG_X11_OPEN is received. The packet contains
3667 : : * the remote channel number. We should do whatever we want, and respond
3668 : : * with either SSH_MSG_OPEN_CONFIRMATION or SSH_MSG_OPEN_FAILURE.
3669 : : */
3670 : :
3671 : : /* ARGSUSED */
3672 : : void
3673 : 0 : x11_input_open(int type, u_int32_t seq, void *ctxt)
3674 : : {
3675 : 0 : Channel *c = NULL;
3676 : 0 : int remote_id, sock = 0;
3677 : : char *remote_host;
3678 : :
3679 : 0 : debug("Received X11 open request.");
3680 : :
3681 : 0 : remote_id = packet_get_int();
3682 : :
3683 [ # # ]: 0 : if (packet_get_protocol_flags() & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) {
3684 : 0 : remote_host = packet_get_string(NULL);
3685 : : } else {
3686 : 0 : remote_host = xstrdup("unknown (remote did not supply name)");
3687 : : }
3688 [ # # ]: 0 : packet_check_eom();
3689 : :
3690 : : /* Obtain a connection to the real X display. */
3691 : 0 : sock = x11_connect_display();
3692 [ # # ]: 0 : if (sock != -1) {
3693 : : /* Allocate a channel for this connection. */
3694 : 0 : c = channel_new("connected x11 socket",
3695 : : SSH_CHANNEL_X11_OPEN, sock, sock, -1, 0, 0, 0,
3696 : : remote_host, 1);
3697 : 0 : c->remote_id = remote_id;
3698 : 0 : c->force_drain = 1;
3699 : : }
3700 : 0 : free(remote_host);
3701 [ # # ]: 0 : if (c == NULL) {
3702 : : /* Send refusal to the remote host. */
3703 : 0 : packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
3704 : 0 : packet_put_int(remote_id);
3705 : : } else {
3706 : : /* Send a confirmation to the remote host. */
3707 : 0 : packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
3708 : 0 : packet_put_int(remote_id);
3709 : 0 : packet_put_int(c->self);
3710 : : }
3711 : 0 : packet_send();
3712 : 0 : }
3713 : :
3714 : : /* dummy protocol handler that denies SSH-1 requests (agent/x11) */
3715 : : /* ARGSUSED */
3716 : : void
3717 : 0 : deny_input_open(int type, u_int32_t seq, void *ctxt)
3718 : : {
3719 : 0 : int rchan = packet_get_int();
3720 : :
3721 [ # # # ]: 0 : switch (type) {
3722 : : case SSH_SMSG_AGENT_OPEN:
3723 : 0 : error("Warning: ssh server tried agent forwarding.");
3724 : 0 : break;
3725 : : case SSH_SMSG_X11_OPEN:
3726 : 0 : error("Warning: ssh server tried X11 forwarding.");
3727 : 0 : break;
3728 : : default:
3729 : 0 : error("deny_input_open: type %d", type);
3730 : 0 : break;
3731 : : }
3732 : 0 : error("Warning: this is probably a break-in attempt by a malicious server.");
3733 : 0 : packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
3734 : 0 : packet_put_int(rchan);
3735 : 0 : packet_send();
3736 : 0 : }
3737 : :
3738 : : /*
3739 : : * Requests forwarding of X11 connections, generates fake authentication
3740 : : * data, and enables authentication spoofing.
3741 : : * This should be called in the client only.
3742 : : */
3743 : : void
3744 : 0 : x11_request_forwarding_with_spoofing(int client_session_id, const char *disp,
3745 : : const char *proto, const char *data, int want_reply)
3746 : : {
3747 : 0 : u_int data_len = (u_int) strlen(data) / 2;
3748 : : u_int i, value;
3749 : : char *new_data;
3750 : : int screen_number;
3751 : : const char *cp;
3752 : 0 : u_int32_t rnd = 0;
3753 : :
3754 [ # # ]: 0 : if (x11_saved_display == NULL)
3755 : 0 : x11_saved_display = xstrdup(disp);
3756 [ # # ]: 0 : else if (strcmp(disp, x11_saved_display) != 0) {
3757 : 0 : error("x11_request_forwarding_with_spoofing: different "
3758 : : "$DISPLAY already forwarded");
3759 : 0 : return;
3760 : : }
3761 : :
3762 : 0 : cp = strchr(disp, ':');
3763 [ # # ]: 0 : if (cp)
3764 : 0 : cp = strchr(cp, '.');
3765 [ # # ]: 0 : if (cp)
3766 : 0 : screen_number = (u_int)strtonum(cp + 1, 0, 400, NULL);
3767 : : else
3768 : : screen_number = 0;
3769 : :
3770 [ # # ]: 0 : if (x11_saved_proto == NULL) {
3771 : : /* Save protocol name. */
3772 : 0 : x11_saved_proto = xstrdup(proto);
3773 : : /*
3774 : : * Extract real authentication data and generate fake data
3775 : : * of the same length.
3776 : : */
3777 : 0 : x11_saved_data = xmalloc(data_len);
3778 : 0 : x11_fake_data = xmalloc(data_len);
3779 [ # # ]: 0 : for (i = 0; i < data_len; i++) {
3780 [ # # ]: 0 : if (sscanf(data + 2 * i, "%2x", &value) != 1)
3781 : 0 : fatal("x11_request_forwarding: bad "
3782 : : "authentication data: %.100s", data);
3783 [ # # ]: 0 : if (i % 4 == 0)
3784 : 0 : rnd = arc4random();
3785 : 0 : x11_saved_data[i] = value;
3786 : 0 : x11_fake_data[i] = rnd & 0xff;
3787 : 0 : rnd >>= 8;
3788 : : }
3789 : 0 : x11_saved_data_len = data_len;
3790 : 0 : x11_fake_data_len = data_len;
3791 : : }
3792 : :
3793 : : /* Convert the fake data into hex. */
3794 : 0 : new_data = tohex(x11_fake_data, data_len);
3795 : :
3796 : : /* Send the request packet. */
3797 [ # # ]: 0 : if (compat20) {
3798 : 0 : channel_request_start(client_session_id, "x11-req", want_reply);
3799 : 0 : packet_put_char(0); /* XXX bool single connection */
3800 : : } else {
3801 : 0 : packet_start(SSH_CMSG_X11_REQUEST_FORWARDING);
3802 : : }
3803 : 0 : packet_put_cstring(proto);
3804 : 0 : packet_put_cstring(new_data);
3805 : 0 : packet_put_int(screen_number);
3806 : 0 : packet_send();
3807 : 0 : packet_write_wait();
3808 : 0 : free(new_data);
3809 : : }
3810 : :
3811 : :
3812 : : /* -- agent forwarding */
3813 : :
3814 : : /* Sends a message to the server to request authentication fd forwarding. */
3815 : :
3816 : : void
3817 : 2 : auth_request_forwarding(void)
3818 : : {
3819 : 2 : packet_start(SSH_CMSG_AGENT_REQUEST_FORWARDING);
3820 : 2 : packet_send();
3821 : 2 : packet_write_wait();
3822 : 2 : }
|