blob: 0a37d1abdf4fc20b2b8eb021da3389b64fc4d446 [file] [log] [blame]
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001/*
Damien Miller95def091999-11-25 00:26:21 +11002 *
3 * channels.c
4 *
5 * Author: Tatu Ylonen <ylo@cs.hut.fi>
6 *
7 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 * All rights reserved
9 *
10 * Created: Fri Mar 24 16:35:24 1995 ylo
11 *
12 * This file contains functions for generic socket connection forwarding.
13 * There is also code for initiating connection forwarding for X11 connections,
14 * arbitrary tcp/ip connections, and the authentication agent connection.
15 *
16 */
Damien Millerd4a8b7e1999-10-27 13:42:43 +100017
18#include "includes.h"
Damien Miller95def091999-11-25 00:26:21 +110019RCSID("$Id: channels.c,v 1.7 1999/11/24 13:26:22 damien Exp $");
Damien Millerd4a8b7e1999-10-27 13:42:43 +100020
21#include "ssh.h"
22#include "packet.h"
23#include "xmalloc.h"
24#include "buffer.h"
25#include "authfd.h"
26#include "uidswap.h"
Damien Miller6d7b2cd1999-11-12 15:19:27 +110027#include "readconf.h"
Damien Millerd4a8b7e1999-10-27 13:42:43 +100028#include "servconf.h"
29
30#include "channels.h"
31#include "nchan.h"
32#include "compat.h"
33
34/* Maximum number of fake X11 displays to try. */
35#define MAX_DISPLAYS 1000
36
37/* Max len of agent socket */
38#define MAX_SOCKET_NAME 100
39
40/* Pointer to an array containing all allocated channels. The array is
41 dynamically extended as needed. */
42static Channel *channels = NULL;
43
44/* Size of the channel array. All slots of the array must always be
45 initialized (at least the type field); unused slots are marked with
46 type SSH_CHANNEL_FREE. */
47static int channels_alloc = 0;
48
49/* Maximum file descriptor value used in any of the channels. This is updated
50 in channel_allocate. */
51static int channel_max_fd_value = 0;
52
53/* Name and directory of socket for authentication agent forwarding. */
54static char *channel_forwarded_auth_socket_name = NULL;
Damien Miller95def091999-11-25 00:26:21 +110055static char *channel_forwarded_auth_socket_dir = NULL;
Damien Millerd4a8b7e1999-10-27 13:42:43 +100056
57/* Saved X11 authentication protocol name. */
58char *x11_saved_proto = NULL;
59
60/* Saved X11 authentication data. This is the real data. */
61char *x11_saved_data = NULL;
62unsigned int x11_saved_data_len = 0;
63
64/* Fake X11 authentication data. This is what the server will be sending
65 us; we should replace any occurrences of this by the real data. */
66char *x11_fake_data = NULL;
67unsigned int x11_fake_data_len;
68
69/* Data structure for storing which hosts are permitted for forward requests.
70 The local sides of any remote forwards are stored in this array to prevent
71 a corrupt remote server from accessing arbitrary TCP/IP ports on our
72 local network (which might be behind a firewall). */
Damien Miller95def091999-11-25 00:26:21 +110073typedef struct {
74 char *host; /* Host name. */
75 int port; /* Port number. */
Damien Millerd4a8b7e1999-10-27 13:42:43 +100076} ForwardPermission;
77
78/* List of all permitted host/port pairs to connect. */
79static ForwardPermission permitted_opens[SSH_MAX_FORWARDS_PER_DIRECTION];
80/* Number of permitted host/port pairs in the array. */
81static int num_permitted_opens = 0;
82/* If this is true, all opens are permitted. This is the case on the
83 server on which we have to trust the client anyway, and the user could
84 do anything after logging in anyway. */
85static int all_opens_permitted = 0;
86
87/* This is set to true if both sides support SSH_PROTOFLAG_HOST_IN_FWD_OPEN. */
88static int have_hostname_in_open = 0;
89
90/* Sets specific protocol options. */
91
Damien Miller95def091999-11-25 00:26:21 +110092void
93channel_set_options(int hostname_in_open)
Damien Millerd4a8b7e1999-10-27 13:42:43 +100094{
Damien Miller95def091999-11-25 00:26:21 +110095 have_hostname_in_open = hostname_in_open;
Damien Millerd4a8b7e1999-10-27 13:42:43 +100096}
97
98/* Permits opening to any host/port in SSH_MSG_PORT_OPEN. This is usually
99 called by the server, because the user could connect to any port anyway,
100 and the server has no way to know but to trust the client anyway. */
101
Damien Miller95def091999-11-25 00:26:21 +1100102void
103channel_permit_all_opens()
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000104{
Damien Miller95def091999-11-25 00:26:21 +1100105 all_opens_permitted = 1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000106}
107
Damien Miller95def091999-11-25 00:26:21 +1100108/* Allocate a new channel object and set its type and socket.
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000109 This will cause remote_name to be freed. */
110
Damien Miller95def091999-11-25 00:26:21 +1100111int
112channel_allocate(int type, int sock, char *remote_name)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000113{
Damien Miller95def091999-11-25 00:26:21 +1100114 int i, found;
115 Channel *c;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000116
Damien Miller95def091999-11-25 00:26:21 +1100117 /* Update the maximum file descriptor value. */
118 if (sock > channel_max_fd_value)
119 channel_max_fd_value = sock;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000120
Damien Miller95def091999-11-25 00:26:21 +1100121 /* Do initial allocation if this is the first call. */
122 if (channels_alloc == 0) {
123 channels_alloc = 10;
124 channels = xmalloc(channels_alloc * sizeof(Channel));
125 for (i = 0; i < channels_alloc; i++)
126 channels[i].type = SSH_CHANNEL_FREE;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000127
Damien Miller95def091999-11-25 00:26:21 +1100128 /* Kludge: arrange a call to channel_stop_listening if we
129 terminate with fatal(). */
130 fatal_add_cleanup((void (*) (void *)) channel_stop_listening, NULL);
131 }
132 /* Try to find a free slot where to put the new channel. */
133 for (found = -1, i = 0; i < channels_alloc; i++)
134 if (channels[i].type == SSH_CHANNEL_FREE) {
135 /* Found a free slot. */
136 found = i;
137 break;
138 }
139 if (found == -1) {
140 /* There are no free slots. Take last+1 slot and expand
141 the array. */
142 found = channels_alloc;
143 channels_alloc += 10;
144 debug("channel: expanding %d", channels_alloc);
145 channels = xrealloc(channels, channels_alloc * sizeof(Channel));
146 for (i = found; i < channels_alloc; i++)
147 channels[i].type = SSH_CHANNEL_FREE;
148 }
149 /* Initialize and return new channel number. */
150 c = &channels[found];
151 buffer_init(&c->input);
152 buffer_init(&c->output);
153 chan_init_iostates(c);
154 c->self = found;
155 c->type = type;
156 c->sock = sock;
157 c->remote_id = -1;
158 c->remote_name = remote_name;
159 debug("channel %d: new [%s]", found, remote_name);
160 return found;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000161}
162
163/* Free the channel and close its socket. */
164
Damien Miller95def091999-11-25 00:26:21 +1100165void
166channel_free(int channel)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000167{
Damien Miller95def091999-11-25 00:26:21 +1100168 if (channel < 0 || channel >= channels_alloc ||
169 channels[channel].type == SSH_CHANNEL_FREE)
170 packet_disconnect("channel free: bad local channel %d", channel);
Damien Millerfd7c9111999-11-08 16:15:55 +1100171
Damien Miller95def091999-11-25 00:26:21 +1100172 if (compat13)
173 shutdown(channels[channel].sock, SHUT_RDWR);
174 close(channels[channel].sock);
175 buffer_free(&channels[channel].input);
176 buffer_free(&channels[channel].output);
177 channels[channel].type = SSH_CHANNEL_FREE;
178 if (channels[channel].remote_name) {
179 xfree(channels[channel].remote_name);
180 channels[channel].remote_name = NULL;
181 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000182}
183
184/* This is called just before select() to add any bits relevant to
185 channels in the select bitmasks. */
186
Damien Miller95def091999-11-25 00:26:21 +1100187void
188channel_prepare_select(fd_set * readset, fd_set * writeset)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000189{
Damien Miller95def091999-11-25 00:26:21 +1100190 int i;
191 Channel *ch;
192 unsigned char *ucp;
193 unsigned int proto_len, data_len;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000194
Damien Miller95def091999-11-25 00:26:21 +1100195 for (i = 0; i < channels_alloc; i++) {
196 ch = &channels[i];
197redo:
198 switch (ch->type) {
199 case SSH_CHANNEL_X11_LISTENER:
200 case SSH_CHANNEL_PORT_LISTENER:
201 case SSH_CHANNEL_AUTH_SOCKET:
202 FD_SET(ch->sock, readset);
203 break;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000204
Damien Miller95def091999-11-25 00:26:21 +1100205 case SSH_CHANNEL_OPEN:
206 if (compat13) {
207 if (buffer_len(&ch->input) < packet_get_maxsize())
208 FD_SET(ch->sock, readset);
209 if (buffer_len(&ch->output) > 0)
210 FD_SET(ch->sock, writeset);
211 break;
212 }
213 /* test whether sockets are 'alive' for read/write */
214 if (ch->istate == CHAN_INPUT_OPEN)
215 if (buffer_len(&ch->input) < packet_get_maxsize())
216 FD_SET(ch->sock, readset);
217 if (ch->ostate == CHAN_OUTPUT_OPEN ||
218 ch->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
219 if (buffer_len(&ch->output) > 0) {
220 FD_SET(ch->sock, writeset);
221 } else if (ch->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
222 chan_obuf_empty(ch);
223 }
224 }
225 break;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000226
Damien Miller95def091999-11-25 00:26:21 +1100227 case SSH_CHANNEL_INPUT_DRAINING:
228 if (!compat13)
229 fatal("cannot happen: IN_DRAIN");
230 if (buffer_len(&ch->input) == 0) {
231 packet_start(SSH_MSG_CHANNEL_CLOSE);
232 packet_put_int(ch->remote_id);
233 packet_send();
234 ch->type = SSH_CHANNEL_CLOSED;
235 debug("Closing channel %d after input drain.", i);
236 break;
237 }
238 break;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000239
Damien Miller95def091999-11-25 00:26:21 +1100240 case SSH_CHANNEL_OUTPUT_DRAINING:
241 if (!compat13)
242 fatal("cannot happen: OUT_DRAIN");
243 if (buffer_len(&ch->output) == 0) {
244 channel_free(i);
245 break;
246 }
247 FD_SET(ch->sock, writeset);
248 break;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000249
Damien Miller95def091999-11-25 00:26:21 +1100250 case SSH_CHANNEL_X11_OPEN:
251 /* This is a special state for X11 authentication
252 spoofing. An opened X11 connection (when
253 authentication spoofing is being done) remains
254 in this state until the first packet has been
255 completely read. The authentication data in
256 that packet is then substituted by the real
257 data if it matches the fake data, and the
258 channel is put into normal mode. */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000259
Damien Miller95def091999-11-25 00:26:21 +1100260 /* Check if the fixed size part of the packet is in buffer. */
261 if (buffer_len(&ch->output) < 12)
262 break;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000263
Damien Miller95def091999-11-25 00:26:21 +1100264 /* Parse the lengths of variable-length fields. */
265 ucp = (unsigned char *) buffer_ptr(&ch->output);
266 if (ucp[0] == 0x42) { /* Byte order MSB first. */
267 proto_len = 256 * ucp[6] + ucp[7];
268 data_len = 256 * ucp[8] + ucp[9];
269 } else if (ucp[0] == 0x6c) { /* Byte order LSB first. */
270 proto_len = ucp[6] + 256 * ucp[7];
271 data_len = ucp[8] + 256 * ucp[9];
272 } else {
273 debug("Initial X11 packet contains bad byte order byte: 0x%x",
274 ucp[0]);
275 ch->type = SSH_CHANNEL_OPEN;
276 goto reject;
277 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000278
Damien Miller95def091999-11-25 00:26:21 +1100279 /* Check if the whole packet is in buffer. */
280 if (buffer_len(&ch->output) <
281 12 + ((proto_len + 3) & ~3) + ((data_len + 3) & ~3))
282 break;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000283
Damien Miller95def091999-11-25 00:26:21 +1100284 /* Check if authentication protocol matches. */
285 if (proto_len != strlen(x11_saved_proto) ||
286 memcmp(ucp + 12, x11_saved_proto, proto_len) != 0) {
287 debug("X11 connection uses different authentication protocol.");
288 ch->type = SSH_CHANNEL_OPEN;
289 goto reject;
290 }
291 /* Check if authentication data matches our fake data. */
292 if (data_len != x11_fake_data_len ||
293 memcmp(ucp + 12 + ((proto_len + 3) & ~3),
294 x11_fake_data, x11_fake_data_len) != 0) {
295 debug("X11 auth data does not match fake data.");
296 ch->type = SSH_CHANNEL_OPEN;
297 goto reject;
298 }
299 /* Check fake data length */
300 if (x11_fake_data_len != x11_saved_data_len) {
301 error("X11 fake_data_len %d != saved_data_len %d",
302 x11_fake_data_len, x11_saved_data_len);
303 ch->type = SSH_CHANNEL_OPEN;
304 goto reject;
305 }
306 /* Received authentication protocol and data match
307 our fake data. Substitute the fake data with
308 real data. */
309 memcpy(ucp + 12 + ((proto_len + 3) & ~3),
310 x11_saved_data, x11_saved_data_len);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000311
Damien Miller95def091999-11-25 00:26:21 +1100312 /* Start normal processing for the channel. */
313 ch->type = SSH_CHANNEL_OPEN;
314 goto redo;
Damien Millerfd7c9111999-11-08 16:15:55 +1100315
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000316 reject:
Damien Miller95def091999-11-25 00:26:21 +1100317 /* We have received an X11 connection that has bad
318 authentication information. */
319 log("X11 connection rejected because of wrong authentication.\r\n");
320 buffer_clear(&ch->input);
321 buffer_clear(&ch->output);
322 if (compat13) {
323 close(ch->sock);
324 ch->sock = -1;
325 ch->type = SSH_CHANNEL_CLOSED;
326 packet_start(SSH_MSG_CHANNEL_CLOSE);
327 packet_put_int(ch->remote_id);
328 packet_send();
329 } else {
330 debug("X11 rejected %d i%d/o%d", ch->self, ch->istate, ch->ostate);
331 chan_read_failed(ch);
332 chan_write_failed(ch);
333 debug("X11 rejected %d i%d/o%d", ch->self, ch->istate, ch->ostate);
334 }
335 break;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000336
Damien Miller95def091999-11-25 00:26:21 +1100337 case SSH_CHANNEL_FREE:
338 default:
339 continue;
340 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000341 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000342}
343
344/* After select, perform any appropriate operations for channels which
345 have events pending. */
346
Damien Miller95def091999-11-25 00:26:21 +1100347void
348channel_after_select(fd_set * readset, fd_set * writeset)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000349{
Damien Miller95def091999-11-25 00:26:21 +1100350 struct sockaddr addr;
351 int addrlen, newsock, i, newch, len;
352 Channel *ch;
353 char buf[16384], *remote_hostname;
354
355 /* Loop over all channels... */
356 for (i = 0; i < channels_alloc; i++) {
357 ch = &channels[i];
358 switch (ch->type) {
359 case SSH_CHANNEL_X11_LISTENER:
360 /* This is our fake X11 server socket. */
361 if (FD_ISSET(ch->sock, readset)) {
362 debug("X11 connection requested.");
363 addrlen = sizeof(addr);
364 newsock = accept(ch->sock, &addr, &addrlen);
365 if (newsock < 0) {
366 error("accept: %.100s", strerror(errno));
367 break;
368 }
369 remote_hostname = get_remote_hostname(newsock);
370 snprintf(buf, sizeof buf, "X11 connection from %.200s port %d",
371 remote_hostname, get_peer_port(newsock));
372 xfree(remote_hostname);
373 newch = channel_allocate(SSH_CHANNEL_OPENING, newsock,
374 xstrdup(buf));
375 packet_start(SSH_SMSG_X11_OPEN);
376 packet_put_int(newch);
377 if (have_hostname_in_open)
378 packet_put_string(buf, strlen(buf));
379 packet_send();
380 }
381 break;
382
383 case SSH_CHANNEL_PORT_LISTENER:
384 /* This socket is listening for connections to a
385 forwarded TCP/IP port. */
386 if (FD_ISSET(ch->sock, readset)) {
387 debug("Connection to port %d forwarding to %.100s:%d requested.",
388 ch->listening_port, ch->path, ch->host_port);
389 addrlen = sizeof(addr);
390 newsock = accept(ch->sock, &addr, &addrlen);
391 if (newsock < 0) {
392 error("accept: %.100s", strerror(errno));
393 break;
394 }
395 remote_hostname = get_remote_hostname(newsock);
396 snprintf(buf, sizeof buf, "listen port %d:%.100s:%d, connect from %.200s:%d",
397 ch->listening_port, ch->path, ch->host_port,
398 remote_hostname, get_peer_port(newsock));
399 xfree(remote_hostname);
400 newch = channel_allocate(SSH_CHANNEL_OPENING, newsock,
401 xstrdup(buf));
402 packet_start(SSH_MSG_PORT_OPEN);
403 packet_put_int(newch);
404 packet_put_string(ch->path, strlen(ch->path));
405 packet_put_int(ch->host_port);
406 if (have_hostname_in_open)
407 packet_put_string(buf, strlen(buf));
408 packet_send();
409 }
410 break;
411
412 case SSH_CHANNEL_AUTH_SOCKET:
413 /* This is the authentication agent socket
414 listening for connections from clients. */
415 if (FD_ISSET(ch->sock, readset)) {
416 int nchan;
417 len = sizeof(addr);
418 newsock = accept(ch->sock, &addr, &len);
419 if (newsock < 0) {
420 error("accept from auth socket: %.100s", strerror(errno));
421 break;
422 }
423 nchan = channel_allocate(SSH_CHANNEL_OPENING, newsock,
424 xstrdup("accepted auth socket"));
425 packet_start(SSH_SMSG_AGENT_OPEN);
426 packet_put_int(nchan);
427 packet_send();
428 }
429 break;
430
431 case SSH_CHANNEL_OPEN:
432 /* This is an open two-way communication channel.
433 It is not of interest to us at this point what
434 kind of data is being transmitted. */
435
436 /* Read available incoming data and append it to
437 buffer; shutdown socket, if read or write
438 failes */
439 if (FD_ISSET(ch->sock, readset)) {
440 len = read(ch->sock, buf, sizeof(buf));
441 if (len <= 0) {
442 if (compat13) {
443 buffer_consume(&ch->output, buffer_len(&ch->output));
444 ch->type = SSH_CHANNEL_INPUT_DRAINING;
445 debug("Channel %d status set to input draining.", i);
446 } else {
447 chan_read_failed(ch);
448 }
449 break;
450 }
451 buffer_append(&ch->input, buf, len);
452 }
453 /* Send buffered output data to the socket. */
454 if (FD_ISSET(ch->sock, writeset) && buffer_len(&ch->output) > 0) {
455 len = write(ch->sock, buffer_ptr(&ch->output),
456 buffer_len(&ch->output));
457 if (len <= 0) {
458 if (compat13) {
459 buffer_consume(&ch->output, buffer_len(&ch->output));
460 debug("Channel %d status set to input draining.", i);
461 ch->type = SSH_CHANNEL_INPUT_DRAINING;
462 } else {
463 chan_write_failed(ch);
464 }
465 break;
466 }
467 buffer_consume(&ch->output, len);
468 }
469 break;
470
471 case SSH_CHANNEL_OUTPUT_DRAINING:
472 if (!compat13)
473 fatal("cannot happen: OUT_DRAIN");
474 /* Send buffered output data to the socket. */
475 if (FD_ISSET(ch->sock, writeset) && buffer_len(&ch->output) > 0) {
476 len = write(ch->sock, buffer_ptr(&ch->output),
477 buffer_len(&ch->output));
478 if (len <= 0)
479 buffer_consume(&ch->output, buffer_len(&ch->output));
480 else
481 buffer_consume(&ch->output, len);
482 }
483 break;
484
485 case SSH_CHANNEL_X11_OPEN:
486 case SSH_CHANNEL_FREE:
487 default:
488 continue;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000489 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000490 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000491}
492
493/* If there is data to send to the connection, send some of it now. */
494
Damien Miller95def091999-11-25 00:26:21 +1100495void
496channel_output_poll()
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000497{
Damien Miller95def091999-11-25 00:26:21 +1100498 int len, i;
499 Channel *ch;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000500
Damien Miller95def091999-11-25 00:26:21 +1100501 for (i = 0; i < channels_alloc; i++) {
502 ch = &channels[i];
503 /* We are only interested in channels that can have
504 buffered incoming data. */
505 if (ch->type != SSH_CHANNEL_OPEN &&
506 ch->type != SSH_CHANNEL_INPUT_DRAINING)
507 continue;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000508
Damien Miller95def091999-11-25 00:26:21 +1100509 /* Get the amount of buffered data for this channel. */
510 len = buffer_len(&ch->input);
511 if (len > 0) {
512 /* Send some data for the other side over the
513 secure connection. */
514 if (packet_is_interactive()) {
515 if (len > 1024)
516 len = 512;
517 } else {
518 /* Keep the packets at reasonable size. */
519 if (len > 16384)
520 len = 16384;
521 }
522 packet_start(SSH_MSG_CHANNEL_DATA);
523 packet_put_int(ch->remote_id);
524 packet_put_string(buffer_ptr(&ch->input), len);
525 packet_send();
526 buffer_consume(&ch->input, len);
527 } else if (ch->istate == CHAN_INPUT_WAIT_DRAIN) {
528 if (compat13)
529 fatal("cannot happen: istate == INPUT_WAIT_DRAIN for proto 1.3");
530 /* input-buffer is empty and read-socket shutdown:
531 tell peer, that we will not send more data:
532 send IEOF */
533 chan_ibuf_empty(ch);
534 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000535 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000536}
537
538/* This is called when a packet of type CHANNEL_DATA has just been received.
539 The message type has already been consumed, but channel number and data
540 is still there. */
541
Damien Miller95def091999-11-25 00:26:21 +1100542void
543channel_input_data(int payload_len)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000544{
Damien Miller95def091999-11-25 00:26:21 +1100545 int channel;
546 char *data;
547 unsigned int data_len;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000548
Damien Miller95def091999-11-25 00:26:21 +1100549 /* Get the channel number and verify it. */
550 channel = packet_get_int();
551 if (channel < 0 || channel >= channels_alloc ||
552 channels[channel].type == SSH_CHANNEL_FREE)
553 packet_disconnect("Received data for nonexistent channel %d.", channel);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000554
Damien Miller95def091999-11-25 00:26:21 +1100555 /* Ignore any data for non-open channels (might happen on close) */
556 if (channels[channel].type != SSH_CHANNEL_OPEN &&
557 channels[channel].type != SSH_CHANNEL_X11_OPEN)
558 return;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000559
Damien Miller95def091999-11-25 00:26:21 +1100560 /* Get the data. */
561 data = packet_get_string(&data_len);
562 packet_integrity_check(payload_len, 4 + 4 + data_len, SSH_MSG_CHANNEL_DATA);
563 buffer_append(&channels[channel].output, data, data_len);
564 xfree(data);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000565}
566
567/* Returns true if no channel has too much buffered data, and false if
568 one or more channel is overfull. */
569
Damien Miller95def091999-11-25 00:26:21 +1100570int
571channel_not_very_much_buffered_data()
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000572{
Damien Miller95def091999-11-25 00:26:21 +1100573 unsigned int i;
574 Channel *ch;
575
576 for (i = 0; i < channels_alloc; i++) {
577 ch = &channels[i];
578 switch (ch->type) {
579 case SSH_CHANNEL_X11_LISTENER:
580 case SSH_CHANNEL_PORT_LISTENER:
581 case SSH_CHANNEL_AUTH_SOCKET:
582 continue;
583 case SSH_CHANNEL_OPEN:
584 if (buffer_len(&ch->input) > packet_get_maxsize())
585 return 0;
586 if (buffer_len(&ch->output) > packet_get_maxsize())
587 return 0;
588 continue;
589 case SSH_CHANNEL_INPUT_DRAINING:
590 case SSH_CHANNEL_OUTPUT_DRAINING:
591 case SSH_CHANNEL_X11_OPEN:
592 case SSH_CHANNEL_FREE:
593 default:
594 continue;
595 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000596 }
Damien Miller95def091999-11-25 00:26:21 +1100597 return 1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000598}
599
600/* This is called after receiving CHANNEL_CLOSE/IEOF. */
601
Damien Miller95def091999-11-25 00:26:21 +1100602void
603channel_input_close()
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000604{
Damien Miller95def091999-11-25 00:26:21 +1100605 int channel;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000606
Damien Miller95def091999-11-25 00:26:21 +1100607 /* Get the channel number and verify it. */
608 channel = packet_get_int();
609 if (channel < 0 || channel >= channels_alloc ||
610 channels[channel].type == SSH_CHANNEL_FREE)
611 packet_disconnect("Received data for nonexistent channel %d.", channel);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000612
Damien Miller95def091999-11-25 00:26:21 +1100613 if (!compat13) {
614 /* proto version 1.5 overloads CLOSE with IEOF */
615 chan_rcvd_ieof(&channels[channel]);
616 return;
617 }
618 /* Send a confirmation that we have closed the channel and no more
619 data is coming for it. */
620 packet_start(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION);
621 packet_put_int(channels[channel].remote_id);
622 packet_send();
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000623
Damien Miller95def091999-11-25 00:26:21 +1100624 /* If the channel is in closed state, we have sent a close
625 request, and the other side will eventually respond with a
626 confirmation. Thus, we cannot free the channel here, because
627 then there would be no-one to receive the confirmation. The
628 channel gets freed when the confirmation arrives. */
629 if (channels[channel].type != SSH_CHANNEL_CLOSED) {
630 /* Not a closed channel - mark it as draining, which will
631 cause it to be freed later. */
632 buffer_consume(&channels[channel].input,
633 buffer_len(&channels[channel].input));
634 channels[channel].type = SSH_CHANNEL_OUTPUT_DRAINING;
635 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000636}
637
638/* This is called after receiving CHANNEL_CLOSE_CONFIRMATION/OCLOSE. */
639
Damien Miller95def091999-11-25 00:26:21 +1100640void
641channel_input_close_confirmation()
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000642{
Damien Miller95def091999-11-25 00:26:21 +1100643 int channel;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000644
Damien Miller95def091999-11-25 00:26:21 +1100645 /* Get the channel number and verify it. */
646 channel = packet_get_int();
647 if (channel < 0 || channel >= channels_alloc)
648 packet_disconnect("Received close confirmation for out-of-range channel %d.",
649 channel);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000650
Damien Miller95def091999-11-25 00:26:21 +1100651 if (!compat13) {
652 /* proto version 1.5 overloads CLOSE_CONFIRMATION with OCLOSE */
653 chan_rcvd_oclose(&channels[channel]);
654 return;
655 }
656 if (channels[channel].type != SSH_CHANNEL_CLOSED)
657 packet_disconnect("Received close confirmation for non-closed channel %d (type %d).",
658 channel, channels[channel].type);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000659
Damien Miller95def091999-11-25 00:26:21 +1100660 /* Free the channel. */
661 channel_free(channel);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000662}
663
664/* This is called after receiving CHANNEL_OPEN_CONFIRMATION. */
665
Damien Miller95def091999-11-25 00:26:21 +1100666void
667channel_input_open_confirmation()
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000668{
Damien Miller95def091999-11-25 00:26:21 +1100669 int channel, remote_channel;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000670
Damien Miller95def091999-11-25 00:26:21 +1100671 /* Get the channel number and verify it. */
672 channel = packet_get_int();
673 if (channel < 0 || channel >= channels_alloc ||
674 channels[channel].type != SSH_CHANNEL_OPENING)
675 packet_disconnect("Received open confirmation for non-opening channel %d.",
676 channel);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000677
Damien Miller95def091999-11-25 00:26:21 +1100678 /* Get remote side's id for this channel. */
679 remote_channel = packet_get_int();
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000680
Damien Miller95def091999-11-25 00:26:21 +1100681 /* Record the remote channel number and mark that the channel is
682 now open. */
683 channels[channel].remote_id = remote_channel;
684 channels[channel].type = SSH_CHANNEL_OPEN;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000685}
686
687/* This is called after receiving CHANNEL_OPEN_FAILURE from the other side. */
688
Damien Miller95def091999-11-25 00:26:21 +1100689void
690channel_input_open_failure()
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000691{
Damien Miller95def091999-11-25 00:26:21 +1100692 int channel;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000693
Damien Miller95def091999-11-25 00:26:21 +1100694 /* Get the channel number and verify it. */
695 channel = packet_get_int();
696 if (channel < 0 || channel >= channels_alloc ||
697 channels[channel].type != SSH_CHANNEL_OPENING)
698 packet_disconnect("Received open failure for non-opening channel %d.",
699 channel);
700
701 /* Free the channel. This will also close the socket. */
702 channel_free(channel);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000703}
704
705/* Stops listening for channels, and removes any unix domain sockets that
706 we might have. */
707
Damien Miller95def091999-11-25 00:26:21 +1100708void
709channel_stop_listening()
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000710{
Damien Miller95def091999-11-25 00:26:21 +1100711 int i;
712 for (i = 0; i < channels_alloc; i++) {
713 switch (channels[i].type) {
714 case SSH_CHANNEL_AUTH_SOCKET:
715 close(channels[i].sock);
716 remove(channels[i].path);
717 channel_free(i);
718 break;
719 case SSH_CHANNEL_PORT_LISTENER:
720 case SSH_CHANNEL_X11_LISTENER:
721 close(channels[i].sock);
722 channel_free(i);
723 break;
724 default:
725 break;
726 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000727 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000728}
729
730/* Closes the sockets of all channels. This is used to close extra file
731 descriptors after a fork. */
732
Damien Miller95def091999-11-25 00:26:21 +1100733void
734channel_close_all()
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000735{
Damien Miller95def091999-11-25 00:26:21 +1100736 int i;
737 for (i = 0; i < channels_alloc; i++) {
738 if (channels[i].type != SSH_CHANNEL_FREE)
739 close(channels[i].sock);
740 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000741}
742
743/* Returns the maximum file descriptor number used by the channels. */
744
Damien Miller95def091999-11-25 00:26:21 +1100745int
746channel_max_fd()
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000747{
Damien Miller95def091999-11-25 00:26:21 +1100748 return channel_max_fd_value;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000749}
750
751/* Returns true if any channel is still open. */
752
Damien Miller95def091999-11-25 00:26:21 +1100753int
754channel_still_open()
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000755{
Damien Miller95def091999-11-25 00:26:21 +1100756 unsigned int i;
757 for (i = 0; i < channels_alloc; i++)
758 switch (channels[i].type) {
759 case SSH_CHANNEL_FREE:
760 case SSH_CHANNEL_X11_LISTENER:
761 case SSH_CHANNEL_PORT_LISTENER:
762 case SSH_CHANNEL_CLOSED:
763 case SSH_CHANNEL_AUTH_SOCKET:
764 continue;
765 case SSH_CHANNEL_OPENING:
766 case SSH_CHANNEL_OPEN:
767 case SSH_CHANNEL_X11_OPEN:
768 return 1;
769 case SSH_CHANNEL_INPUT_DRAINING:
770 case SSH_CHANNEL_OUTPUT_DRAINING:
771 if (!compat13)
772 fatal("cannot happen: OUT_DRAIN");
773 return 1;
774 default:
775 fatal("channel_still_open: bad channel type %d", channels[i].type);
776 /* NOTREACHED */
777 }
778 return 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000779}
780
781/* Returns a message describing the currently open forwarded
782 connections, suitable for sending to the client. The message
783 contains crlf pairs for newlines. */
784
Damien Miller95def091999-11-25 00:26:21 +1100785char *
786channel_open_message()
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000787{
Damien Miller95def091999-11-25 00:26:21 +1100788 Buffer buffer;
789 int i;
790 char buf[512], *cp;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000791
Damien Miller95def091999-11-25 00:26:21 +1100792 buffer_init(&buffer);
793 snprintf(buf, sizeof buf, "The following connections are open:\r\n");
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000794 buffer_append(&buffer, buf, strlen(buf));
Damien Miller95def091999-11-25 00:26:21 +1100795 for (i = 0; i < channels_alloc; i++) {
796 Channel *c = &channels[i];
797 switch (c->type) {
798 case SSH_CHANNEL_FREE:
799 case SSH_CHANNEL_X11_LISTENER:
800 case SSH_CHANNEL_PORT_LISTENER:
801 case SSH_CHANNEL_CLOSED:
802 case SSH_CHANNEL_AUTH_SOCKET:
803 continue;
804 case SSH_CHANNEL_OPENING:
805 case SSH_CHANNEL_OPEN:
806 case SSH_CHANNEL_X11_OPEN:
807 case SSH_CHANNEL_INPUT_DRAINING:
808 case SSH_CHANNEL_OUTPUT_DRAINING:
809 snprintf(buf, sizeof buf, " #%d %.300s (t%d r%d i%d o%d)\r\n",
810 c->self, c->remote_name,
811 c->type, c->remote_id, c->istate, c->ostate);
812 buffer_append(&buffer, buf, strlen(buf));
813 continue;
814 default:
815 fatal("channel_still_open: bad channel type %d", c->type);
816 /* NOTREACHED */
817 }
818 }
819 buffer_append(&buffer, "\0", 1);
820 cp = xstrdup(buffer_ptr(&buffer));
821 buffer_free(&buffer);
822 return cp;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000823}
824
825/* Initiate forwarding of connections to local port "port" through the secure
826 channel to host:port from remote side. */
827
Damien Miller95def091999-11-25 00:26:21 +1100828void
829channel_request_local_forwarding(int port, const char *host,
830 int host_port)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000831{
Damien Miller95def091999-11-25 00:26:21 +1100832 int ch, sock;
833 struct sockaddr_in sin;
834 extern Options options;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000835
Damien Miller95def091999-11-25 00:26:21 +1100836 if (strlen(host) > sizeof(channels[0].path) - 1)
837 packet_disconnect("Forward host name too long.");
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000838
Damien Miller95def091999-11-25 00:26:21 +1100839 /* Create a port to listen for the host. */
840 sock = socket(AF_INET, SOCK_STREAM, 0);
841 if (sock < 0)
842 packet_disconnect("socket: %.100s", strerror(errno));
843
844 /* Initialize socket address. */
845 memset(&sin, 0, sizeof(sin));
846 sin.sin_family = AF_INET;
847 if (options.gateway_ports == 1)
848 sin.sin_addr.s_addr = htonl(INADDR_ANY);
849 else
850 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
851 sin.sin_port = htons(port);
852
853 /* Bind the socket to the address. */
854 if (bind(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0)
855 packet_disconnect("bind: %.100s", strerror(errno));
856
857 /* Start listening for connections on the socket. */
858 if (listen(sock, 5) < 0)
859 packet_disconnect("listen: %.100s", strerror(errno));
860
861 /* Allocate a channel number for the socket. */
862 ch = channel_allocate(SSH_CHANNEL_PORT_LISTENER, sock,
863 xstrdup("port listener"));
864 strcpy(channels[ch].path, host);
865 channels[ch].host_port = host_port;
866 channels[ch].listening_port = port;
867}
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000868
869/* Initiate forwarding of connections to port "port" on remote host through
870 the secure channel to host:port from local side. */
871
Damien Miller95def091999-11-25 00:26:21 +1100872void
873channel_request_remote_forwarding(int port, const char *host,
874 int remote_port)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000875{
Damien Miller95def091999-11-25 00:26:21 +1100876 int payload_len;
877 /* Record locally that connection to this host/port is permitted. */
878 if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION)
879 fatal("channel_request_remote_forwarding: too many forwards");
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000880
Damien Miller95def091999-11-25 00:26:21 +1100881 permitted_opens[num_permitted_opens].host = xstrdup(host);
882 permitted_opens[num_permitted_opens].port = remote_port;
883 num_permitted_opens++;
884
885 /* Send the forward request to the remote side. */
886 packet_start(SSH_CMSG_PORT_FORWARD_REQUEST);
887 packet_put_int(port);
888 packet_put_string(host, strlen(host));
889 packet_put_int(remote_port);
890 packet_send();
891 packet_write_wait();
892
893 /* Wait for response from the remote side. It will send a
894 disconnect message on failure, and we will never see it here. */
895 packet_read_expect(&payload_len, SSH_SMSG_SUCCESS);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000896}
897
898/* This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates
899 listening for the port, and sends back a success reply (or disconnect
Damien Miller95def091999-11-25 00:26:21 +1100900 message if there was an error). This never returns if there was an
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000901 error. */
902
Damien Miller95def091999-11-25 00:26:21 +1100903void
904channel_input_port_forward_request(int is_root)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000905{
Damien Miller95def091999-11-25 00:26:21 +1100906 int port, host_port;
907 char *hostname;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000908
Damien Miller95def091999-11-25 00:26:21 +1100909 /* Get arguments from the packet. */
910 port = packet_get_int();
911 hostname = packet_get_string(NULL);
912 host_port = packet_get_int();
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000913
Damien Miller95def091999-11-25 00:26:21 +1100914 /* Port numbers are 16 bit quantities. */
915 if ((port & 0xffff) != port)
916 packet_disconnect("Requested forwarding of nonexistent port %d.", port);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000917
Damien Miller95def091999-11-25 00:26:21 +1100918 /* Check that an unprivileged user is not trying to forward a
919 privileged port. */
920 if (port < IPPORT_RESERVED && !is_root)
921 packet_disconnect("Requested forwarding of port %d but user is not root.",
922 port);
923
924 /* Initiate forwarding. */
925 channel_request_local_forwarding(port, hostname, host_port);
926
927 /* Free the argument string. */
928 xfree(hostname);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000929}
930
931/* This is called after receiving PORT_OPEN message. This attempts to connect
932 to the given host:port, and sends back CHANNEL_OPEN_CONFIRMATION or
933 CHANNEL_OPEN_FAILURE. */
934
Damien Miller95def091999-11-25 00:26:21 +1100935void
936channel_input_port_open(int payload_len)
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000937{
Damien Miller95def091999-11-25 00:26:21 +1100938 int remote_channel, sock, newch, host_port, i;
939 struct sockaddr_in sin;
940 char *host, *originator_string;
941 struct hostent *hp;
942 int host_len, originator_len;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000943
Damien Miller95def091999-11-25 00:26:21 +1100944 /* Get remote channel number. */
945 remote_channel = packet_get_int();
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000946
Damien Miller95def091999-11-25 00:26:21 +1100947 /* Get host name to connect to. */
948 host = packet_get_string(&host_len);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000949
Damien Miller95def091999-11-25 00:26:21 +1100950 /* Get port to connect to. */
951 host_port = packet_get_int();
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000952
Damien Miller95def091999-11-25 00:26:21 +1100953 /* Get remote originator name. */
954 if (have_hostname_in_open)
955 originator_string = packet_get_string(&originator_len);
956 else
957 originator_string = xstrdup("unknown (remote did not supply name)");
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000958
Damien Miller95def091999-11-25 00:26:21 +1100959 packet_integrity_check(payload_len,
960 4 + 4 + host_len + 4 + 4 + originator_len,
961 SSH_MSG_PORT_OPEN);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000962
Damien Miller95def091999-11-25 00:26:21 +1100963 /* Check if opening that port is permitted. */
964 if (!all_opens_permitted) {
965 /* Go trough all permitted ports. */
966 for (i = 0; i < num_permitted_opens; i++)
967 if (permitted_opens[i].port == host_port &&
968 strcmp(permitted_opens[i].host, host) == 0)
969 break;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000970
Damien Miller95def091999-11-25 00:26:21 +1100971 /* Check if we found the requested port among those permitted. */
972 if (i >= num_permitted_opens) {
973 /* The port is not permitted. */
974 log("Received request to connect to %.100s:%d, but the request was denied.",
975 host, host_port);
976 packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
977 packet_put_int(remote_channel);
978 packet_send();
979 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000980 }
Damien Miller95def091999-11-25 00:26:21 +1100981 memset(&sin, 0, sizeof(sin));
982 sin.sin_addr.s_addr = inet_addr(host);
983 if ((sin.sin_addr.s_addr & 0xffffffff) != 0xffffffff) {
984 /* It was a valid numeric host address. */
985 sin.sin_family = AF_INET;
986 } else {
987 /* Look up the host address from the name servers. */
988 hp = gethostbyname(host);
989 if (!hp) {
990 error("%.100s: unknown host.", host);
991 goto fail;
992 }
993 if (!hp->h_addr_list[0]) {
994 error("%.100s: host has no IP address.", host);
995 goto fail;
996 }
997 sin.sin_family = hp->h_addrtype;
998 memcpy(&sin.sin_addr, hp->h_addr_list[0],
999 sizeof(sin.sin_addr));
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001000 }
Damien Miller95def091999-11-25 00:26:21 +11001001 sin.sin_port = htons(host_port);
1002
1003 /* Create the socket. */
1004 sock = socket(sin.sin_family, SOCK_STREAM, 0);
1005 if (sock < 0) {
1006 error("socket: %.100s", strerror(errno));
1007 goto fail;
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001008 }
Damien Miller95def091999-11-25 00:26:21 +11001009 /* Connect to the host/port. */
1010 if (connect(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0) {
1011 error("connect %.100s:%d: %.100s", host, host_port,
1012 strerror(errno));
1013 close(sock);
1014 goto fail;
1015 }
1016 /* Successful connection. */
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001017
Damien Miller95def091999-11-25 00:26:21 +11001018 /* Allocate a channel for this connection. */
1019 newch = channel_allocate(SSH_CHANNEL_OPEN, sock, originator_string);
1020 channels[newch].remote_id = remote_channel;
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001021
Damien Miller95def091999-11-25 00:26:21 +11001022 /* Send a confirmation to the remote host. */
1023 packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
1024 packet_put_int(remote_channel);
1025 packet_put_int(newch);
1026 packet_send();
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001027
Damien Miller95def091999-11-25 00:26:21 +11001028 /* Free the argument string. */
1029 xfree(host);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001030
Damien Miller95def091999-11-25 00:26:21 +11001031 return;
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001032
Damien Miller95def091999-11-25 00:26:21 +11001033fail:
1034 /* Free the argument string. */
1035 xfree(host);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001036
Damien Miller95def091999-11-25 00:26:21 +11001037 /* Send refusal to the remote host. */
1038 packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
1039 packet_put_int(remote_channel);
1040 packet_send();
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001041}
1042
Damien Miller95def091999-11-25 00:26:21 +11001043/* Creates an internet domain socket for listening for X11 connections.
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001044 Returns a suitable value for the DISPLAY variable, or NULL if an error
1045 occurs. */
1046
Damien Miller95def091999-11-25 00:26:21 +11001047char *
1048x11_create_display_inet(int screen_number)
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001049{
Damien Miller95def091999-11-25 00:26:21 +11001050 extern ServerOptions options;
1051 int display_number, port, sock;
1052 struct sockaddr_in sin;
1053 char buf[512];
1054 char hostname[MAXHOSTNAMELEN];
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001055
Damien Miller95def091999-11-25 00:26:21 +11001056 for (display_number = options.x11_display_offset;
1057 display_number < MAX_DISPLAYS;
1058 display_number++) {
1059 port = 6000 + display_number;
1060 memset(&sin, 0, sizeof(sin));
1061 sin.sin_family = AF_INET;
1062 sin.sin_addr.s_addr = htonl(INADDR_ANY);
1063 sin.sin_port = htons(port);
1064
1065 sock = socket(AF_INET, SOCK_STREAM, 0);
1066 if (sock < 0) {
1067 error("socket: %.100s", strerror(errno));
1068 return NULL;
1069 }
1070 if (bind(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0) {
1071 debug("bind port %d: %.100s", port, strerror(errno));
1072 shutdown(sock, SHUT_RDWR);
1073 close(sock);
1074 continue;
1075 }
1076 break;
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001077 }
Damien Miller95def091999-11-25 00:26:21 +11001078 if (display_number >= MAX_DISPLAYS) {
1079 error("Failed to allocate internet-domain X11 display socket.");
1080 return NULL;
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001081 }
Damien Miller95def091999-11-25 00:26:21 +11001082 /* Start listening for connections on the socket. */
1083 if (listen(sock, 5) < 0) {
1084 error("listen: %.100s", strerror(errno));
1085 shutdown(sock, SHUT_RDWR);
1086 close(sock);
1087 return NULL;
1088 }
1089 /* Set up a suitable value for the DISPLAY variable. */
1090 if (gethostname(hostname, sizeof(hostname)) < 0)
1091 fatal("gethostname: %.100s", strerror(errno));
1092 snprintf(buf, sizeof buf, "%.400s:%d.%d", hostname,
1093 display_number, screen_number);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001094
Damien Miller95def091999-11-25 00:26:21 +11001095 /* Allocate a channel for the socket. */
1096 (void) channel_allocate(SSH_CHANNEL_X11_LISTENER, sock,
1097 xstrdup("X11 inet listener"));
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001098
Damien Miller95def091999-11-25 00:26:21 +11001099 /* Return a suitable value for the DISPLAY environment variable. */
1100 return xstrdup(buf);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001101}
1102
1103#ifndef X_UNIX_PATH
1104#define X_UNIX_PATH "/tmp/.X11-unix/X"
1105#endif
1106
1107static
1108int
1109connect_local_xsocket(unsigned dnr)
1110{
Damien Miller95def091999-11-25 00:26:21 +11001111 static const char *const x_sockets[] = {
1112 X_UNIX_PATH "%u",
1113 "/var/X/.X11-unix/X" "%u",
1114 "/usr/spool/sockets/X11/" "%u",
1115 NULL
1116 };
1117 int sock;
1118 struct sockaddr_un addr;
1119 const char *const * path;
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001120
Damien Miller95def091999-11-25 00:26:21 +11001121 for (path = x_sockets; *path; ++path) {
1122 sock = socket(AF_UNIX, SOCK_STREAM, 0);
1123 if (sock < 0)
1124 error("socket: %.100s", strerror(errno));
1125 memset(&addr, 0, sizeof(addr));
1126 addr.sun_family = AF_UNIX;
1127 snprintf(addr.sun_path, sizeof addr.sun_path, *path, dnr);
1128 if (connect(sock, (struct sockaddr *) & addr, sizeof(addr)) == 0)
1129 return sock;
1130 close(sock);
1131 }
1132 error("connect %.100s: %.100s", addr.sun_path, strerror(errno));
1133 return -1;
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001134}
1135
1136
1137/* This is called when SSH_SMSG_X11_OPEN is received. The packet contains
1138 the remote channel number. We should do whatever we want, and respond
1139 with either SSH_MSG_OPEN_CONFIRMATION or SSH_MSG_OPEN_FAILURE. */
1140
Damien Miller95def091999-11-25 00:26:21 +11001141void
1142x11_input_open(int payload_len)
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001143{
Damien Miller95def091999-11-25 00:26:21 +11001144 int remote_channel, display_number, sock, newch;
1145 const char *display;
1146 struct sockaddr_in sin;
1147 char buf[1024], *cp, *remote_host;
1148 struct hostent *hp;
1149 int remote_len;
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001150
Damien Miller95def091999-11-25 00:26:21 +11001151 /* Get remote channel number. */
1152 remote_channel = packet_get_int();
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001153
Damien Miller95def091999-11-25 00:26:21 +11001154 /* Get remote originator name. */
1155 if (have_hostname_in_open)
1156 remote_host = packet_get_string(&remote_len);
1157 else
1158 remote_host = xstrdup("unknown (remote did not supply name)");
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001159
Damien Miller95def091999-11-25 00:26:21 +11001160 debug("Received X11 open request.");
1161 packet_integrity_check(payload_len, 4 + 4 + remote_len, SSH_SMSG_X11_OPEN);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001162
Damien Miller95def091999-11-25 00:26:21 +11001163 /* Try to open a socket for the local X server. */
1164 display = getenv("DISPLAY");
1165 if (!display) {
1166 error("DISPLAY not set.");
1167 goto fail;
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001168 }
Damien Miller95def091999-11-25 00:26:21 +11001169 /* Now we decode the value of the DISPLAY variable and make a
1170 connection to the real X server. */
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001171
Damien Miller95def091999-11-25 00:26:21 +11001172 /* Check if it is a unix domain socket. Unix domain displays are
1173 in one of the following formats: unix:d[.s], :d[.s], ::d[.s] */
1174 if (strncmp(display, "unix:", 5) == 0 ||
1175 display[0] == ':') {
1176 /* Connect to the unix domain socket. */
1177 if (sscanf(strrchr(display, ':') + 1, "%d", &display_number) != 1) {
1178 error("Could not parse display number from DISPLAY: %.100s",
1179 display);
1180 goto fail;
1181 }
1182 /* Create a socket. */
1183 sock = connect_local_xsocket(display_number);
1184 if (sock < 0)
1185 goto fail;
1186
1187 /* OK, we now have a connection to the display. */
1188 goto success;
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001189 }
Damien Miller95def091999-11-25 00:26:21 +11001190 /* Connect to an inet socket. The DISPLAY value is supposedly
1191 hostname:d[.s], where hostname may also be numeric IP address. */
1192 strncpy(buf, display, sizeof(buf));
1193 buf[sizeof(buf) - 1] = 0;
1194 cp = strchr(buf, ':');
1195 if (!cp) {
1196 error("Could not find ':' in DISPLAY: %.100s", display);
1197 goto fail;
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001198 }
Damien Miller95def091999-11-25 00:26:21 +11001199 *cp = 0;
1200 /* buf now contains the host name. But first we parse the display
1201 number. */
1202 if (sscanf(cp + 1, "%d", &display_number) != 1) {
1203 error("Could not parse display number from DISPLAY: %.100s",
1204 display);
1205 goto fail;
1206 }
1207 /* Try to parse the host name as a numeric IP address. */
1208 memset(&sin, 0, sizeof(sin));
1209 sin.sin_addr.s_addr = inet_addr(buf);
1210 if ((sin.sin_addr.s_addr & 0xffffffff) != 0xffffffff) {
1211 /* It was a valid numeric host address. */
1212 sin.sin_family = AF_INET;
1213 } else {
1214 /* Not a numeric IP address. */
1215 /* Look up the host address from the name servers. */
1216 hp = gethostbyname(buf);
1217 if (!hp) {
1218 error("%.100s: unknown host.", buf);
1219 goto fail;
1220 }
1221 if (!hp->h_addr_list[0]) {
1222 error("%.100s: host has no IP address.", buf);
1223 goto fail;
1224 }
1225 sin.sin_family = hp->h_addrtype;
1226 memcpy(&sin.sin_addr, hp->h_addr_list[0],
1227 sizeof(sin.sin_addr));
1228 }
1229 /* Set port number. */
1230 sin.sin_port = htons(6000 + display_number);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001231
Damien Miller95def091999-11-25 00:26:21 +11001232 /* Create a socket. */
1233 sock = socket(sin.sin_family, SOCK_STREAM, 0);
1234 if (sock < 0) {
1235 error("socket: %.100s", strerror(errno));
1236 goto fail;
1237 }
1238 /* Connect it to the display. */
1239 if (connect(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0) {
1240 error("connect %.100s:%d: %.100s", buf, 6000 + display_number,
1241 strerror(errno));
1242 close(sock);
1243 goto fail;
1244 }
1245success:
1246 /* We have successfully obtained a connection to the real X display. */
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001247
Damien Miller95def091999-11-25 00:26:21 +11001248 /* Allocate a channel for this connection. */
1249 if (x11_saved_proto == NULL)
1250 newch = channel_allocate(SSH_CHANNEL_OPEN, sock, remote_host);
1251 else
1252 newch = channel_allocate(SSH_CHANNEL_X11_OPEN, sock, remote_host);
1253 channels[newch].remote_id = remote_channel;
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001254
Damien Miller95def091999-11-25 00:26:21 +11001255 /* Send a confirmation to the remote host. */
1256 packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
1257 packet_put_int(remote_channel);
1258 packet_put_int(newch);
1259 packet_send();
1260
1261 return;
1262
1263fail:
1264 /* Send refusal to the remote host. */
1265 packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
1266 packet_put_int(remote_channel);
1267 packet_send();
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001268}
1269
1270/* Requests forwarding of X11 connections, generates fake authentication
1271 data, and enables authentication spoofing. */
1272
Damien Miller95def091999-11-25 00:26:21 +11001273void
1274x11_request_forwarding_with_spoofing(const char *proto, const char *data)
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001275{
Damien Miller95def091999-11-25 00:26:21 +11001276 unsigned int data_len = (unsigned int) strlen(data) / 2;
1277 unsigned int i, value;
1278 char *new_data;
1279 int screen_number;
1280 const char *cp;
1281 u_int32_t rand = 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001282
Damien Miller95def091999-11-25 00:26:21 +11001283 cp = getenv("DISPLAY");
1284 if (cp)
1285 cp = strchr(cp, ':');
1286 if (cp)
1287 cp = strchr(cp, '.');
1288 if (cp)
1289 screen_number = atoi(cp + 1);
1290 else
1291 screen_number = 0;
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001292
Damien Miller95def091999-11-25 00:26:21 +11001293 /* Save protocol name. */
1294 x11_saved_proto = xstrdup(proto);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001295
Damien Miller95def091999-11-25 00:26:21 +11001296 /* Extract real authentication data and generate fake data of the
1297 same length. */
1298 x11_saved_data = xmalloc(data_len);
1299 x11_fake_data = xmalloc(data_len);
1300 for (i = 0; i < data_len; i++) {
1301 if (sscanf(data + 2 * i, "%2x", &value) != 1)
1302 fatal("x11_request_forwarding: bad authentication data: %.100s", data);
1303 if (i % 4 == 0)
1304 rand = arc4random();
1305 x11_saved_data[i] = value;
1306 x11_fake_data[i] = rand & 0xff;
1307 rand >>= 8;
1308 }
1309 x11_saved_data_len = data_len;
1310 x11_fake_data_len = data_len;
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001311
Damien Miller95def091999-11-25 00:26:21 +11001312 /* Convert the fake data into hex. */
1313 new_data = xmalloc(2 * data_len + 1);
1314 for (i = 0; i < data_len; i++)
1315 sprintf(new_data + 2 * i, "%02x", (unsigned char) x11_fake_data[i]);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001316
Damien Miller95def091999-11-25 00:26:21 +11001317 /* Send the request packet. */
1318 packet_start(SSH_CMSG_X11_REQUEST_FORWARDING);
1319 packet_put_string(proto, strlen(proto));
1320 packet_put_string(new_data, strlen(new_data));
1321 packet_put_int(screen_number);
1322 packet_send();
1323 packet_write_wait();
1324 xfree(new_data);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001325}
1326
1327/* Sends a message to the server to request authentication fd forwarding. */
1328
Damien Miller95def091999-11-25 00:26:21 +11001329void
1330auth_request_forwarding()
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001331{
Damien Miller95def091999-11-25 00:26:21 +11001332 packet_start(SSH_CMSG_AGENT_REQUEST_FORWARDING);
1333 packet_send();
1334 packet_write_wait();
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001335}
1336
1337/* Returns the name of the forwarded authentication socket. Returns NULL
1338 if there is no forwarded authentication socket. The returned value
1339 points to a static buffer. */
1340
Damien Miller95def091999-11-25 00:26:21 +11001341char *
1342auth_get_socket_name()
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001343{
Damien Miller95def091999-11-25 00:26:21 +11001344 return channel_forwarded_auth_socket_name;
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001345}
1346
1347/* removes the agent forwarding socket */
1348
Damien Miller95def091999-11-25 00:26:21 +11001349void
1350cleanup_socket(void)
1351{
1352 remove(channel_forwarded_auth_socket_name);
1353 rmdir(channel_forwarded_auth_socket_dir);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001354}
1355
1356/* This if called to process SSH_CMSG_AGENT_REQUEST_FORWARDING on the server.
1357 This starts forwarding authentication requests. */
1358
Damien Miller95def091999-11-25 00:26:21 +11001359void
1360auth_input_request_forwarding(struct passwd * pw)
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001361{
Damien Miller95def091999-11-25 00:26:21 +11001362 int sock, newch;
1363 struct sockaddr_un sunaddr;
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001364
Damien Miller95def091999-11-25 00:26:21 +11001365 if (auth_get_socket_name() != NULL)
1366 fatal("Protocol error: authentication forwarding requested twice.");
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001367
Damien Miller95def091999-11-25 00:26:21 +11001368 /* Temporarily drop privileged uid for mkdir/bind. */
1369 temporarily_use_uid(pw->pw_uid);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001370
Damien Miller95def091999-11-25 00:26:21 +11001371 /* Allocate a buffer for the socket name, and format the name. */
1372 channel_forwarded_auth_socket_name = xmalloc(MAX_SOCKET_NAME);
1373 channel_forwarded_auth_socket_dir = xmalloc(MAX_SOCKET_NAME);
1374 strlcpy(channel_forwarded_auth_socket_dir, "/tmp/ssh-XXXXXXXX", MAX_SOCKET_NAME);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001375
Damien Miller95def091999-11-25 00:26:21 +11001376 /* Create private directory for socket */
1377 if (mkdtemp(channel_forwarded_auth_socket_dir) == NULL)
1378 packet_disconnect("mkdtemp: %.100s", strerror(errno));
1379 snprintf(channel_forwarded_auth_socket_name, MAX_SOCKET_NAME, "%s/agent.%d",
1380 channel_forwarded_auth_socket_dir, (int) getpid());
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001381
Damien Miller95def091999-11-25 00:26:21 +11001382 if (atexit(cleanup_socket) < 0) {
1383 int saved = errno;
1384 cleanup_socket();
1385 packet_disconnect("socket: %.100s", strerror(saved));
1386 }
1387 /* Create the socket. */
1388 sock = socket(AF_UNIX, SOCK_STREAM, 0);
1389 if (sock < 0)
1390 packet_disconnect("socket: %.100s", strerror(errno));
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001391
Damien Miller95def091999-11-25 00:26:21 +11001392 /* Bind it to the name. */
1393 memset(&sunaddr, 0, sizeof(sunaddr));
1394 sunaddr.sun_family = AF_UNIX;
1395 strncpy(sunaddr.sun_path, channel_forwarded_auth_socket_name,
1396 sizeof(sunaddr.sun_path));
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001397
Damien Miller95def091999-11-25 00:26:21 +11001398 if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0)
1399 packet_disconnect("bind: %.100s", strerror(errno));
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001400
Damien Miller95def091999-11-25 00:26:21 +11001401 /* Restore the privileged uid. */
1402 restore_uid();
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001403
Damien Miller95def091999-11-25 00:26:21 +11001404 /* Start listening on the socket. */
1405 if (listen(sock, 5) < 0)
1406 packet_disconnect("listen: %.100s", strerror(errno));
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001407
Damien Miller95def091999-11-25 00:26:21 +11001408 /* Allocate a channel for the authentication agent socket. */
1409 newch = channel_allocate(SSH_CHANNEL_AUTH_SOCKET, sock,
1410 xstrdup("auth socket"));
1411 strcpy(channels[newch].path, channel_forwarded_auth_socket_name);
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001412}
1413
1414/* This is called to process an SSH_SMSG_AGENT_OPEN message. */
1415
Damien Miller95def091999-11-25 00:26:21 +11001416void
1417auth_input_open_request()
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001418{
Damien Miller95def091999-11-25 00:26:21 +11001419 int remch, sock, newch;
1420 char *dummyname;
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001421
Damien Miller95def091999-11-25 00:26:21 +11001422 /* Read the remote channel number from the message. */
1423 remch = packet_get_int();
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001424
Damien Miller95def091999-11-25 00:26:21 +11001425 /* Get a connection to the local authentication agent (this may
1426 again get forwarded). */
1427 sock = ssh_get_authentication_socket();
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001428
Damien Miller95def091999-11-25 00:26:21 +11001429 /* If we could not connect the agent, send an error message back
1430 to the server. This should never happen unless the agent dies,
1431 because authentication forwarding is only enabled if we have an
1432 agent. */
1433 if (sock < 0) {
1434 packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
1435 packet_put_int(remch);
1436 packet_send();
1437 return;
1438 }
1439 debug("Forwarding authentication connection.");
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001440
Damien Miller95def091999-11-25 00:26:21 +11001441 /* Dummy host name. This will be freed when the channel is freed;
1442 it will still be valid in the packet_put_string below since the
1443 channel cannot yet be freed at that point. */
1444 dummyname = xstrdup("authentication agent connection");
1445
1446 newch = channel_allocate(SSH_CHANNEL_OPEN, sock, dummyname);
1447 channels[newch].remote_id = remch;
1448
1449 /* Send a confirmation to the remote host. */
1450 packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
1451 packet_put_int(remch);
1452 packet_put_int(newch);
1453 packet_send();
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001454}