channel.c 35.9 KB
Newer Older
Niels Möller's avatar
Niels Möller committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* channel.c
 *
 * $Id$
 */

/* lsh, an implementation of the ssh protocol
 *
 * Copyright (C) 1998 Niels Mller
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
J.H.M. Dassen's avatar
J.H.M. Dassen committed
22
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
Niels Möller's avatar
Niels Möller committed
23
24
25
26
27
 */

#include "channel.h"

#include "format.h"
28
#include "io.h"
Niels Möller's avatar
Niels Möller committed
29
#include "read_data.h"
Niels Möller's avatar
Niels Möller committed
30
31
32
33
34
#include "ssh.h"
#include "werror.h"
#include "xalloc.h"

#include <assert.h>
35
#include <string.h>
Niels Möller's avatar
Niels Möller committed
36

37
#define GABA_DEFINE
38
#include "channel.h.x"
39
#undef GABA_DEFINE
40

41
42
#include "channel.c.x"

43
/* GABA:
44
45
   (class
     (name connection_service)
46
     (super command)
47
48
49
50
     (vars
       ; Supported global requests 
       (global_requests object alist)

51
       (channel_types object alist) ))
52
53
54
55

       ; Initialize connection (for instance, request channels to be 
       ; opened or services to be forwarded).

56
       ; (start object connection_startup)))
57
58
*/

59
/* GABA:
60
61
   (class
     (name global_request_handler)
62
     (super packet_handler)
63
64
65
66
     (vars
       (global_requests object alist)))
*/

67
/* GABA:
68
69
   (class
     (name channel_open_handler)
70
     (super packet_handler)
71
72
73
74
     (vars
       (channel_types object alist)))
*/

75
/* GABA:
76
77
78
79
80
81
82
83
84
   (class
     (name channel_open_response)
     (super channel_open_callback)
     (vars
       (remote_channel_number simple UINT32)
       (window_size simple UINT32)
       (max_packet simple UINT32)))
*/

Niels Möller's avatar
Niels Möller committed
85
86
87
88
89
struct lsh_string *format_global_failure(void)
{
  return ssh_format("%c", SSH_MSG_REQUEST_FAILURE);
}

90
91
92
93
94
struct lsh_string *format_global_success(void)
{
  return ssh_format("%c", SSH_MSG_REQUEST_SUCCESS);
}

95
96
struct lsh_string *format_open_confirmation(struct ssh_channel *channel,
					    UINT32 channel_number,
97
					    const char *format, ...)
98
99
100
101
102
103
{
  va_list args;
  UINT32 l1, l2;
  struct lsh_string *packet;

#define CONFIRM_FORMAT "%c%i%i%i%i"
104
105
#define CONFIRM_ARGS \
  SSH_MSG_CHANNEL_OPEN_CONFIRMATION, channel->channel_number, \
106
107
108
109
110
111
112
113
114
115
116
117
118
  channel_number, channel->rec_window_size, channel->rec_max_packet
    
  l1 = ssh_format_length(CONFIRM_FORMAT, CONFIRM_ARGS);

  va_start(args, format);
  l2 = ssh_vformat_length(format, args);
  va_end(args);

  packet = lsh_string_alloc(l1 + l2);

  ssh_format_write(CONFIRM_FORMAT, l1, packet->data, CONFIRM_ARGS);

  va_start(args, format);
119
  ssh_vformat_write(format, l2, packet->data+l1, args);
120
121
122
123
124
125
126
  va_end(args);

  return packet;
#undef CONFIRM_FORMAT
#undef CONFIRM_ARGS
}

Niels Möller's avatar
Niels Möller committed
127
struct lsh_string *format_open_failure(UINT32 channel, UINT32 reason,
128
				       const char *msg, const char *language)
Niels Möller's avatar
Niels Möller committed
129
130
131
132
133
{
  return ssh_format("%c%i%i%z%z", SSH_MSG_CHANNEL_OPEN_FAILURE,
		    channel, reason, msg, language);
}

134
135
136
137
138
struct lsh_string *format_channel_success(UINT32 channel)
{
  return ssh_format("%c%i", SSH_MSG_CHANNEL_SUCCESS, channel);
}

Niels Möller's avatar
Niels Möller committed
139
140
141
142
143
struct lsh_string *format_channel_failure(UINT32 channel)
{
  return ssh_format("%c%i", SSH_MSG_CHANNEL_FAILURE, channel);
}

144
145
146
147
148
149
150
151
152
153
struct lsh_string *prepare_window_adjust(struct ssh_channel *channel,
					 UINT32 add)
{
  channel->rec_window_size += add;
  
  return ssh_format("%c%i%i",
		    SSH_MSG_CHANNEL_WINDOW_ADJUST,
		    channel->channel_number, add);
}

154
/* Channel objects */
Niels Möller's avatar
Niels Möller committed
155
156
157
158
159

#define INITIAL_CHANNELS 32
/* Arbitrary limit */
#define MAX_CHANNELS (1L<<17)

Niels Möller's avatar
Niels Möller committed
160
struct channel_table *make_channel_table(void)
Niels Möller's avatar
Niels Möller committed
161
{
162
  NEW(channel_table, table);
Niels Möller's avatar
Niels Möller committed
163

164
  table->channels = lsh_space_alloc(sizeof(struct ssh_channel *)
165
				      * INITIAL_CHANNELS);
166
167
168
169
  table->allocated_channels = INITIAL_CHANNELS;
  table->next_channel = 0;
  table->used_channels = 0;
  table->max_channels = MAX_CHANNELS;
Niels Möller's avatar
Niels Möller committed
170

Niels Möller's avatar
Niels Möller committed
171
172
  table->pending_close = 0;
  
173
  return table;
Niels Möller's avatar
Niels Möller committed
174
175
176
};

/* Returns -1 if allocation fails */
177
178
179
/* NOTE: This function returns locally chosen channel numbers, which
 * are always small integers. So there's no problem fitting them in
 * a signed int. */
180
int alloc_channel(struct channel_table *table)
Niels Möller's avatar
Niels Möller committed
181
{
182
  UINT32 i;
183
  
184
  for(i = table->next_channel; i < table->used_channels; i++)
Niels Möller's avatar
Niels Möller committed
185
    {
186
      if (!table->channels[i])
Niels Möller's avatar
Niels Möller committed
187
	{
188
	  table->next_channel = i+1;
Niels Möller's avatar
Niels Möller committed
189
190
191
	  return i;
	}
    }
192
  if (i == table->max_channels)
Niels Möller's avatar
Niels Möller committed
193
    return -1;
194

195
  if (i == table->allocated_channels) 
Niels Möller's avatar
Niels Möller committed
196
    {
197
      int new_size = table->allocated_channels * 2;
Niels Möller's avatar
Niels Möller committed
198
      struct ssh_channel **new
199
	= lsh_space_alloc(sizeof(struct ssh_channel *) * new_size);
Niels Möller's avatar
Niels Möller committed
200

201
202
      memcpy(new, table->channels,
	     sizeof(struct ssh_channel *) * table->used_channels);
Niels Möller's avatar
Niels Möller committed
203
      
204
205
      table->channels = new;
      table->allocated_channels = new_size;
Niels Möller's avatar
Niels Möller committed
206
207
    }

208
  table->next_channel = table->used_channels = i+1;
Niels Möller's avatar
Niels Möller committed
209
210
211
212

  return i;
}

213
void dealloc_channel(struct channel_table *table, int i)
Niels Möller's avatar
Niels Möller committed
214
215
{
  assert(i >= 0);
216
  assert( (unsigned) i < table->used_channels);
Niels Möller's avatar
Niels Möller committed
217
  
218
219
  table->channels[i] = NULL;

220
  if ( (unsigned) i < table->next_channel)
221
222
223
    table->next_channel = i;
}

224
225
/* Returns -1 if no channel number can be allocated. See also the note
 * for alloc_channel(). */
226
227
228
229
230
231
int register_channel(struct channel_table *table, struct ssh_channel *channel)
{
  int n = alloc_channel(table);

  if (n >= 0)
    table->channels[n] = channel;
Niels Möller's avatar
Niels Möller committed
232

233
  return n;
Niels Möller's avatar
Niels Möller committed
234
235
}

236
struct ssh_channel *lookup_channel(struct channel_table *table, UINT32 i)
Niels Möller's avatar
Niels Möller committed
237
{
238
239
  return (i < table->used_channels)
    ? table->channels[i] : NULL;
Niels Möller's avatar
Niels Möller committed
240
241
}

242
243
244
static int adjust_rec_window(struct ssh_channel *channel)
{
  if (channel->rec_window_size < channel->max_window / 2)
245
246
247
248
249
    return A_WRITE(channel->write,
		   prepare_window_adjust
		   (channel, channel->max_window - channel->rec_window_size));
  else
    return 0;
250
251
}

252
253
/* Process channel-related status codes. Used by the packet handlers,
 * before returning. */
Niels Möller's avatar
Niels Möller committed
254
255
256
257
static int channel_process_status(struct channel_table *table,
				  int channel,
				  int status)
{
258
259
260
261
  struct ssh_channel *c = table->channels[channel];
  
  while (!LSH_CLOSEDP(status))
    {
262
263
264
265
266
267
268
      if (status & LSH_CHANNEL_CLOSE)
	{ /* Close the channel now */ 
	  if (!c->flags & CHANNEL_SENT_CLOSE)
	    status |= channel_close(c);
	  break;
	}
      
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
      if (status & LSH_CHANNEL_READY_SEND)
	{
	  status &= ~ LSH_CHANNEL_READY_SEND;
	  if (c->send_window_size)
	    status |= CHANNEL_SEND(c);
	}
      else if (status & LSH_CHANNEL_READY_REC)
	{
	  status &= ~ LSH_CHANNEL_READY_REC;
	  status |= adjust_rec_window(c);
	}
      else
	break;
    }
	
Niels Möller's avatar
Niels Möller committed
284
285
286
287
  if (status & LSH_CHANNEL_FINISHED)
    {
      /* Clear this bit */
      status &= ~LSH_CHANNEL_FINISHED;
288

289
      if (c->close)
290
	status |= CHANNEL_CLOSE(c);
Niels Möller's avatar
Niels Möller committed
291
292
293
294
      
      dealloc_channel(table, channel);
    }

295
296
297
298
299
300
301
  if (status & LSH_CHANNEL_PENDING_CLOSE)
    table->pending_close = 1;
  
  /* If this was the last channel, close connection */
  if (table->pending_close && !table->next_channel)
    status |= LSH_CLOSE;

Niels Möller's avatar
Niels Möller committed
302
303
  return status;
}
Niels Möller's avatar
Niels Möller committed
304

305
306
307
308
309
310
311
/* Ugly macros to make it a little simpler to free the input packet at
 * the right time. */

#define START int foo_res
#define RETURN(x) do { foo_res = (x); goto foo_finish; } while(0)
#define END(s) foo_finish: do { lsh_string_free((s)); return foo_res; } while(0)

Niels Möller's avatar
Niels Möller committed
312
/* Channel related messages */
Niels Möller's avatar
Niels Möller committed
313
314
315
316
static int do_global_request(struct packet_handler *c,
			     struct ssh_connection *connection,
			     struct lsh_string *packet)
{
317
  CAST(global_request_handler, closure, c);
Niels Möller's avatar
Niels Möller committed
318
319

  struct simple_buffer buffer;
320
  unsigned msg_number;
Niels Möller's avatar
Niels Möller committed
321
322
  int name;
  int want_reply;
323
  START;
Niels Möller's avatar
Niels Möller committed
324
325
326
327
328
329
330
331
332
333
334
  
  simple_buffer_init(&buffer, packet->length, packet->data);

  if (parse_uint8(&buffer, &msg_number)
      && (msg_number == SSH_MSG_GLOBAL_REQUEST)
      && parse_atom(&buffer, &name)
      && parse_boolean(&buffer, &want_reply))
    {
      struct global_request *req;

      if (!name || !(req = ALIST_GET(closure->global_requests, name)))
335
336
	RETURN (A_WRITE(connection->write,
		       format_global_failure()));
Niels Möller's avatar
Niels Möller committed
337

338
      RETURN (GLOBAL_REQUEST(req, connection, want_reply, &buffer));
Niels Möller's avatar
Niels Möller committed
339
    }
340
  RETURN (LSH_FAIL | LSH_DIE);
Niels Möller's avatar
Niels Möller committed
341

342
  END (packet);
Niels Möller's avatar
Niels Möller committed
343
344
}

345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
/* Callback given to the CHANNEL_OPEN method */
static int do_channel_open_response(struct channel_open_callback *c,
                                    struct ssh_channel *channel,
                                    UINT32 error, char *error_msg,
                                    struct lsh_string *args)
{
  CAST(channel_open_response, closure, c);
  
  int local_channel_number;

  if (!channel)
    {
      if (error)
        return A_WRITE(closure->super.connection->write,
                       format_open_failure(closure->remote_channel_number,
                                           error, error_msg, ""));
        /* The request was invalid */
        return LSH_FAIL | LSH_DIE;
    }

  if ( (local_channel_number
            = register_channel(closure->super.connection->channels,
			       channel)) < 0)
    {
      werror("Could not allocate a channel number for opened channel!\n");
      return A_WRITE(closure->super.connection->write,
                     format_open_failure(closure->remote_channel_number,
                                         SSH_OPEN_RESOURCE_SHORTAGE,
                                         "Could not allocate a channel number "
                                         "(shouldn't happen...)", ""));
    }

  /* FIXME: This copying could just as wel be done by the
   * CHANNEL_OPEN handler? Then we can remove the corresponding fields
   * from the closure as well. */
  channel->send_window_size = closure->window_size;
  channel->send_max_packet = closure->max_packet;
  channel->channel_number = closure->remote_channel_number;

  /* FIXME: Is the channel->write field really needed? */
  channel->write = closure->super.connection->write;

  return A_WRITE(closure->super.connection->write,
                 args
                 ? format_open_confirmation(channel, local_channel_number,
                                            "%lfS", args)
                 : format_open_confirmation(channel, local_channel_number,
                                            ""));
}

static struct channel_open_response *
make_channel_open_response(struct ssh_connection* connection,
			   UINT32 remote_channel_number,
			   UINT32 window_size,
			   UINT32 max_packet)
{
  NEW(channel_open_response, closure);

  closure->super.response = do_channel_open_response;
  closure->super.connection = connection;
  closure->remote_channel_number = remote_channel_number;
  closure->window_size = window_size;
  closure->max_packet = max_packet;

  return closure;
}
411

412

413
414
415
416
417
418
419
420
421
422
423
#if 0
/* ;;GABA:
   (class
     (name channel_open_continuation)
     (super command_continuation)
     (vars
       (connection object ssh_connection)
       (remote_channel_number simple UINT32)
       (window_size simple UINT32)
       (max_packet simple UINT32)))
*/
424

425
426
427
428
429
430
431
432
static int do_channel_open_continue(struct command_continuation *c,
				    struct lsh_object *result)
{
  CAST(channel_open_continuation, self, c);
  CAST_SUBTYPE(channel);
}
#endif
				    
Niels Möller's avatar
Niels Möller committed
433
434
435
436
static int do_channel_open(struct packet_handler *c,
			   struct ssh_connection *connection,
			   struct lsh_string *packet)
{
437
  CAST(channel_open_handler, closure, c);
Niels Möller's avatar
Niels Möller committed
438
439

  struct simple_buffer buffer;
440
  unsigned msg_number;
Niels Möller's avatar
Niels Möller committed
441
  int type;
442
443
444
  UINT32 remote_channel_number;
  UINT32 window_size;
  UINT32 max_packet;
445
  START;
Niels Möller's avatar
Niels Möller committed
446
447
448
449
450
451
  
  simple_buffer_init(&buffer, packet->length, packet->data);

  if (parse_uint8(&buffer, &msg_number)
      && (msg_number == SSH_MSG_CHANNEL_OPEN)
      && parse_atom(&buffer, &type)
452
453
454
      && parse_uint32(&buffer, &remote_channel_number)
      && parse_uint32(&buffer, &window_size)
      && parse_uint32(&buffer, &max_packet))
Niels Möller's avatar
Niels Möller committed
455
456
    {
      struct channel_open *open;
457
458
      struct channel_open_response *response;
      int res;
459
      
460
      if (connection->channels->pending_close)
Niels Möller's avatar
Niels Möller committed
461
	/* We are waiting for channels to close. Don't open any new ones. */
462
463
464
465
466
	RETURN
	  (A_WRITE(connection->write,
		   format_open_failure(remote_channel_number,
				       SSH_OPEN_ADMINISTRATIVELY_PROHIBITED,
				       "Waiting for channels to close.", "")));
Niels Möller's avatar
Niels Möller committed
467
468
      
      if (!type || !(open = ALIST_GET(closure->channel_types, type)))
469
470
471
472
	RETURN (A_WRITE(connection->write,
			format_open_failure(remote_channel_number,
					    SSH_OPEN_UNKNOWN_CHANNEL_TYPE,
					    "Unknown channel type", "")));
473

474
475
476
477
478
479
480
481
      response = make_channel_open_response(connection,
					    remote_channel_number,
					    window_size, max_packet);
      /* NOTE: If the channel could be opened immediately, this method
       * will call response right away. */
      res = CHANNEL_OPEN(open, connection, &buffer, &response->super);

      RETURN (res);
Niels Möller's avatar
Niels Möller committed
482
    }
483
  RETURN (LSH_FAIL | LSH_DIE);
Niels Möller's avatar
Niels Möller committed
484

485
  END(packet);
Niels Möller's avatar
Niels Möller committed
486
487
}     

488
static int do_channel_request(struct packet_handler *closure UNUSED,
Niels Möller's avatar
Niels Möller committed
489
490
491
492
			      struct ssh_connection *connection,
			      struct lsh_string *packet)
{
  struct simple_buffer buffer;
493
  unsigned msg_number;
Niels Möller's avatar
Niels Möller committed
494
495
496
  UINT32 channel_number;
  int type;
  int want_reply;
497
498
  START;
  
Niels Möller's avatar
Niels Möller committed
499
500
501
502
503
504
505
506
  simple_buffer_init(&buffer, packet->length, packet->data);

  if (parse_uint8(&buffer, &msg_number)
      && (msg_number == SSH_MSG_CHANNEL_REQUEST)
      && parse_uint32(&buffer, &channel_number)
      && parse_atom(&buffer, &type)
      && parse_boolean(&buffer, &want_reply))
    {
507
      struct ssh_channel *channel = lookup_channel(connection->channels,
Niels Möller's avatar
Niels Möller committed
508
509
						   channel_number);

510
511
512
513
      /* NOTE: We can't free packet yet, because it is not yet fully
       * parsed. There may be some more arguments, which are parsed by
       * the CHANNEL_REQUEST method below. */

Niels Möller's avatar
Niels Möller committed
514
515
516
517
      if (channel)
	{
	  struct channel_request *req;

518
519
	  if (type && channel->request_types 
	      && ( (req = ALIST_GET(channel->request_types, type)) ))
520
521
522
523
	    RETURN
	      (channel_process_status
	       (connection->channels, channel_number,
		CHANNEL_REQUEST(req, channel, connection, want_reply, &buffer)));
524
	  else
525
526
527
528
	    RETURN (want_reply
		    ? A_WRITE(connection->write,
			      format_channel_failure(channel->channel_number))
		    : LSH_OK | LSH_GOON);
529
	  
Niels Möller's avatar
Niels Möller committed
530
	}
531
      werror("SSH_MSG_CHANNEL_REQUEST on nonexistant channel %i\n",
Niels Möller's avatar
Niels Möller committed
532
533
	     channel_number);

534
535
536
537
    }
  RETURN (LSH_FAIL | LSH_DIE);
  
  END(packet);
Niels Möller's avatar
Niels Möller committed
538
539
}
      
540
541
static int do_window_adjust(struct packet_handler *closure UNUSED,
			    struct ssh_connection *connection,
542
			    struct lsh_string *packet)
Niels Möller's avatar
Niels Möller committed
543
544
{
  struct simple_buffer buffer;
545
  unsigned msg_number;
Niels Möller's avatar
Niels Möller committed
546
547
548
549
550
551
552
  UINT32 channel_number;
  UINT32 size;

  simple_buffer_init(&buffer, packet->length, packet->data);

  if (parse_uint8(&buffer, &msg_number)
      && (msg_number == SSH_MSG_CHANNEL_WINDOW_ADJUST)
553
      && parse_uint32(&buffer, &channel_number)
Niels Möller's avatar
Niels Möller committed
554
555
556
      && parse_uint32(&buffer, &size)
      && parse_eod(&buffer))
    {
557
      struct ssh_channel *channel = lookup_channel(connection->channels,
Niels Möller's avatar
Niels Möller committed
558
559
560
561
						   channel_number);

      lsh_string_free(packet);
      
Niels Möller's avatar
Niels Möller committed
562
      if (channel
563
564
	  && !(channel->flags & (CHANNEL_RECEIVED_EOF
				 | CHANNEL_RECEIVED_CLOSE)))
Niels Möller's avatar
Niels Möller committed
565
	{
Niels Möller's avatar
Niels Möller committed
566
567
568
569
	  if (! (channel->flags & CHANNEL_SENT_CLOSE))
	    {
	      channel->send_window_size += size;
	      if (channel->send_window_size && channel->send)
570
		return channel_process_status(connection->channels,
Niels Möller's avatar
Niels Möller committed
571
572
					      channel_number,
					      CHANNEL_SEND(channel));
Niels Möller's avatar
Niels Möller committed
573
	    }
Niels Möller's avatar
Niels Möller committed
574
575
576
577
	  return LSH_OK | LSH_GOON;
	}
      /* FIXME: What to do now? Should unknown channel numbers be
       * ignored silently? */
578
579
      werror("SSH_MSG_CHANNEL_WINDOW_ADJUST on nonexistant or closed "
	     "channel %i\n", channel_number);
Niels Möller's avatar
Niels Möller committed
580
581
582
583
584
585
586
      return LSH_FAIL | LSH_DIE;
    }
  lsh_string_free(packet);

  return LSH_FAIL | LSH_DIE;
}

587
588
static int do_channel_data(struct packet_handler *closure UNUSED,
			   struct ssh_connection *connection,
Niels Möller's avatar
Niels Möller committed
589
590
591
			   struct lsh_string *packet)
{
  struct simple_buffer buffer;
592
  unsigned msg_number;
Niels Möller's avatar
Niels Möller committed
593
594
595
596
597
598
599
  UINT32 channel_number;
  struct lsh_string *data;
  
  simple_buffer_init(&buffer, packet->length, packet->data);

  if (parse_uint8(&buffer, &msg_number)
      && (msg_number == SSH_MSG_CHANNEL_DATA)
600
      && parse_uint32(&buffer, &channel_number)
Niels Möller's avatar
Niels Möller committed
601
602
603
      && ( (data = parse_string_copy(&buffer)) )
      && parse_eod(&buffer))
    {
604
      struct ssh_channel *channel = lookup_channel(connection->channels,
Niels Möller's avatar
Niels Möller committed
605
606
607
608
						   channel_number);

      lsh_string_free(packet);
      
609
      if (channel && channel->receive
610
611
	  && !(channel->flags & (CHANNEL_RECEIVED_EOF
				 | CHANNEL_RECEIVED_CLOSE)))
Niels Möller's avatar
Niels Möller committed
612
	{
Niels Möller's avatar
Niels Möller committed
613
	  if (channel->flags & CHANNEL_SENT_CLOSE)
Niels Möller's avatar
Niels Möller committed
614
	    {
615
	      werror("Ignoring data on channel which is closing\n");
Niels Möller's avatar
Niels Möller committed
616
	      return LSH_OK | LSH_GOON;
Niels Möller's avatar
Niels Möller committed
617
	    }
Niels Möller's avatar
Niels Möller committed
618
619
	  else
	    {
620
621
	      int res = 0;
	      
Niels Möller's avatar
Niels Möller committed
622
623
624
	      if (data->length > channel->rec_window_size)
		{
		  /* Truncate data to fit window */
625
		  werror("Channel data overflow. Extra data ignored.\n"); 
Niels Möller's avatar
Niels Möller committed
626
627
		  data->length = channel->rec_window_size;
		}
628
629
630
631

	      if (!data->length)
		/* Ignore data packet */
		return 0;
632
633
	      channel->rec_window_size -= data->length;

634
	      /* FIXME: Unconditionally adjusting the receive window
635
	       * breaks flow control. We better let the channel's
636
	       * receive method decide whether or not to receive more
637
638
639
	       * data. */
	      res = adjust_rec_window(channel);
	      
640
641
	      if (LSH_CLOSEDP(res))
		return res;
642

Niels Möller's avatar
Niels Möller committed
643
	      return channel_process_status(
644
		connection->channels, channel_number,
645
		res | CHANNEL_RECEIVE(channel, 
Niels Möller's avatar
Niels Möller committed
646
				      CHANNEL_DATA, data));
Niels Möller's avatar
Niels Möller committed
647
648
	    }
	  return LSH_OK | LSH_GOON;
Niels Möller's avatar
Niels Möller committed
649
650
	}
	  
651
      werror("Data on closed or non-existant channel %i\n",
Niels Möller's avatar
Niels Möller committed
652
653
654
655
656
657
658
659
660
	     channel_number);
      lsh_string_free(data);
      return LSH_FAIL | LSH_DIE;
    }
  lsh_string_free(packet);
  
  return LSH_FAIL | LSH_DIE;
}

661
662
static int do_channel_extended_data(struct packet_handler *closure UNUSED,
				    struct ssh_connection *connection,
Niels Möller's avatar
Niels Möller committed
663
664
665
				    struct lsh_string *packet)
{
  struct simple_buffer buffer;
666
  unsigned msg_number;
Niels Möller's avatar
Niels Möller committed
667
668
669
670
671
672
673
674
  UINT32 channel_number;
  UINT32 type;
  struct lsh_string *data;
  
  simple_buffer_init(&buffer, packet->length, packet->data);

  if (parse_uint8(&buffer, &msg_number)
      && (msg_number == SSH_MSG_CHANNEL_EXTENDED_DATA)
675
      && parse_uint32(&buffer, &channel_number)
Niels Möller's avatar
Niels Möller committed
676
677
678
679
      && parse_uint32(&buffer, &type)
      && ( (data = parse_string_copy(&buffer)) )
      && parse_eod(&buffer))
    {
680
      struct ssh_channel *channel = lookup_channel(connection->channels,
Niels Möller's avatar
Niels Möller committed
681
682
683
684
						   channel_number);

      lsh_string_free(packet);
      
685
      if (channel && channel->receive
686
687
	  && !(channel->flags & (CHANNEL_RECEIVED_EOF
				 | CHANNEL_RECEIVED_CLOSE)))
Niels Möller's avatar
Niels Möller committed
688
	{
Niels Möller's avatar
Niels Möller committed
689
	  if (channel->flags & CHANNEL_SENT_CLOSE)
Niels Möller's avatar
Niels Möller committed
690
	    {
691
	      werror("Ignoring extended data on channel which is closing\n");
Niels Möller's avatar
Niels Möller committed
692
	      return LSH_OK | LSH_GOON;
Niels Möller's avatar
Niels Möller committed
693
	    }
Niels Möller's avatar
Niels Möller committed
694
	  else
Niels Möller's avatar
Niels Möller committed
695
	    {
696
697
	      int res = 0;
	      
Niels Möller's avatar
Niels Möller committed
698
699
700
	      if (data->length > channel->rec_window_size)
		{
		  /* Truncate data to fit window */
701
		  werror("Channel extended data overflow. "
Niels Möller's avatar
Niels Möller committed
702
703
704
705
706
			 "Extra data ignored.\n");
		  data->length = channel->rec_window_size;
		}
	      
	      channel->rec_window_size -= data->length;
707

708
709
710
711
712
713
	      /* FIXME: Like for do_channel_data(), unconditionally
	       * adjusting the window breaks flow control. */
	      res = adjust_rec_window(channel);

	      if (LSH_CLOSEDP(res))
		return res;
714

Niels Möller's avatar
Niels Möller committed
715
716
717
	      switch(type)
		{
		case SSH_EXTENDED_DATA_STDERR:
Niels Möller's avatar
Niels Möller committed
718
		  return channel_process_status(
719
		    connection->channels, channel_number,
720
		    res | CHANNEL_RECEIVE(channel, 
Niels Möller's avatar
Niels Möller committed
721
					  CHANNEL_STDERR_DATA, data));
Niels Möller's avatar
Niels Möller committed
722
		default:
723
		  werror("Unknown type %i of extended data.\n",
Niels Möller's avatar
Niels Möller committed
724
725
726
727
			 type);
		  lsh_string_free(data);
		  return LSH_FAIL | LSH_DIE;
		}
Niels Möller's avatar
Niels Möller committed
728
729
	    }
	}
730
      werror("Extended data on closed or non-existant channel %i\n",
Niels Möller's avatar
Niels Möller committed
731
732
733
734
735
736
737
738
739
	     channel_number);
      lsh_string_free(data);
      return LSH_FAIL | LSH_DIE;
    }
  lsh_string_free(packet);
  
  return LSH_FAIL | LSH_DIE;
}

740
741
static int do_channel_eof(struct packet_handler *closure UNUSED,
			  struct ssh_connection *connection,
742
			  struct lsh_string *packet)
Niels Möller's avatar
Niels Möller committed
743
744
{
  struct simple_buffer buffer;
745
  unsigned msg_number;
Niels Möller's avatar
Niels Möller committed
746
747
748
749
750
751
  UINT32 channel_number;
  
  simple_buffer_init(&buffer, packet->length, packet->data);

  if (parse_uint8(&buffer, &msg_number)
      && (msg_number == SSH_MSG_CHANNEL_EOF)
752
      && parse_uint32(&buffer, &channel_number)
Niels Möller's avatar
Niels Möller committed
753
754
      && parse_eod(&buffer))
    {
755
      struct ssh_channel *channel = lookup_channel(connection->channels,
Niels Möller's avatar
Niels Möller committed
756
757
758
759
						   channel_number);

      lsh_string_free(packet);

Niels Möller's avatar
Niels Möller committed
760
761
      if (channel)
	{
762
763
	  int res = 0;
	  
764
	  if (channel->flags & (CHANNEL_RECEIVED_EOF | CHANNEL_RECEIVED_CLOSE))
Niels Möller's avatar
Niels Möller committed
765
	    {
766
	      werror("Receiving EOF on channel on closed channel.\n");
Niels Möller's avatar
Niels Möller committed
767
768
769
	      return LSH_FAIL | LSH_DIE;
	    }

770
	  channel->flags |= CHANNEL_RECEIVED_EOF;
Niels Möller's avatar
Niels Möller committed
771

772
773
	  if (channel->eof)
	    res = CHANNEL_EOF(channel);
774
775
776
	  else
	    /* FIXME: What is a reasonable default behaviour?
	     * Closing the channel may be the right thing to do. */
777
778
779
	    if (! (channel->flags & CHANNEL_SENT_CLOSE))
	      res |= channel_close(channel);
#if 0
780
781
782
	  if (!LSH_CLOSEDP(res)
	      && ! (channel->flags & CHANNEL_SENT_CLOSE)
	      && (channel->flags & CHANNEL_SENT_EOF))
Niels Möller's avatar
Niels Möller committed
783
784
785
	    {
	      /* Both parties have sent EOF. Initiate close, if we
	       * havn't done that already. */
786
787
	      
	      res |= channel_close(channel);
Niels Möller's avatar
Niels Möller committed
788
	    }
789
#endif      
790
	  return channel_process_status(connection->channels, channel_number,
791
792
					res);

Niels Möller's avatar
Niels Möller committed
793
	}
794
      werror("EOF on non-existant channel %i\n",
Niels Möller's avatar
Niels Möller committed
795
796
	     channel_number);
      return LSH_FAIL | LSH_DIE;
Niels Möller's avatar
Niels Möller committed
797
    }
Niels Möller's avatar
Niels Möller committed
798
      
Niels Möller's avatar
Niels Möller committed
799
800
801
802
  lsh_string_free(packet);
  return LSH_FAIL | LSH_DIE;
}

803
804
static int do_channel_close(struct packet_handler *closure UNUSED,
			    struct ssh_connection *connection,
Niels Möller's avatar
Niels Möller committed
805
806
807
			    struct lsh_string *packet)
{
  struct simple_buffer buffer;
808
  unsigned msg_number;
Niels Möller's avatar
Niels Möller committed
809
810
811
812
813
814
  UINT32 channel_number;
  
  simple_buffer_init(&buffer, packet->length, packet->data);

  if (parse_uint8(&buffer, &msg_number)
      && (msg_number == SSH_MSG_CHANNEL_CLOSE)
815
      && parse_uint32(&buffer, &channel_number)
Niels Möller's avatar
Niels Möller committed
816
817
      && parse_eod(&buffer))
    {
818
      struct ssh_channel *channel = lookup_channel(connection->channels,
Niels Möller's avatar
Niels Möller committed
819
820
821
822
						   channel_number);

      lsh_string_free(packet);
      
Niels Möller's avatar
Niels Möller committed
823
824
      if (channel)
	{
825
826
	  int res = 0;
	  
827
	  if (channel->flags & CHANNEL_RECEIVED_CLOSE)
Niels Möller's avatar
Niels Möller committed
828
	    {
829
	      werror("Receiving multiple CLOSE on channel.\n");
Niels Möller's avatar
Niels Möller committed
830
831
832
	      return LSH_FAIL | LSH_DIE;
	    }

833
	  channel->flags |= CHANNEL_RECEIVED_CLOSE;
Niels Möller's avatar
Niels Möller committed
834
	  
835
	  if (! (channel->flags & (CHANNEL_RECEIVED_EOF | CHANNEL_SENT_EOF)))
Niels Möller's avatar
Niels Möller committed
836
	    {
837
	      werror("Unexpected channel CLOSE.\n");
Niels Möller's avatar
Niels Möller committed
838
	    }
839

840
	  if (! (channel->flags & (CHANNEL_RECEIVED_EOF))
841
	      && channel->eof)
842
	    res = CHANNEL_EOF(channel);
Niels Möller's avatar
Niels Möller committed
843
	  
Niels Möller's avatar
Niels Möller committed
844
	  return channel_process_status(
845
	    connection->channels, channel_number,
846
847
848
849
	    ( ( (channel->flags & (CHANNEL_SENT_CLOSE))
		? LSH_OK | LSH_CHANNEL_FINISHED
		: channel_close(channel))
	      | res));
Niels Möller's avatar
Niels Möller committed
850
	}
851
      werror("CLOSE on non-existant channel %i\n",
Niels Möller's avatar
Niels Möller committed
852
853
	     channel_number);
      return LSH_FAIL | LSH_DIE;
Niels Möller's avatar
Niels Möller committed
854
855
856
857
858
859
      
    }
  lsh_string_free(packet);
  return LSH_FAIL | LSH_DIE;
}

860
static int do_channel_open_confirm(struct packet_handler *closure UNUSED,
Niels Möller's avatar
Niels Möller committed
861
862
				   struct ssh_connection *connection,
				   struct lsh_string *packet)
Niels Möller's avatar
Niels Möller committed
863
864
{
  struct simple_buffer buffer;
865
  unsigned msg_number;
Niels Möller's avatar
Niels Möller committed
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
  UINT32 local_channel_number;
  UINT32 remote_channel_number;  
  UINT32 window_size;
  UINT32 max_packet;
  
  simple_buffer_init(&buffer, packet->length, packet->data);

  if (parse_uint8(&buffer, &msg_number)
      && (msg_number == SSH_MSG_CHANNEL_OPEN_CONFIRMATION)
      && parse_uint32(&buffer, &local_channel_number)
      && parse_uint32(&buffer, &remote_channel_number)
      && parse_uint32(&buffer, &window_size)
      && parse_uint32(&buffer, &max_packet)
      && parse_eod(&buffer))
    {
881
      struct ssh_channel *channel = lookup_channel(connection->channels,
Niels Möller's avatar
Niels Möller committed
882
883
884
885
						   local_channel_number);

      lsh_string_free(packet);

886
      if (channel && channel->open_continuation)
Niels Möller's avatar
Niels Möller committed
887
888
889
890
891
	{
	  channel->channel_number = remote_channel_number;
	  channel->send_window_size = window_size;
	  channel->send_max_packet = max_packet;

892
893
894
895
	  return channel_process_status
	    (connection->channels,
	     local_channel_number,
	     COMMAND_RETURN(channel->open_continuation, channel));
Niels Möller's avatar
Niels Möller committed
896
	}
897
      werror("Unexpected SSH_MSG_CHANNEL_OPEN_CONFIRMATION on channel %i\n",
Niels Möller's avatar
Niels Möller committed
898
899
900
901
902
903
904
	     local_channel_number);
      return LSH_FAIL | LSH_DIE;
    }
  lsh_string_free(packet);
  return LSH_FAIL | LSH_DIE;
}

905
906
static int do_channel_open_failure(struct packet_handler *closure UNUSED,
			      struct ssh_connection *connection,
Niels Möller's avatar
Niels Möller committed
907
908
909
			      struct lsh_string *packet)
{
  struct simple_buffer buffer;
910
  unsigned msg_number;
Niels Möller's avatar
Niels Möller committed
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
  UINT32 channel_number;
  UINT32 reason;

  UINT8 *msg;
  UINT32 length;

  UINT8 *language;
  UINT32 language_length;
  
  simple_buffer_init(&buffer, packet->length, packet->data);

  if (parse_uint8(&buffer, &msg_number)
      && (msg_number == SSH_MSG_CHANNEL_OPEN_FAILURE)
      && parse_uint32(&buffer, &channel_number)
      && parse_uint32(&buffer, &reason)
      && parse_string(&buffer, &length, &msg)
      && parse_string(&buffer, &language_length, &language)
      && parse_eod(&buffer))
    {
930
      struct ssh_channel *channel = lookup_channel(connection->channels,
Niels Möller's avatar
Niels Möller committed
931
932
933
934
						   channel_number);

      /* lsh_string_free(packet); */

935
      if (channel && channel->open_continuation)
Niels Möller's avatar
Niels Möller committed
936
	{
937
	  int res = COMMAND_RETURN(channel->open_continuation, NULL);
Niels Möller's avatar
Niels Möller committed
938
939

	  lsh_string_free(packet);
Niels Möller's avatar
Niels Möller committed
940

941
	  return channel_process_status(connection->channels, channel_number,
Niels Möller's avatar
Niels Möller committed
942
					res | LSH_CHANNEL_FINISHED);
Niels Möller's avatar
Niels Möller committed
943
	}
944
      werror("Unexpected SSH_MSG_CHANNEL_OPEN_FAILURE on channel %i\n",
Niels Möller's avatar
Niels Möller committed
945
946
947
948
949
950
951
952
953
	     channel_number);
      lsh_string_free(packet);
      
      return LSH_FAIL | LSH_DIE;
    }
  lsh_string_free(packet);
  return LSH_FAIL | LSH_DIE;
}

954
955
static int do_channel_success(struct packet_handler *closure UNUSED,
			      struct ssh_connection *connection,
956
957
958
			      struct lsh_string *packet)
{
  struct simple_buffer buffer;
959
  unsigned msg_number;
960
  UINT32 channel_number;
961
962
  struct ssh_channel *channel;
      
963
964
965
966
  simple_buffer_init(&buffer, packet->length, packet->data);

  if (parse_uint8(&buffer, &msg_number)
      && (msg_number == SSH_MSG_CHANNEL_SUCCESS)
967
      && parse_uint32(&buffer, &channel_number)
968
      && parse_eod(&buffer)
969
      && (channel = lookup_channel(connection->channels, channel_number)))
970
971
    {
      lsh_string_free(packet);
972

973
      if (object_queue_is_empty(&channel->pending_requests))
974
	{
975
	  werror("do_channel_success: Unexpected message. Ignoring.\n");
976
977
	  return LSH_OK | LSH_GOON;
	}
978
      {
Niels Möller's avatar
Niels Möller committed
979
	CAST_SUBTYPE(command_continuation, c,
980
981
982
983
	     object_queue_remove_head(&channel->pending_requests));
	return channel_process_status(connection->channels, channel_number,
				      COMMAND_RETURN(c, channel));
      }
984
985
986
987
988
    }
  lsh_string_free(packet);
  return LSH_FAIL | LSH_DIE;
}

989
990
static int do_channel_failure(struct packet_handler *closure UNUSED,
			      struct ssh_connection *connection,
991
992
993
			      struct lsh_string *packet)
{
  struct simple_buffer buffer;
994
  unsigned msg_number;
995
  UINT32 channel_number;
996
  struct ssh_channel *channel;
997
998
999
1000
1001
  
  simple_buffer_init(&buffer, packet->length, packet->data);

  if (parse_uint8(&buffer, &msg_number)
      && (msg_number == SSH_MSG_CHANNEL_FAILURE)
1002
      && parse_uint32(&buffer, &channel_number)
1003
      && parse_eod(&buffer)
1004
      && (channel = lookup_channel(connection->channels, channel_number)))
1005
1006
1007
    {
      lsh_string_free(packet);
      
1008
      if (object_queue_is_empty(&channel->pending_requests))
1009
1010
1011
1012
	{
	  werror("do_channel_failure: No handler. Ignoring.\n");
	  return LSH_OK | LSH_GOON;
	}
1013
      {
Niels Möller's avatar
Niels Möller committed
1014
	CAST_SUBTYPE(command_continuation, c,
1015
1016
1017
1018
1019
	     object_queue_remove_head(&channel->pending_requests));

	return channel_process_status(connection->channels, channel_number,
				      COMMAND_RETURN(c, NULL));
      }
1020
1021
1022
1023
1024
    }
  lsh_string_free(packet);
  return LSH_FAIL | LSH_DIE;
}

1025
1026
1027
static int do_connection_service(struct command *s,
				 struct lsh_object *x,
				 struct command_continuation *c)
Niels Möller's avatar
Niels Möller committed
1028
{
1029
  CAST(connection_service, self, s);
1030
  CAST(ssh_connection, connection, x);
1031

1032
  struct channel_table *table;
Niels Möller's avatar
Niels Möller committed
1033
  
1034
1035
  NEW(global_request_handler, globals);
  NEW(channel_open_handler, open);
1036
  NEW(packet_handler, request);
Niels Möller's avatar
Niels Möller committed
1037

1038
1039
1040
  NEW(packet_handler, adjust);
  NEW(packet_handler, data);
  NEW(packet_handler, extended);
Niels Möller's avatar
Niels Möller committed
1041

1042
1043
  NEW(packet_handler, eof);
  NEW(packet_handler, close);
1044

1045
1046
  NEW(packet_handler, open_confirm);
  NEW(packet_handler, open_failure);
Niels Möller's avatar
Niels Möller committed
1047

1048
1049
  NEW(packet_handler, channel_success);
  NEW(packet_handler, channel_failure);
Niels Möller's avatar
Niels Möller committed
1050

1051
  table = make_channel_table();
Niels Möller's avatar
Niels Möller committed
1052
  
1053
1054
1055
  connection->channels = table;
  
  globals->super.handler = do_global_request;
Niels Möller's avatar
Niels Möller committed
1056
  globals->global_requests = self->global_requests;
1057
  connection->dispatch[SSH_MSG_GLOBAL_REQUEST] = &globals->super;
Niels Möller's avatar
Niels Möller committed
1058
    
1059
  open->super.handler = do_channel_open;
Niels Möller's avatar
Niels Möller committed
1060
  open->channel_types = self->channel_types;
1061
  connection->dispatch[SSH_MSG_CHANNEL_OPEN] = &open->super;
Niels Möller's avatar
Niels Möller committed
1062

1063
1064
  request->handler = do_channel_request;
  connection->dispatch[SSH_MSG_CHANNEL_REQUEST] = request;
Niels Möller's avatar
Niels Möller committed
1065
  
1066
1067
  adjust->handler = do_window_adjust;
  connection->dispatch[SSH_MSG_CHANNEL_WINDOW_ADJUST] = adjust;
Niels Möller's avatar
Niels Möller committed
1068

1069
1070
  data->handler = do_channel_data;
  connection->dispatch[SSH_MSG_CHANNEL_DATA] = data;
Niels Möller's avatar
Niels Möller committed
1071

1072
1073
  extended->handler = do_channel_extended_data;
  connection->dispatch[SSH_MSG_CHANNEL_EXTENDED_DATA] = extended;
Niels Möller's avatar
Niels Möller committed
1074

1075
1076
  eof->handler = do_channel_eof;
  connection->dispatch[SSH_MSG_CHANNEL_EOF] = eof;
Niels Möller's avatar
Niels Möller committed
1077

1078
1079
  close->handler = do_channel_close;
  connection->dispatch[SSH_MSG_CHANNEL_CLOSE] = close;
Niels Möller's avatar
Niels Möller committed
1080

1081
1082
  open_confirm->handler = do_channel_open_confirm;
  connection->dispatch[SSH_MSG_CHANNEL_OPEN_CONFIRMATION] = open_confirm;
Niels Möller's avatar
Niels Möller committed
1083

1084
1085
  open_failure->handler = do_channel_open_failure;
  connection->dispatch[SSH_MSG_CHANNEL_OPEN_FAILURE] = open_failure;
Niels Möller's avatar
Niels Möller committed
1086
  
1087
1088
  channel_success->handler = do_channel_success;
  connection->dispatch[SSH_MSG_CHANNEL_SUCCESS] = channel_success;
1089

1090
1091
  channel_failure->handler = do_channel_failure;
  connection->dispatch[SSH_MSG_CHANNEL_FAILURE] = channel_failure;
Niels Möller's avatar