channel.c 35.6 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
35
#include "service.h"
#include "ssh.h"
#include "werror.h"
#include "xalloc.h"

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

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

42
43
#include "channel.c.x"

44
/* GABA:
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
   (class
     (name connection_service)
     (super ssh_service)
     (vars
       ; Supported global requests 
       (global_requests object alist)

       (channel_types object alist)

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

       (start object connection_startup)))
*/

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

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

76
/* GABA:
77
78
79
80
81
82
83
84
85
   (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
86
87
88
89
90
struct lsh_string *format_global_failure(void)
{
  return ssh_format("%c", SSH_MSG_REQUEST_FAILURE);
}

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

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

#define CONFIRM_FORMAT "%c%i%i%i%i"
105
106
#define CONFIRM_ARGS \
  SSH_MSG_CHANNEL_OPEN_CONFIRMATION, channel->channel_number, \
107
108
109
110
111
112
113
114
115
116
117
118
119
  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);
120
  ssh_vformat_write(format, l2, packet->data+l1, args);
121
122
123
124
125
126
127
  va_end(args);

  return packet;
#undef CONFIRM_FORMAT
#undef CONFIRM_ARGS
}

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

135
136
137
138
139
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
140
141
142
143
144
struct lsh_string *format_channel_failure(UINT32 channel)
{
  return ssh_format("%c%i", SSH_MSG_CHANNEL_FAILURE, channel);
}

145
146
147
148
149
150
151
152
153
154
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);
}

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

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

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

165
  table->channels = lsh_space_alloc(sizeof(struct ssh_channel *)
166
				      * INITIAL_CHANNELS);
167
168
169
170
  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
171

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

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

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

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

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

  return i;
}

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

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

225
226
/* Returns -1 if no channel number can be allocated. See also the note
 * for alloc_channel(). */
227
228
229
230
231
232
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
233

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

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

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

256
257
/* Process channel-related status codes. Used by the packet handlers,
 * before returning. */
Niels Möller's avatar
Niels Möller committed
258
259
260
261
static int channel_process_status(struct channel_table *table,
				  int channel,
				  int status)
{
262
263
264
265
  struct ssh_channel *c = table->channels[channel];
  
  while (!LSH_CLOSEDP(status))
    {
266
267
268
269
270
271
272
      if (status & LSH_CHANNEL_CLOSE)
	{ /* Close the channel now */ 
	  if (!c->flags & CHANNEL_SENT_CLOSE)
	    status |= channel_close(c);
	  break;
	}
      
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
      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
288
289
290
291
292
293
294
  if (status & LSH_CHANNEL_PENDING_CLOSE)
    table->pending_close = 1;
  
  if (status & LSH_CHANNEL_FINISHED)
    {
      /* Clear this bit */
      status &= ~LSH_CHANNEL_FINISHED;
295

296
297
      if (c->close)
	CHANNEL_CLOSE(c);
Niels Möller's avatar
Niels Möller committed
298
299
300
301
302
303
304
305
306
307
      
      dealloc_channel(table, channel);

      /* If this was the last channel, close connection */
      if (table->pending_close && !table->next_channel)
	status |= LSH_CLOSE;
    }

  return status;
}
Niels Möller's avatar
Niels Möller committed
308

309
310
311
312
313
314
315
/* 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
316
/* Channel related messages */
Niels Möller's avatar
Niels Möller committed
317
318
319
320
static int do_global_request(struct packet_handler *c,
			     struct ssh_connection *connection,
			     struct lsh_string *packet)
{
321
  CAST(global_request_handler, closure, c);
Niels Möller's avatar
Niels Möller committed
322
323

  struct simple_buffer buffer;
324
  unsigned msg_number;
Niels Möller's avatar
Niels Möller committed
325
326
  int name;
  int want_reply;
327
  START;
Niels Möller's avatar
Niels Möller committed
328
329
330
331
332
333
334
335
336
337
338
  
  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)))
339
340
	RETURN (A_WRITE(connection->write,
		       format_global_failure()));
Niels Möller's avatar
Niels Möller committed
341

342
      RETURN (GLOBAL_REQUEST(req, connection, want_reply, &buffer));
Niels Möller's avatar
Niels Möller committed
343
    }
344
  RETURN (LSH_FAIL | LSH_DIE);
Niels Möller's avatar
Niels Möller committed
345

346
  END (packet);
Niels Möller's avatar
Niels Möller committed
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
411
412
413
414
415
416
/* 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;
}


Niels Möller's avatar
Niels Möller committed
417
418
419
420
static int do_channel_open(struct packet_handler *c,
			   struct ssh_connection *connection,
			   struct lsh_string *packet)
{
421
  CAST(channel_open_handler, closure, c);
Niels Möller's avatar
Niels Möller committed
422
423

  struct simple_buffer buffer;
424
  unsigned msg_number;
Niels Möller's avatar
Niels Möller committed
425
  int type;
426
427
428
  UINT32 remote_channel_number;
  UINT32 window_size;
  UINT32 max_packet;
429
  START;
Niels Möller's avatar
Niels Möller committed
430
431
432
433
434
435
  
  simple_buffer_init(&buffer, packet->length, packet->data);

  if (parse_uint8(&buffer, &msg_number)
      && (msg_number == SSH_MSG_CHANNEL_OPEN)
      && parse_atom(&buffer, &type)
436
437
438
      && 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
439
440
    {
      struct channel_open *open;
441
442
      struct channel_open_response *response;
      int res;
443
      
444
      if (connection->channels->pending_close)
Niels Möller's avatar
Niels Möller committed
445
	/* We are waiting for channels to close. Don't open any new ones. */
446
447
448
449
450
	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
451
452
      
      if (!type || !(open = ALIST_GET(closure->channel_types, type)))
453
454
455
456
	RETURN (A_WRITE(connection->write,
			format_open_failure(remote_channel_number,
					    SSH_OPEN_UNKNOWN_CHANNEL_TYPE,
					    "Unknown channel type", "")));
457

458
459
460
461
462
463
464
465
      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
466
    }
467
  RETURN (LSH_FAIL | LSH_DIE);
Niels Möller's avatar
Niels Möller committed
468

469
  END(packet);
Niels Möller's avatar
Niels Möller committed
470
471
}     

472
static int do_channel_request(struct packet_handler *closure UNUSED,
Niels Möller's avatar
Niels Möller committed
473
474
475
476
			      struct ssh_connection *connection,
			      struct lsh_string *packet)
{
  struct simple_buffer buffer;
477
  unsigned msg_number;
Niels Möller's avatar
Niels Möller committed
478
479
480
  UINT32 channel_number;
  int type;
  int want_reply;
481
482
  START;
  
Niels Möller's avatar
Niels Möller committed
483
484
485
486
487
488
489
490
  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))
    {
491
      struct ssh_channel *channel = lookup_channel(connection->channels,
Niels Möller's avatar
Niels Möller committed
492
493
						   channel_number);

494
495
496
497
      /* 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
498
499
500
501
      if (channel)
	{
	  struct channel_request *req;

502
503
	  if (type && channel->request_types 
	      && ( (req = ALIST_GET(channel->request_types, type)) ))
504
505
506
507
	    RETURN
	      (channel_process_status
	       (connection->channels, channel_number,
		CHANNEL_REQUEST(req, channel, connection, want_reply, &buffer)));
508
	  else
509
510
511
512
	    RETURN (want_reply
		    ? A_WRITE(connection->write,
			      format_channel_failure(channel->channel_number))
		    : LSH_OK | LSH_GOON);
513
	  
Niels Möller's avatar
Niels Möller committed
514
	}
515
      werror("SSH_MSG_CHANNEL_REQUEST on nonexistant channel %i\n",
Niels Möller's avatar
Niels Möller committed
516
517
	     channel_number);

518
519
520
521
    }
  RETURN (LSH_FAIL | LSH_DIE);
  
  END(packet);
Niels Möller's avatar
Niels Möller committed
522
523
}
      
524
525
static int do_window_adjust(struct packet_handler *closure UNUSED,
			    struct ssh_connection *connection,
526
			    struct lsh_string *packet)
Niels Möller's avatar
Niels Möller committed
527
528
{
  struct simple_buffer buffer;
529
  unsigned msg_number;
Niels Möller's avatar
Niels Möller committed
530
531
532
533
534
535
536
  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)
537
      && parse_uint32(&buffer, &channel_number)
Niels Möller's avatar
Niels Möller committed
538
539
540
      && parse_uint32(&buffer, &size)
      && parse_eod(&buffer))
    {
541
      struct ssh_channel *channel = lookup_channel(connection->channels,
Niels Möller's avatar
Niels Möller committed
542
543
544
545
						   channel_number);

      lsh_string_free(packet);
      
Niels Möller's avatar
Niels Möller committed
546
      if (channel
547
548
	  && !(channel->flags & (CHANNEL_RECEIVED_EOF
				 | CHANNEL_RECEIVED_CLOSE)))
Niels Möller's avatar
Niels Möller committed
549
	{
Niels Möller's avatar
Niels Möller committed
550
551
552
553
	  if (! (channel->flags & CHANNEL_SENT_CLOSE))
	    {
	      channel->send_window_size += size;
	      if (channel->send_window_size && channel->send)
554
		return channel_process_status(connection->channels,
Niels Möller's avatar
Niels Möller committed
555
556
					      channel_number,
					      CHANNEL_SEND(channel));
Niels Möller's avatar
Niels Möller committed
557
	    }
Niels Möller's avatar
Niels Möller committed
558
559
560
561
	  return LSH_OK | LSH_GOON;
	}
      /* FIXME: What to do now? Should unknown channel numbers be
       * ignored silently? */
562
      werror("SSH_MSG_CHANNEL_WINDOW_ADJUST on nonexistant or closed channel %i\n",
Niels Möller's avatar
Niels Möller committed
563
564
565
566
567
568
569
570
	     channel_number);
      return LSH_FAIL | LSH_DIE;
    }
  lsh_string_free(packet);

  return LSH_FAIL | LSH_DIE;
}

571
572
static int do_channel_data(struct packet_handler *closure UNUSED,
			   struct ssh_connection *connection,
Niels Möller's avatar
Niels Möller committed
573
574
575
			   struct lsh_string *packet)
{
  struct simple_buffer buffer;
576
  unsigned msg_number;
Niels Möller's avatar
Niels Möller committed
577
578
579
580
581
582
583
  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)
584
      && parse_uint32(&buffer, &channel_number)
Niels Möller's avatar
Niels Möller committed
585
586
587
      && ( (data = parse_string_copy(&buffer)) )
      && parse_eod(&buffer))
    {
588
      struct ssh_channel *channel = lookup_channel(connection->channels,
Niels Möller's avatar
Niels Möller committed
589
590
591
592
						   channel_number);

      lsh_string_free(packet);
      
593
594
      if (channel && channel->receive
	  && !(channel->flags & (CHANNEL_RECEIVED_EOF | CHANNEL_RECEIVED_CLOSE)))
Niels Möller's avatar
Niels Möller committed
595
	{
Niels Möller's avatar
Niels Möller committed
596
	  if (channel->flags & CHANNEL_SENT_CLOSE)
Niels Möller's avatar
Niels Möller committed
597
	    {
598
	      werror("Ignoring data on channel which is closing\n");
Niels Möller's avatar
Niels Möller committed
599
	      return LSH_OK | LSH_GOON;
Niels Möller's avatar
Niels Möller committed
600
	    }
Niels Möller's avatar
Niels Möller committed
601
602
	  else
	    {
603
604
	      int res = 0;
	      
Niels Möller's avatar
Niels Möller committed
605
606
607
	      if (data->length > channel->rec_window_size)
		{
		  /* Truncate data to fit window */
608
		  werror("Channel data overflow. Extra data ignored.\n"); 
Niels Möller's avatar
Niels Möller committed
609
610
		  data->length = channel->rec_window_size;
		}
611
612
613
614

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

617
	      /* FIXME: Unconditionally adjusting the receive window
618
	       * breaks flow control. We better let the channel's
619
	       * receive method decide whether or not to receive more
620
621
622
	       * data. */
	      res = adjust_rec_window(channel);
	      
623
624
625
626
627
628
629
630
631
	      if (channel->rec_window_size < channel->max_window / 2)
		{
		  res = A_WRITE(channel->write, prepare_window_adjust
				(channel,
				 channel->max_window - channel->rec_window_size));
		  if (LSH_CLOSEDP(res))
		    return res;
		}

Niels Möller's avatar
Niels Möller committed
632
	      return channel_process_status(
633
		connection->channels, channel_number,
634
		res | CHANNEL_RECEIVE(channel, 
Niels Möller's avatar
Niels Möller committed
635
				      CHANNEL_DATA, data));
Niels Möller's avatar
Niels Möller committed
636
637
	    }
	  return LSH_OK | LSH_GOON;
Niels Möller's avatar
Niels Möller committed
638
639
	}
	  
640
      werror("Data on closed or non-existant channel %i\n",
Niels Möller's avatar
Niels Möller committed
641
642
643
644
645
646
647
648
649
	     channel_number);
      lsh_string_free(data);
      return LSH_FAIL | LSH_DIE;
    }
  lsh_string_free(packet);
  
  return LSH_FAIL | LSH_DIE;
}

650
651
static int do_channel_extended_data(struct packet_handler *closure UNUSED,
				    struct ssh_connection *connection,
Niels Möller's avatar
Niels Möller committed
652
653
654
				    struct lsh_string *packet)
{
  struct simple_buffer buffer;
655
  unsigned msg_number;
Niels Möller's avatar
Niels Möller committed
656
657
658
659
660
661
662
663
  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)
664
      && parse_uint32(&buffer, &channel_number)
Niels Möller's avatar
Niels Möller committed
665
666
667
668
      && parse_uint32(&buffer, &type)
      && ( (data = parse_string_copy(&buffer)) )
      && parse_eod(&buffer))
    {
669
      struct ssh_channel *channel = lookup_channel(connection->channels,
Niels Möller's avatar
Niels Möller committed
670
671
672
673
						   channel_number);

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

	      if (channel->rec_window_size < channel->max_window / 2)
		{
		  res = A_WRITE(channel->write, prepare_window_adjust
				(channel,
				 channel->max_window - channel->rec_window_size));
		  if (LSH_CLOSEDP(res))
		    return res;
		}

Niels Möller's avatar
Niels Möller committed
705
706
707
	      switch(type)
		{
		case SSH_EXTENDED_DATA_STDERR:
Niels Möller's avatar
Niels Möller committed
708
		  return channel_process_status(
709
		    connection->channels, channel_number,
710
		    res | CHANNEL_RECEIVE(channel, 
Niels Möller's avatar
Niels Möller committed
711
					  CHANNEL_STDERR_DATA, data));
Niels Möller's avatar
Niels Möller committed
712
		default:
713
		  werror("Unknown type %i of extended data.\n",
Niels Möller's avatar
Niels Möller committed
714
715
716
717
			 type);
		  lsh_string_free(data);
		  return LSH_FAIL | LSH_DIE;
		}
Niels Möller's avatar
Niels Möller committed
718
719
	    }
	}
720
      werror("Extended data on closed or non-existant channel %i\n",
Niels Möller's avatar
Niels Möller committed
721
722
723
724
725
726
727
728
729
	     channel_number);
      lsh_string_free(data);
      return LSH_FAIL | LSH_DIE;
    }
  lsh_string_free(packet);
  
  return LSH_FAIL | LSH_DIE;
}

730
731
static int do_channel_eof(struct packet_handler *closure UNUSED,
			  struct ssh_connection *connection,
732
			  struct lsh_string *packet)
Niels Möller's avatar
Niels Möller committed
733
734
{
  struct simple_buffer buffer;
735
  unsigned msg_number;
Niels Möller's avatar
Niels Möller committed
736
737
738
739
740
741
  UINT32 channel_number;
  
  simple_buffer_init(&buffer, packet->length, packet->data);

  if (parse_uint8(&buffer, &msg_number)
      && (msg_number == SSH_MSG_CHANNEL_EOF)
742
      && parse_uint32(&buffer, &channel_number)
Niels Möller's avatar
Niels Möller committed
743
744
      && parse_eod(&buffer))
    {
745
      struct ssh_channel *channel = lookup_channel(connection->channels,
Niels Möller's avatar
Niels Möller committed
746
747
748
749
						   channel_number);

      lsh_string_free(packet);

Niels Möller's avatar
Niels Möller committed
750
751
      if (channel)
	{
752
753
	  int res = 0;
	  
754
	  if (channel->flags & (CHANNEL_RECEIVED_EOF | CHANNEL_RECEIVED_CLOSE))
Niels Möller's avatar
Niels Möller committed
755
	    {
756
	      werror("Receiving EOF on channel on closed channel.\n");
Niels Möller's avatar
Niels Möller committed
757
758
759
	      return LSH_FAIL | LSH_DIE;
	    }

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

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

Niels Möller's avatar
Niels Möller committed
783
	}
784
      werror("EOF on non-existant channel %i\n",
Niels Möller's avatar
Niels Möller committed
785
786
	     channel_number);
      return LSH_FAIL | LSH_DIE;
Niels Möller's avatar
Niels Möller committed
787
    }
Niels Möller's avatar
Niels Möller committed
788
      
Niels Möller's avatar
Niels Möller committed
789
790
791
792
  lsh_string_free(packet);
  return LSH_FAIL | LSH_DIE;
}

793
794
static int do_channel_close(struct packet_handler *closure UNUSED,
			    struct ssh_connection *connection,
Niels Möller's avatar
Niels Möller committed
795
796
797
			    struct lsh_string *packet)
{
  struct simple_buffer buffer;
798
  unsigned msg_number;
Niels Möller's avatar
Niels Möller committed
799
800
801
802
803
804
  UINT32 channel_number;
  
  simple_buffer_init(&buffer, packet->length, packet->data);

  if (parse_uint8(&buffer, &msg_number)
      && (msg_number == SSH_MSG_CHANNEL_CLOSE)
805
      && parse_uint32(&buffer, &channel_number)
Niels Möller's avatar
Niels Möller committed
806
807
      && parse_eod(&buffer))
    {
808
      struct ssh_channel *channel = lookup_channel(connection->channels,
Niels Möller's avatar
Niels Möller committed
809
810
811
812
						   channel_number);

      lsh_string_free(packet);
      
Niels Möller's avatar
Niels Möller committed
813
814
      if (channel)
	{
815
816
	  int res = 0;
	  
817
	  if (channel->flags & CHANNEL_RECEIVED_CLOSE)
Niels Möller's avatar
Niels Möller committed
818
	    {
819
	      werror("Receiving multiple CLOSE on channel.\n");
Niels Möller's avatar
Niels Möller committed
820
821
822
	      return LSH_FAIL | LSH_DIE;
	    }

823
	  channel->flags |= CHANNEL_RECEIVED_CLOSE;
Niels Möller's avatar
Niels Möller committed
824
	  
825
	  if (! (channel->flags & (CHANNEL_RECEIVED_EOF | CHANNEL_SENT_EOF)))
Niels Möller's avatar
Niels Möller committed
826
	    {
827
	      werror("Unexpected channel CLOSE.\n");
Niels Möller's avatar
Niels Möller committed
828
	    }
829

830
	  if (! (channel->flags & (CHANNEL_RECEIVED_EOF))
831
	      && channel->eof)
832
	    res = CHANNEL_EOF(channel);
Niels Möller's avatar
Niels Möller committed
833
	  
Niels Möller's avatar
Niels Möller committed
834
	  return channel_process_status(
835
	    connection->channels, channel_number,
836
837
838
839
	    ( ( (channel->flags & (CHANNEL_SENT_CLOSE))
		? LSH_OK | LSH_CHANNEL_FINISHED
		: channel_close(channel))
	      | res));
Niels Möller's avatar
Niels Möller committed
840
	}
841
      werror("CLOSE on non-existant channel %i\n",
Niels Möller's avatar
Niels Möller committed
842
843
	     channel_number);
      return LSH_FAIL | LSH_DIE;
Niels Möller's avatar
Niels Möller committed
844
845
846
847
848
849
      
    }
  lsh_string_free(packet);
  return LSH_FAIL | LSH_DIE;
}

850
static int do_channel_open_confirm(struct packet_handler *closure UNUSED,
Niels Möller's avatar
Niels Möller committed
851
852
				   struct ssh_connection *connection,
				   struct lsh_string *packet)
Niels Möller's avatar
Niels Möller committed
853
854
{
  struct simple_buffer buffer;
855
  unsigned msg_number;
Niels Möller's avatar
Niels Möller committed
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
  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))
    {
871
      struct ssh_channel *channel = lookup_channel(connection->channels,
Niels Möller's avatar
Niels Möller committed
872
873
874
875
						   local_channel_number);

      lsh_string_free(packet);

876
      if (channel && channel->open_continuation)
Niels Möller's avatar
Niels Möller committed
877
878
879
880
881
	{
	  channel->channel_number = remote_channel_number;
	  channel->send_window_size = window_size;
	  channel->send_max_packet = max_packet;

882
883
884
885
	  return channel_process_status
	    (connection->channels,
	     local_channel_number,
	     COMMAND_RETURN(channel->open_continuation, channel));
Niels Möller's avatar
Niels Möller committed
886
	}
887
      werror("Unexpected SSH_MSG_CHANNEL_OPEN_CONFIRMATION on channel %i\n",
Niels Möller's avatar
Niels Möller committed
888
889
890
891
892
893
894
	     local_channel_number);
      return LSH_FAIL | LSH_DIE;
    }
  lsh_string_free(packet);
  return LSH_FAIL | LSH_DIE;
}

895
896
static int do_channel_open_failure(struct packet_handler *closure UNUSED,
			      struct ssh_connection *connection,
Niels Möller's avatar
Niels Möller committed
897
898
899
			      struct lsh_string *packet)
{
  struct simple_buffer buffer;
900
  unsigned msg_number;
Niels Möller's avatar
Niels Möller committed
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
  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))
    {
920
      struct ssh_channel *channel = lookup_channel(connection->channels,
Niels Möller's avatar
Niels Möller committed
921
922
923
924
						   channel_number);

      /* lsh_string_free(packet); */

925
      if (channel && channel->open_continuation)
Niels Möller's avatar
Niels Möller committed
926
	{
927
	  int res = COMMAND_RETURN(channel->open_continuation, NULL);
Niels Möller's avatar
Niels Möller committed
928
929

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

931
	  return channel_process_status(connection->channels, channel_number,
Niels Möller's avatar
Niels Möller committed
932
					res | LSH_CHANNEL_FINISHED);
Niels Möller's avatar
Niels Möller committed
933
	}
934
      werror("Unexpected SSH_MSG_CHANNEL_OPEN_FAILURE on channel %i\n",
Niels Möller's avatar
Niels Möller committed
935
936
937
938
939
940
941
942
943
	     channel_number);
      lsh_string_free(packet);
      
      return LSH_FAIL | LSH_DIE;
    }
  lsh_string_free(packet);
  return LSH_FAIL | LSH_DIE;
}

944
945
static int do_channel_success(struct packet_handler *closure UNUSED,
			      struct ssh_connection *connection,
946
947
948
			      struct lsh_string *packet)
{
  struct simple_buffer buffer;
949
  unsigned msg_number;
950
  UINT32 channel_number;
951
952
  struct ssh_channel *channel;
      
953
954
955
956
  simple_buffer_init(&buffer, packet->length, packet->data);

  if (parse_uint8(&buffer, &msg_number)
      && (msg_number == SSH_MSG_CHANNEL_SUCCESS)
957
      && parse_uint32(&buffer, &channel_number)
958
      && parse_eod(&buffer)
959
      && (channel = lookup_channel(connection->channels, channel_number)))
960
    
961
962
    {
      lsh_string_free(packet);
963
964
965
966
967
968
969

      if (!channel->channel_failure)
	{
	  werror("do_channel_success: No handler. Ignoring.\n");
	  return LSH_OK | LSH_GOON;
	}

970
      return channel_process_status(connection->channels, channel_number,
971
				    CHANNEL_SUCCESS(channel));
972
973
974
975
976
    }
  lsh_string_free(packet);
  return LSH_FAIL | LSH_DIE;
}

977
978
static int do_channel_failure(struct packet_handler *closure UNUSED,
			      struct ssh_connection *connection,
979
980
981
			      struct lsh_string *packet)
{
  struct simple_buffer buffer;
982
  unsigned msg_number;
983
  UINT32 channel_number;
984
  struct ssh_channel *channel;
985
986
987
988
989
  
  simple_buffer_init(&buffer, packet->length, packet->data);

  if (parse_uint8(&buffer, &msg_number)
      && (msg_number == SSH_MSG_CHANNEL_FAILURE)
990
      && parse_uint32(&buffer, &channel_number)
991
      && parse_eod(&buffer)
992
      && (channel = lookup_channel(connection->channels, channel_number)))
993
994
995
    {
      lsh_string_free(packet);
      
996
997
998
999
1000
1001

      if (!channel->channel_failure)
	{
	  werror("do_channel_failure: No handler. Ignoring.\n");
	  return LSH_OK | LSH_GOON;
	}
1002
      return channel_process_status(connection->channels, channel_number,
1003
					CHANNEL_FAILURE(channel));
1004
1005
1006
1007
1008
    }
  lsh_string_free(packet);
  return LSH_FAIL | LSH_DIE;
}

1009
static int init_connection_service(struct ssh_service *s,
Niels Möller's avatar
Niels Möller committed
1010
				   struct ssh_connection *connection)
Niels Möller's avatar
Niels Möller committed
1011
{
1012
1013
  CAST(connection_service, self, s);

1014
  struct channel_table *table;
Niels Möller's avatar
Niels Möller committed
1015
  
1016
1017
  NEW(global_request_handler, globals);
  NEW(channel_open_handler, open);
1018
  NEW(packet_handler, request);
Niels Möller's avatar
Niels Möller committed
1019

1020
1021
1022
  NEW(packet_handler, adjust);
  NEW(packet_handler, data);
  NEW(packet_handler, extended);
Niels Möller's avatar
Niels Möller committed
1023

1024
1025
  NEW(packet_handler, eof);
  NEW(packet_handler, close);
1026

1027
1028
  NEW(packet_handler, open_confirm);
  NEW(packet_handler, open_failure);
Niels Möller's avatar
Niels Möller committed
1029

1030
1031
  NEW(packet_handler, channel_success);
  NEW(packet_handler, channel_failure);
Niels Möller's avatar
Niels Möller committed
1032

1033
  table = make_channel_table();
Niels Möller's avatar
Niels Möller committed
1034
  
1035
1036
1037
  connection->channels = table;
  
  globals->super.handler = do_global_request;
Niels Möller's avatar
Niels Möller committed
1038
  globals->global_requests = self->global_requests;
1039
  connection->dispatch[SSH_MSG_GLOBAL_REQUEST] = &globals->super;
Niels Möller's avatar
Niels Möller committed
1040
    
1041
  open->super.handler = do_channel_open;
Niels Möller's avatar
Niels Möller committed
1042
  open->channel_types = self->channel_types;
1043
  connection->dispatch[SSH_MSG_CHANNEL_OPEN] = &open->super;
Niels Möller's avatar
Niels Möller committed
1044

1045
1046
  request->handler = do_channel_request;
  connection->dispatch[SSH_MSG_CHANNEL_REQUEST] = request;
Niels Möller's avatar
Niels Möller committed
1047
  
1048
1049
  adjust->handler = do_window_adjust;
  connection->dispatch[SSH_MSG_CHANNEL_WINDOW_ADJUST] = adjust;
Niels Möller's avatar
Niels Möller committed
1050

1051
1052
  data->handler = do_channel_data;
  connection->dispatch[SSH_MSG_CHANNEL_DATA] = data;
Niels Möller's avatar
Niels Möller committed
1053

1054
1055
  extended->handler = do_channel_extended_data;
  connection->dispatch[SSH_MSG_CHANNEL_EXTENDED_DATA] = extended;
Niels Möller's avatar
Niels Möller committed
1056

1057
1058
  eof->handler = do_channel_eof;
  connection->dispatch[SSH_MSG_CHANNEL_EOF] = eof;
Niels Möller's avatar
Niels Möller committed
1059

1060
1061
  close->handler = do_channel_close;
  connection->dispatch[SSH_MSG_CHANNEL_CLOSE] = close;
Niels Möller's avatar
Niels Möller committed
1062

1063
1064
  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
1065

1066
1067
  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
1068
  
1069
1070
  channel_success->handler = do_channel_success;
  connection->dispatch[SSH_MSG_CHANNEL_SUCCESS] = channel_success;
1071

1072
1073
  channel_failure->handler = do_channel_failure;
  connection->dispatch[SSH_MSG_CHANNEL_FAILURE] = channel_failure;
1074
    
Niels Möller's avatar
Niels Möller committed
1075
  return self->start
1076
    ? CONNECTION_START(self->start, connection)
1077
    : LSH_OK | LSH_GOON;
Niels Möller's avatar
Niels Möller committed
1078
1079
}

1080
1081
1082
struct ssh_service *make_connection_service(struct alist *global_requests,
					    struct alist *channel_types,
					    struct connection_startup *start)
1083
{
1084
  NEW(connection_service, self);
1085

1086
1087
1088
1089
1090
1091
  self->super.init = init_connection_service;
  self->global_requests = global_requests;
  self->channel_types = channel_types;
  self->start = start;
  
  return &self->super;
1092
1093
}

Niels Möller's avatar
Niels Möller committed
1094
1095
1096
1097
1098
1099
1100
1101
1102
struct lsh_string *format_channel_close(struct ssh_channel *channel)
{
  return ssh_format("%c%i",
		    SSH_MSG_CHANNEL_CLOSE,
		    channel->channel_number);
}

int channel_close(struct ssh_channel *channel)
{
1103
1104
  assert(! (channel->flags & CHANNEL_SENT_CLOSE));
  
Niels Möller's avatar
Niels Möller committed
1105
1106
1107
  channel->flags |= CHANNEL_SENT_CLOSE;

  return A_WRITE(channel->write, format_channel_close(channel))
1108
    | ( (channel->flags & CHANNEL_RECEIVED_CLOSE)
Niels Möller's avatar
Niels Möller committed
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
	? LSH_CHANNEL_FINISHED : 0);
}

struct lsh_string *format_channel_eof(struct ssh_channel *channel)
{
  return ssh_format("%c%i",
		    SSH_MSG_CHANNEL_EOF,
		    channel->channel_number);
}

int channel_eof(struct ssh_channel *channel)
{
  int res ;
1122
1123

  assert(! (channel->flags & CHANNEL_SENT_EOF));
Niels Möller's avatar
Niels Möller committed
1124
  
1125
  channel->flags |= CHANNEL_SENT_EOF;
Niels Möller's avatar