1 /* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
2 * Copyright (c) 2005,2006 Mikhail Gusarov
3 * Copyright (c) 2009-2014 by Daniel Stenberg
4 * Copyright (c) 2010 Simon Josefsson
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms,
8 * with or without modification, are permitted provided
9 * that the following conditions are met:
10 *
11 * Redistributions of source code must retain the above
12 * copyright notice, this list of conditions and the
13 * following disclaimer.
14 *
15 * Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer in the documentation and/or other materials
18 * provided with the distribution.
19 *
20 * Neither the name of the copyright holder nor the names
21 * of any other contributors may be used to endorse or
22 * promote products derived from this software without
23 * specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
26 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
27 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
30 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
32 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
33 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
35 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
37 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
38 * OF SUCH DAMAGE.
39 */
40
41 #include "libssh2_priv.h"
42 #include <errno.h>
43 #include <fcntl.h>
44
45 #ifdef HAVE_UNISTD_H
46 #include <unistd.h>
47 #endif
48
49 #ifdef HAVE_SYS_TIME_H
50 #include <sys/time.h>
51 #endif
52
53 #ifdef HAVE_INTTYPES_H
54 #include <inttypes.h>
55 #endif
56
57 /* Needed for struct iovec on some platforms */
58 #ifdef HAVE_SYS_UIO_H
59 #include <sys/uio.h>
60 #endif
61
62 #include <sys/types.h>
63
64 #include "transport.h"
65 #include "channel.h"
66 #include "packet.h"
67
68 /*
69 * libssh2_packet_queue_listener
70 *
71 * Queue a connection request for a listener
72 */
73 static inline int
packet_queue_listener(LIBSSH2_SESSION * session,unsigned char * data,unsigned long datalen,packet_queue_listener_state_t * listen_state)74 packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data,
75 unsigned long datalen,
76 packet_queue_listener_state_t *listen_state)
77 {
78 /*
79 * Look for a matching listener
80 */
81 /* 17 = packet_type(1) + channel(4) + reason(4) + descr(4) + lang(4) */
82 unsigned long packet_len = 17 + (sizeof(FwdNotReq) - 1);
83 unsigned char *p;
84 LIBSSH2_LISTENER *listn = _libssh2_list_first(&session->listeners);
85 char failure_code = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED;
86 int rc;
87
88 (void) datalen;
89
90 if (listen_state->state == libssh2_NB_state_idle) {
91 unsigned char *s = data + (sizeof("forwarded-tcpip") - 1) + 5;
92 listen_state->sender_channel = _libssh2_ntohu32(s);
93 s += 4;
94
95 listen_state->initial_window_size = _libssh2_ntohu32(s);
96 s += 4;
97 listen_state->packet_size = _libssh2_ntohu32(s);
98 s += 4;
99
100 listen_state->host_len = _libssh2_ntohu32(s);
101 s += 4;
102 listen_state->host = s;
103 s += listen_state->host_len;
104 listen_state->port = _libssh2_ntohu32(s);
105 s += 4;
106
107 listen_state->shost_len = _libssh2_ntohu32(s);
108 s += 4;
109 listen_state->shost = s;
110 s += listen_state->shost_len;
111 listen_state->sport = _libssh2_ntohu32(s);
112
113 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
114 "Remote received connection from %s:%ld to %s:%ld",
115 listen_state->shost, listen_state->sport,
116 listen_state->host, listen_state->port);
117
118 listen_state->state = libssh2_NB_state_allocated;
119 }
120
121 if (listen_state->state != libssh2_NB_state_sent) {
122 while (listn) {
123 if ((listn->port == (int) listen_state->port) &&
124 (strlen(listn->host) == listen_state->host_len) &&
125 (memcmp (listn->host, listen_state->host,
126 listen_state->host_len) == 0)) {
127 /* This is our listener */
128 LIBSSH2_CHANNEL *channel = NULL;
129 listen_state->channel = NULL;
130
131 if (listen_state->state == libssh2_NB_state_allocated) {
132 if (listn->queue_maxsize &&
133 (listn->queue_maxsize <= listn->queue_size)) {
134 /* Queue is full */
135 failure_code = SSH_OPEN_RESOURCE_SHORTAGE;
136 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
137 "Listener queue full, ignoring");
138 listen_state->state = libssh2_NB_state_sent;
139 break;
140 }
141
142 channel = LIBSSH2_CALLOC(session, sizeof(LIBSSH2_CHANNEL));
143 if (!channel) {
144 _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
145 "Unable to allocate a channel for "
146 "new connection");
147 failure_code = SSH_OPEN_RESOURCE_SHORTAGE;
148 listen_state->state = libssh2_NB_state_sent;
149 break;
150 }
151 listen_state->channel = channel;
152
153 channel->session = session;
154 channel->channel_type_len = sizeof("forwarded-tcpip") - 1;
155 channel->channel_type = LIBSSH2_ALLOC(session,
156 channel->
157 channel_type_len +
158 1);
159 if (!channel->channel_type) {
160 _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
161 "Unable to allocate a channel for new"
162 " connection");
163 LIBSSH2_FREE(session, channel);
164 failure_code = SSH_OPEN_RESOURCE_SHORTAGE;
165 listen_state->state = libssh2_NB_state_sent;
166 break;
167 }
168 memcpy(channel->channel_type, "forwarded-tcpip",
169 channel->channel_type_len + 1);
170
171 channel->remote.id = listen_state->sender_channel;
172 channel->remote.window_size_initial =
173 LIBSSH2_CHANNEL_WINDOW_DEFAULT;
174 channel->remote.window_size =
175 LIBSSH2_CHANNEL_WINDOW_DEFAULT;
176 channel->remote.packet_size =
177 LIBSSH2_CHANNEL_PACKET_DEFAULT;
178
179 channel->local.id = _libssh2_channel_nextid(session);
180 channel->local.window_size_initial =
181 listen_state->initial_window_size;
182 channel->local.window_size =
183 listen_state->initial_window_size;
184 channel->local.packet_size = listen_state->packet_size;
185
186 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
187 "Connection queued: channel %lu/%lu "
188 "win %lu/%lu packet %lu/%lu",
189 channel->local.id, channel->remote.id,
190 channel->local.window_size,
191 channel->remote.window_size,
192 channel->local.packet_size,
193 channel->remote.packet_size);
194
195 p = listen_state->packet;
196 *(p++) = SSH_MSG_CHANNEL_OPEN_CONFIRMATION;
197 _libssh2_store_u32(&p, channel->remote.id);
198 _libssh2_store_u32(&p, channel->local.id);
199 _libssh2_store_u32(&p,
200 channel->remote.window_size_initial);
201 _libssh2_store_u32(&p, channel->remote.packet_size);
202
203 listen_state->state = libssh2_NB_state_created;
204 }
205
206 if (listen_state->state == libssh2_NB_state_created) {
207 rc = _libssh2_transport_send(session, listen_state->packet,
208 17, NULL, 0);
209 if (rc == LIBSSH2_ERROR_EAGAIN)
210 return rc;
211 else if (rc) {
212 listen_state->state = libssh2_NB_state_idle;
213 return _libssh2_error(session, rc,
214 "Unable to send channel "
215 "open confirmation");
216 }
217
218 /* Link the channel into the end of the queue list */
219 if (listen_state->channel) {
220 _libssh2_list_add(&listn->queue,
221 &listen_state->channel->node);
222 listn->queue_size++;
223 }
224
225 listen_state->state = libssh2_NB_state_idle;
226 return 0;
227 }
228 }
229
230 listn = _libssh2_list_next(&listn->node);
231 }
232
233 listen_state->state = libssh2_NB_state_sent;
234 }
235
236 /* We're not listening to you */
237 p = listen_state->packet;
238 *(p++) = SSH_MSG_CHANNEL_OPEN_FAILURE;
239 _libssh2_store_u32(&p, listen_state->sender_channel);
240 _libssh2_store_u32(&p, failure_code);
241 _libssh2_store_str(&p, FwdNotReq, sizeof(FwdNotReq) - 1);
242 _libssh2_htonu32(p, 0);
243
244 rc = _libssh2_transport_send(session, listen_state->packet,
245 packet_len, NULL, 0);
246 if (rc == LIBSSH2_ERROR_EAGAIN) {
247 return rc;
248 } else if (rc) {
249 listen_state->state = libssh2_NB_state_idle;
250 return _libssh2_error(session, rc, "Unable to send open failure");
251
252 }
253 listen_state->state = libssh2_NB_state_idle;
254 return 0;
255 }
256
257 /*
258 * packet_x11_open
259 *
260 * Accept a forwarded X11 connection
261 */
262 static inline int
packet_x11_open(LIBSSH2_SESSION * session,unsigned char * data,unsigned long datalen,packet_x11_open_state_t * x11open_state)263 packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data,
264 unsigned long datalen,
265 packet_x11_open_state_t *x11open_state)
266 {
267 int failure_code = SSH_OPEN_CONNECT_FAILED;
268 /* 17 = packet_type(1) + channel(4) + reason(4) + descr(4) + lang(4) */
269 unsigned long packet_len = 17 + (sizeof(X11FwdUnAvil) - 1);
270 unsigned char *p;
271 LIBSSH2_CHANNEL *channel = x11open_state->channel;
272 int rc;
273
274 (void) datalen;
275
276 if (x11open_state->state == libssh2_NB_state_idle) {
277 unsigned char *s = data + (sizeof("x11") - 1) + 5;
278 x11open_state->sender_channel = _libssh2_ntohu32(s);
279 s += 4;
280 x11open_state->initial_window_size = _libssh2_ntohu32(s);
281 s += 4;
282 x11open_state->packet_size = _libssh2_ntohu32(s);
283 s += 4;
284 x11open_state->shost_len = _libssh2_ntohu32(s);
285 s += 4;
286 x11open_state->shost = s;
287 s += x11open_state->shost_len;
288 x11open_state->sport = _libssh2_ntohu32(s);
289
290 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
291 "X11 Connection Received from %s:%ld on channel %lu",
292 x11open_state->shost, x11open_state->sport,
293 x11open_state->sender_channel);
294
295 x11open_state->state = libssh2_NB_state_allocated;
296 }
297
298 if (session->x11) {
299 if (x11open_state->state == libssh2_NB_state_allocated) {
300 channel = LIBSSH2_CALLOC(session, sizeof(LIBSSH2_CHANNEL));
301 if (!channel) {
302 _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
303 "allocate a channel for new connection");
304 failure_code = SSH_OPEN_RESOURCE_SHORTAGE;
305 goto x11_exit;
306 }
307
308 channel->session = session;
309 channel->channel_type_len = sizeof("x11") - 1;
310 channel->channel_type = LIBSSH2_ALLOC(session,
311 channel->channel_type_len +
312 1);
313 if (!channel->channel_type) {
314 _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
315 "allocate a channel for new connection");
316 LIBSSH2_FREE(session, channel);
317 failure_code = SSH_OPEN_RESOURCE_SHORTAGE;
318 goto x11_exit;
319 }
320 memcpy(channel->channel_type, "x11",
321 channel->channel_type_len + 1);
322
323 channel->remote.id = x11open_state->sender_channel;
324 channel->remote.window_size_initial =
325 LIBSSH2_CHANNEL_WINDOW_DEFAULT;
326 channel->remote.window_size = LIBSSH2_CHANNEL_WINDOW_DEFAULT;
327 channel->remote.packet_size = LIBSSH2_CHANNEL_PACKET_DEFAULT;
328
329 channel->local.id = _libssh2_channel_nextid(session);
330 channel->local.window_size_initial =
331 x11open_state->initial_window_size;
332 channel->local.window_size = x11open_state->initial_window_size;
333 channel->local.packet_size = x11open_state->packet_size;
334
335 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
336 "X11 Connection established: channel %lu/%lu "
337 "win %lu/%lu packet %lu/%lu",
338 channel->local.id, channel->remote.id,
339 channel->local.window_size,
340 channel->remote.window_size,
341 channel->local.packet_size,
342 channel->remote.packet_size);
343 p = x11open_state->packet;
344 *(p++) = SSH_MSG_CHANNEL_OPEN_CONFIRMATION;
345 _libssh2_store_u32(&p, channel->remote.id);
346 _libssh2_store_u32(&p, channel->local.id);
347 _libssh2_store_u32(&p, channel->remote.window_size_initial);
348 _libssh2_store_u32(&p, channel->remote.packet_size);
349
350 x11open_state->state = libssh2_NB_state_created;
351 }
352
353 if (x11open_state->state == libssh2_NB_state_created) {
354 rc = _libssh2_transport_send(session, x11open_state->packet, 17,
355 NULL, 0);
356 if (rc == LIBSSH2_ERROR_EAGAIN) {
357 return rc;
358 } else if (rc) {
359 x11open_state->state = libssh2_NB_state_idle;
360 return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
361 "Unable to send channel open "
362 "confirmation");
363 }
364
365 /* Link the channel into the session */
366 _libssh2_list_add(&session->channels, &channel->node);
367
368 /*
369 * Pass control to the callback, they may turn right around and
370 * free the channel, or actually use it
371 */
372 LIBSSH2_X11_OPEN(channel, (char *)x11open_state->shost,
373 x11open_state->sport);
374
375 x11open_state->state = libssh2_NB_state_idle;
376 return 0;
377 }
378 }
379 else
380 failure_code = SSH_OPEN_RESOURCE_SHORTAGE;
381 /* fall-trough */
382 x11_exit:
383 p = x11open_state->packet;
384 *(p++) = SSH_MSG_CHANNEL_OPEN_FAILURE;
385 _libssh2_store_u32(&p, x11open_state->sender_channel);
386 _libssh2_store_u32(&p, failure_code);
387 _libssh2_store_str(&p, X11FwdUnAvil, sizeof(X11FwdUnAvil) - 1);
388 _libssh2_htonu32(p, 0);
389
390 rc = _libssh2_transport_send(session, x11open_state->packet, packet_len,
391 NULL, 0);
392 if (rc == LIBSSH2_ERROR_EAGAIN) {
393 return rc;
394 } else if (rc) {
395 x11open_state->state = libssh2_NB_state_idle;
396 return _libssh2_error(session, rc, "Unable to send open failure");
397 }
398 x11open_state->state = libssh2_NB_state_idle;
399 return 0;
400 }
401
402 /*
403 * _libssh2_packet_add
404 *
405 * Create a new packet and attach it to the brigade. Called from the transport
406 * layer when it has received a packet.
407 *
408 * The input pointer 'data' is pointing to allocated data that this function
409 * is asked to deal with so on failure OR success, it must be freed fine.
410 * The only exception is when the return code is LIBSSH2_ERROR_EAGAIN.
411 *
412 * This function will always be called with 'datalen' greater than zero.
413 */
414 int
_libssh2_packet_add(LIBSSH2_SESSION * session,unsigned char * data,size_t datalen,int macstate)415 _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
416 size_t datalen, int macstate)
417 {
418 int rc = 0;
419 char *message=NULL;
420 char *language=NULL;
421 size_t message_len=0;
422 size_t language_len=0;
423 LIBSSH2_CHANNEL *channelp = NULL;
424 size_t data_head = 0;
425 unsigned char msg = data[0];
426
427 switch(session->packAdd_state) {
428 case libssh2_NB_state_idle:
429 _libssh2_debug(session, LIBSSH2_TRACE_TRANS,
430 "Packet type %d received, length=%d",
431 (int) msg, (int) datalen);
432
433 if ((macstate == LIBSSH2_MAC_INVALID) &&
434 (!session->macerror ||
435 LIBSSH2_MACERROR(session, (char *) data, datalen))) {
436 /* Bad MAC input, but no callback set or non-zero return from the
437 callback */
438
439 LIBSSH2_FREE(session, data);
440 return _libssh2_error(session, LIBSSH2_ERROR_INVALID_MAC,
441 "Invalid MAC received");
442 }
443 session->packAdd_state = libssh2_NB_state_allocated;
444 break;
445 case libssh2_NB_state_jump1:
446 goto libssh2_packet_add_jump_point1;
447 case libssh2_NB_state_jump2:
448 goto libssh2_packet_add_jump_point2;
449 case libssh2_NB_state_jump3:
450 goto libssh2_packet_add_jump_point3;
451 case libssh2_NB_state_jump4:
452 goto libssh2_packet_add_jump_point4;
453 case libssh2_NB_state_jump5:
454 goto libssh2_packet_add_jump_point5;
455 default: /* nothing to do */
456 break;
457 }
458
459 if (session->packAdd_state == libssh2_NB_state_allocated) {
460 /* A couple exceptions to the packet adding rule: */
461 switch (msg) {
462
463 /*
464 byte SSH_MSG_DISCONNECT
465 uint32 reason code
466 string description in ISO-10646 UTF-8 encoding [RFC3629]
467 string language tag [RFC3066]
468 */
469
470 case SSH_MSG_DISCONNECT:
471 if(datalen >= 5) {
472 size_t reason = _libssh2_ntohu32(data + 1);
473
474 if(datalen >= 9) {
475 message_len = _libssh2_ntohu32(data + 5);
476
477 if(message_len < datalen-13) {
478 /* 9 = packet_type(1) + reason(4) + message_len(4) */
479 message = (char *) data + 9;
480
481 language_len = _libssh2_ntohu32(data + 9 + message_len);
482 language = (char *) data + 9 + message_len + 4;
483
484 if(language_len > (datalen-13-message_len)) {
485 /* bad input, clear info */
486 language = message = NULL;
487 language_len = message_len = 0;
488 }
489 }
490 else
491 /* bad size, clear it */
492 message_len=0;
493 }
494 if (session->ssh_msg_disconnect) {
495 LIBSSH2_DISCONNECT(session, reason, message,
496 message_len, language, language_len);
497 }
498 _libssh2_debug(session, LIBSSH2_TRACE_TRANS,
499 "Disconnect(%d): %s(%s)", reason,
500 message, language);
501 }
502
503 LIBSSH2_FREE(session, data);
504 session->socket_state = LIBSSH2_SOCKET_DISCONNECTED;
505 session->packAdd_state = libssh2_NB_state_idle;
506 return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_DISCONNECT,
507 "socket disconnect");
508 /*
509 byte SSH_MSG_IGNORE
510 string data
511 */
512
513 case SSH_MSG_IGNORE:
514 if (datalen >= 2) {
515 if (session->ssh_msg_ignore) {
516 LIBSSH2_IGNORE(session, (char *) data + 1, datalen - 1);
517 }
518 } else if (session->ssh_msg_ignore) {
519 LIBSSH2_IGNORE(session, "", 0);
520 }
521 LIBSSH2_FREE(session, data);
522 session->packAdd_state = libssh2_NB_state_idle;
523 return 0;
524
525 /*
526 byte SSH_MSG_DEBUG
527 boolean always_display
528 string message in ISO-10646 UTF-8 encoding [RFC3629]
529 string language tag [RFC3066]
530 */
531
532 case SSH_MSG_DEBUG:
533 if(datalen >= 2) {
534 int always_display= data[1];
535
536 if(datalen >= 6) {
537 message_len = _libssh2_ntohu32(data + 2);
538
539 if(message_len <= (datalen - 10)) {
540 /* 6 = packet_type(1) + display(1) + message_len(4) */
541 message = (char *) data + 6;
542 language_len = _libssh2_ntohu32(data + 6 + message_len);
543
544 if(language_len <= (datalen - 10 - message_len))
545 language = (char *) data + 10 + message_len;
546 }
547 }
548
549 if (session->ssh_msg_debug) {
550 LIBSSH2_DEBUG(session, always_display, message,
551 message_len, language, language_len);
552 }
553 }
554 /*
555 * _libssh2_debug will actually truncate this for us so
556 * that it's not an inordinate about of data
557 */
558 _libssh2_debug(session, LIBSSH2_TRACE_TRANS,
559 "Debug Packet: %s", message);
560 LIBSSH2_FREE(session, data);
561 session->packAdd_state = libssh2_NB_state_idle;
562 return 0;
563
564 /*
565 byte SSH_MSG_GLOBAL_REQUEST
566 string request name in US-ASCII only
567 boolean want reply
568 .... request-specific data follows
569 */
570
571 case SSH_MSG_GLOBAL_REQUEST:
572 if(datalen >= 5) {
573 uint32_t len =0;
574 unsigned char want_reply=0;
575 len = _libssh2_ntohu32(data + 1);
576 if(datalen >= (6 + len)) {
577 want_reply = data[5 + len];
578 _libssh2_debug(session,
579 LIBSSH2_TRACE_CONN,
580 "Received global request type %.*s (wr %X)",
581 len, data + 5, want_reply);
582 }
583
584
585 if (want_reply) {
586 static const unsigned char packet =
587 SSH_MSG_REQUEST_FAILURE;
588 libssh2_packet_add_jump_point5:
589 session->packAdd_state = libssh2_NB_state_jump5;
590 rc = _libssh2_transport_send(session, &packet, 1, NULL, 0);
591 if (rc == LIBSSH2_ERROR_EAGAIN)
592 return rc;
593 }
594 }
595 LIBSSH2_FREE(session, data);
596 session->packAdd_state = libssh2_NB_state_idle;
597 return 0;
598
599 /*
600 byte SSH_MSG_CHANNEL_EXTENDED_DATA
601 uint32 recipient channel
602 uint32 data_type_code
603 string data
604 */
605
606 case SSH_MSG_CHANNEL_EXTENDED_DATA:
607 /* streamid(4) */
608 data_head += 4;
609
610 /* fall-through */
611
612 /*
613 byte SSH_MSG_CHANNEL_DATA
614 uint32 recipient channel
615 string data
616 */
617
618 case SSH_MSG_CHANNEL_DATA:
619 /* packet_type(1) + channelno(4) + datalen(4) */
620 data_head += 9;
621
622 if(datalen >= data_head)
623 channelp =
624 _libssh2_channel_locate(session,
625 _libssh2_ntohu32(data + 1));
626
627 if (!channelp) {
628 _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_UNKNOWN,
629 "Packet received for unknown channel");
630 LIBSSH2_FREE(session, data);
631 session->packAdd_state = libssh2_NB_state_idle;
632 return 0;
633 }
634 #ifdef LIBSSH2DEBUG
635 {
636 uint32_t stream_id = 0;
637 if (msg == SSH_MSG_CHANNEL_EXTENDED_DATA)
638 stream_id = _libssh2_ntohu32(data + 5);
639
640 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
641 "%d bytes packet_add() for %lu/%lu/%lu",
642 (int) (datalen - data_head),
643 channelp->local.id,
644 channelp->remote.id,
645 stream_id);
646 }
647 #endif
648 if ((channelp->remote.extended_data_ignore_mode ==
649 LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) &&
650 (msg == SSH_MSG_CHANNEL_EXTENDED_DATA)) {
651 /* Pretend we didn't receive this */
652 LIBSSH2_FREE(session, data);
653
654 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
655 "Ignoring extended data and refunding %d bytes",
656 (int) (datalen - 13));
657 if (channelp->read_avail + datalen - data_head >=
658 channelp->remote.window_size)
659 datalen = channelp->remote.window_size -
660 channelp->read_avail + data_head;
661
662 channelp->remote.window_size -= datalen - data_head;
663 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
664 "shrinking window size by %lu bytes to %lu, read_avail %lu",
665 datalen - data_head,
666 channelp->remote.window_size,
667 channelp->read_avail);
668
669 session->packAdd_channelp = channelp;
670
671 /* Adjust the window based on the block we just freed */
672 libssh2_packet_add_jump_point1:
673 session->packAdd_state = libssh2_NB_state_jump1;
674 rc = _libssh2_channel_receive_window_adjust(session->
675 packAdd_channelp,
676 datalen - 13,
677 1, NULL);
678 if (rc == LIBSSH2_ERROR_EAGAIN)
679 return rc;
680
681 session->packAdd_state = libssh2_NB_state_idle;
682 return 0;
683 }
684
685 /*
686 * REMEMBER! remote means remote as source of data,
687 * NOT remote window!
688 */
689 if (channelp->remote.packet_size < (datalen - data_head)) {
690 /*
691 * Spec says we MAY ignore bytes sent beyond
692 * packet_size
693 */
694 _libssh2_error(session,
695 LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED,
696 "Packet contains more data than we offered"
697 " to receive, truncating");
698 datalen = channelp->remote.packet_size + data_head;
699 }
700 if (channelp->remote.window_size <= channelp->read_avail) {
701 /*
702 * Spec says we MAY ignore bytes sent beyond
703 * window_size
704 */
705 _libssh2_error(session,
706 LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED,
707 "The current receive window is full,"
708 " data ignored");
709 LIBSSH2_FREE(session, data);
710 session->packAdd_state = libssh2_NB_state_idle;
711 return 0;
712 }
713 /* Reset EOF status */
714 channelp->remote.eof = 0;
715
716 if (channelp->read_avail + datalen - data_head >
717 channelp->remote.window_size) {
718 _libssh2_error(session,
719 LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED,
720 "Remote sent more data than current "
721 "window allows, truncating");
722 datalen = channelp->remote.window_size -
723 channelp->read_avail + data_head;
724 }
725
726 /* Update the read_avail counter. The window size will be
727 * updated once the data is actually read from the queue
728 * from an upper layer */
729 channelp->read_avail += datalen - data_head;
730
731 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
732 "increasing read_avail by %lu bytes to %lu/%lu",
733 (long)(datalen - data_head),
734 (long)channelp->read_avail,
735 (long)channelp->remote.window_size);
736
737 break;
738
739 /*
740 byte SSH_MSG_CHANNEL_EOF
741 uint32 recipient channel
742 */
743
744 case SSH_MSG_CHANNEL_EOF:
745 if(datalen >= 5)
746 channelp =
747 _libssh2_channel_locate(session,
748 _libssh2_ntohu32(data + 1));
749 if (!channelp)
750 /* We may have freed already, just quietly ignore this... */
751 ;
752 else {
753 _libssh2_debug(session,
754 LIBSSH2_TRACE_CONN,
755 "EOF received for channel %lu/%lu",
756 channelp->local.id,
757 channelp->remote.id);
758 channelp->remote.eof = 1;
759 }
760 LIBSSH2_FREE(session, data);
761 session->packAdd_state = libssh2_NB_state_idle;
762 return 0;
763
764 /*
765 byte SSH_MSG_CHANNEL_REQUEST
766 uint32 recipient channel
767 string request type in US-ASCII characters only
768 boolean want reply
769 .... type-specific data follows
770 */
771
772 case SSH_MSG_CHANNEL_REQUEST:
773 if(datalen >= 9) {
774 uint32_t channel = _libssh2_ntohu32(data + 1);
775 uint32_t len = _libssh2_ntohu32(data + 5);
776 unsigned char want_reply = 1;
777
778 if(len < (datalen - 10))
779 want_reply = data[9 + len];
780
781 _libssh2_debug(session,
782 LIBSSH2_TRACE_CONN,
783 "Channel %d received request type %.*s (wr %X)",
784 channel, len, data + 9, want_reply);
785
786 if (len == sizeof("exit-status") - 1
787 && !memcmp("exit-status", data + 9,
788 sizeof("exit-status") - 1)) {
789
790 /* we've got "exit-status" packet. Set the session value */
791 if(datalen >= 20)
792 channelp =
793 _libssh2_channel_locate(session, channel);
794
795 if (channelp) {
796 channelp->exit_status =
797 _libssh2_ntohu32(data + 9 + sizeof("exit-status"));
798 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
799 "Exit status %lu received for "
800 "channel %lu/%lu",
801 channelp->exit_status,
802 channelp->local.id,
803 channelp->remote.id);
804 }
805
806 }
807 else if (len == sizeof("exit-signal") - 1
808 && !memcmp("exit-signal", data + 9,
809 sizeof("exit-signal") - 1)) {
810 /* command terminated due to signal */
811 if(datalen >= 20)
812 channelp = _libssh2_channel_locate(session, channel);
813
814 if (channelp) {
815 /* set signal name (without SIG prefix) */
816 uint32_t namelen =
817 _libssh2_ntohu32(data + 9 + sizeof("exit-signal"));
818 channelp->exit_signal =
819 LIBSSH2_ALLOC(session, namelen + 1);
820 if (!channelp->exit_signal)
821 rc = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
822 "memory for signal name");
823 else {
824 memcpy(channelp->exit_signal,
825 data + 13 + sizeof("exit_signal"), namelen);
826 channelp->exit_signal[namelen] = '\0';
827 /* TODO: save error message and language tag */
828 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
829 "Exit signal %s received for "
830 "channel %lu/%lu",
831 channelp->exit_signal,
832 channelp->local.id,
833 channelp->remote.id);
834 }
835 }
836 }
837
838
839 if (want_reply) {
840 unsigned char packet[5];
841 libssh2_packet_add_jump_point4:
842 session->packAdd_state = libssh2_NB_state_jump4;
843 packet[0] = SSH_MSG_CHANNEL_FAILURE;
844 memcpy(&packet[1], data+1, 4);
845 rc = _libssh2_transport_send(session, packet, 5, NULL, 0);
846 if (rc == LIBSSH2_ERROR_EAGAIN)
847 return rc;
848 }
849 }
850 LIBSSH2_FREE(session, data);
851 session->packAdd_state = libssh2_NB_state_idle;
852 return rc;
853
854 /*
855 byte SSH_MSG_CHANNEL_CLOSE
856 uint32 recipient channel
857 */
858
859 case SSH_MSG_CHANNEL_CLOSE:
860 if(datalen >= 5)
861 channelp =
862 _libssh2_channel_locate(session,
863 _libssh2_ntohu32(data + 1));
864 if (!channelp) {
865 /* We may have freed already, just quietly ignore this... */
866 LIBSSH2_FREE(session, data);
867 session->packAdd_state = libssh2_NB_state_idle;
868 return 0;
869 }
870 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
871 "Close received for channel %lu/%lu",
872 channelp->local.id,
873 channelp->remote.id);
874
875 channelp->remote.close = 1;
876 channelp->remote.eof = 1;
877
878 LIBSSH2_FREE(session, data);
879 session->packAdd_state = libssh2_NB_state_idle;
880 return 0;
881
882 /*
883 byte SSH_MSG_CHANNEL_OPEN
884 string "session"
885 uint32 sender channel
886 uint32 initial window size
887 uint32 maximum packet size
888 */
889
890 case SSH_MSG_CHANNEL_OPEN:
891 if(datalen < 17)
892 ;
893 else if ((datalen >= (sizeof("forwarded-tcpip") + 4)) &&
894 ((sizeof("forwarded-tcpip") - 1) ==
895 _libssh2_ntohu32(data + 1))
896 &&
897 (memcmp(data + 5, "forwarded-tcpip",
898 sizeof("forwarded-tcpip") - 1) == 0)) {
899
900 /* init the state struct */
901 memset(&session->packAdd_Qlstn_state, 0,
902 sizeof(session->packAdd_Qlstn_state));
903
904 libssh2_packet_add_jump_point2:
905 session->packAdd_state = libssh2_NB_state_jump2;
906 rc = packet_queue_listener(session, data, datalen,
907 &session->packAdd_Qlstn_state);
908 }
909 else if ((datalen >= (sizeof("x11") + 4)) &&
910 ((sizeof("x11") - 1) == _libssh2_ntohu32(data + 1)) &&
911 (memcmp(data + 5, "x11", sizeof("x11") - 1) == 0)) {
912
913 /* init the state struct */
914 memset(&session->packAdd_x11open_state, 0,
915 sizeof(session->packAdd_x11open_state));
916
917 libssh2_packet_add_jump_point3:
918 session->packAdd_state = libssh2_NB_state_jump3;
919 rc = packet_x11_open(session, data, datalen,
920 &session->packAdd_x11open_state);
921 }
922 if (rc == LIBSSH2_ERROR_EAGAIN)
923 return rc;
924
925 LIBSSH2_FREE(session, data);
926 session->packAdd_state = libssh2_NB_state_idle;
927 return rc;
928
929 /*
930 byte SSH_MSG_CHANNEL_WINDOW_ADJUST
931 uint32 recipient channel
932 uint32 bytes to add
933 */
934 case SSH_MSG_CHANNEL_WINDOW_ADJUST:
935 if(datalen < 9)
936 ;
937 else {
938 uint32_t bytestoadd = _libssh2_ntohu32(data + 5);
939 channelp =
940 _libssh2_channel_locate(session,
941 _libssh2_ntohu32(data + 1));
942 if(channelp) {
943 channelp->local.window_size += bytestoadd;
944
945 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
946 "Window adjust for channel %lu/%lu, "
947 "adding %lu bytes, new window_size=%lu",
948 channelp->local.id,
949 channelp->remote.id,
950 bytestoadd,
951 channelp->local.window_size);
952 }
953 }
954 LIBSSH2_FREE(session, data);
955 session->packAdd_state = libssh2_NB_state_idle;
956 return 0;
957 default:
958 break;
959 }
960
961 session->packAdd_state = libssh2_NB_state_sent;
962 }
963
964 if (session->packAdd_state == libssh2_NB_state_sent) {
965 LIBSSH2_PACKET *packetp =
966 LIBSSH2_ALLOC(session, sizeof(LIBSSH2_PACKET));
967 if (!packetp) {
968 _libssh2_debug(session, LIBSSH2_ERROR_ALLOC,
969 "memory for packet");
970 LIBSSH2_FREE(session, data);
971 session->packAdd_state = libssh2_NB_state_idle;
972 return LIBSSH2_ERROR_ALLOC;
973 }
974 packetp->data = data;
975 packetp->data_len = datalen;
976 packetp->data_head = data_head;
977
978 _libssh2_list_add(&session->packets, &packetp->node);
979
980 session->packAdd_state = libssh2_NB_state_sent1;
981 }
982
983 if ((msg == SSH_MSG_KEXINIT &&
984 !(session->state & LIBSSH2_STATE_EXCHANGING_KEYS)) ||
985 (session->packAdd_state == libssh2_NB_state_sent2)) {
986 if (session->packAdd_state == libssh2_NB_state_sent1) {
987 /*
988 * Remote wants new keys
989 * Well, it's already in the brigade,
990 * let's just call back into ourselves
991 */
992 _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Renegotiating Keys");
993
994 session->packAdd_state = libssh2_NB_state_sent2;
995 }
996
997 /*
998 * The KEXINIT message has been added to the queue. The packAdd and
999 * readPack states need to be reset because _libssh2_kex_exchange
1000 * (eventually) calls upon _libssh2_transport_read to read the rest of
1001 * the key exchange conversation.
1002 */
1003 session->readPack_state = libssh2_NB_state_idle;
1004 session->packet.total_num = 0;
1005 session->packAdd_state = libssh2_NB_state_idle;
1006 session->fullpacket_state = libssh2_NB_state_idle;
1007
1008 memset(&session->startup_key_state, 0, sizeof(key_exchange_state_t));
1009
1010 /*
1011 * If there was a key reexchange failure, let's just hope we didn't
1012 * send NEWKEYS yet, otherwise remote will drop us like a rock
1013 */
1014 rc = _libssh2_kex_exchange(session, 1, &session->startup_key_state);
1015 if (rc == LIBSSH2_ERROR_EAGAIN)
1016 return rc;
1017 }
1018
1019 session->packAdd_state = libssh2_NB_state_idle;
1020 return 0;
1021 }
1022
1023 /*
1024 * _libssh2_packet_ask
1025 *
1026 * Scan the brigade for a matching packet type, optionally poll the socket for
1027 * a packet first
1028 */
1029 int
_libssh2_packet_ask(LIBSSH2_SESSION * session,unsigned char packet_type,unsigned char ** data,size_t * data_len,int match_ofs,const unsigned char * match_buf,size_t match_len)1030 _libssh2_packet_ask(LIBSSH2_SESSION * session, unsigned char packet_type,
1031 unsigned char **data, size_t *data_len,
1032 int match_ofs, const unsigned char *match_buf,
1033 size_t match_len)
1034 {
1035 LIBSSH2_PACKET *packet = _libssh2_list_first(&session->packets);
1036
1037 _libssh2_debug(session, LIBSSH2_TRACE_TRANS,
1038 "Looking for packet of type: %d", (int) packet_type);
1039
1040 while (packet) {
1041 if (packet->data[0] == packet_type
1042 && (packet->data_len >= (match_ofs + match_len))
1043 && (!match_buf ||
1044 (memcmp(packet->data + match_ofs, match_buf,
1045 match_len) == 0))) {
1046 *data = packet->data;
1047 *data_len = packet->data_len;
1048
1049 /* unlink struct from session->packets */
1050 _libssh2_list_remove(&packet->node);
1051
1052 LIBSSH2_FREE(session, packet);
1053
1054 return 0;
1055 }
1056 packet = _libssh2_list_next(&packet->node);
1057 }
1058 return -1;
1059 }
1060
1061 /*
1062 * libssh2_packet_askv
1063 *
1064 * Scan for any of a list of packet types in the brigade, optionally poll the
1065 * socket for a packet first
1066 */
1067 int
_libssh2_packet_askv(LIBSSH2_SESSION * session,const unsigned char * packet_types,unsigned char ** data,size_t * data_len,int match_ofs,const unsigned char * match_buf,size_t match_len)1068 _libssh2_packet_askv(LIBSSH2_SESSION * session,
1069 const unsigned char *packet_types,
1070 unsigned char **data, size_t *data_len,
1071 int match_ofs,
1072 const unsigned char *match_buf,
1073 size_t match_len)
1074 {
1075 int i, packet_types_len = strlen((char *) packet_types);
1076
1077 for(i = 0; i < packet_types_len; i++) {
1078 if (0 == _libssh2_packet_ask(session, packet_types[i], data,
1079 data_len, match_ofs,
1080 match_buf, match_len)) {
1081 return 0;
1082 }
1083 }
1084
1085 return -1;
1086 }
1087
1088 /*
1089 * _libssh2_packet_require
1090 *
1091 * Loops _libssh2_transport_read() until the packet requested is available
1092 * SSH_DISCONNECT or a SOCKET_DISCONNECTED will cause a bailout
1093 *
1094 * Returns negative on error
1095 * Returns 0 when it has taken care of the requested packet.
1096 */
1097 int
_libssh2_packet_require(LIBSSH2_SESSION * session,unsigned char packet_type,unsigned char ** data,size_t * data_len,int match_ofs,const unsigned char * match_buf,size_t match_len,packet_require_state_t * state)1098 _libssh2_packet_require(LIBSSH2_SESSION * session, unsigned char packet_type,
1099 unsigned char **data, size_t *data_len,
1100 int match_ofs,
1101 const unsigned char *match_buf,
1102 size_t match_len,
1103 packet_require_state_t *state)
1104 {
1105 if (state->start == 0) {
1106 if (_libssh2_packet_ask(session, packet_type, data, data_len,
1107 match_ofs, match_buf,
1108 match_len) == 0) {
1109 /* A packet was available in the packet brigade */
1110 return 0;
1111 }
1112
1113 state->start = time(NULL);
1114 }
1115
1116 while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
1117 int ret = _libssh2_transport_read(session);
1118 if (ret == LIBSSH2_ERROR_EAGAIN)
1119 return ret;
1120 else if (ret < 0) {
1121 state->start = 0;
1122 /* an error which is not just because of blocking */
1123 return ret;
1124 } else if (ret == packet_type) {
1125 /* Be lazy, let packet_ask pull it out of the brigade */
1126 ret = _libssh2_packet_ask(session, packet_type, data, data_len,
1127 match_ofs, match_buf, match_len);
1128 state->start = 0;
1129 return ret;
1130 } else if (ret == 0) {
1131 /* nothing available, wait until data arrives or we time out */
1132 long left = LIBSSH2_READ_TIMEOUT - (long)(time(NULL) -
1133 state->start);
1134
1135 if (left <= 0) {
1136 state->start = 0;
1137 return LIBSSH2_ERROR_TIMEOUT;
1138 }
1139 return -1; /* no packet available yet */
1140 }
1141 }
1142
1143 /* Only reached if the socket died */
1144 return LIBSSH2_ERROR_SOCKET_DISCONNECT;
1145 }
1146
1147 /*
1148 * _libssh2_packet_burn
1149 *
1150 * Loops _libssh2_transport_read() until any packet is available and promptly
1151 * discards it.
1152 * Used during KEX exchange to discard badly guessed KEX_INIT packets
1153 */
1154 int
_libssh2_packet_burn(LIBSSH2_SESSION * session,libssh2_nonblocking_states * state)1155 _libssh2_packet_burn(LIBSSH2_SESSION * session,
1156 libssh2_nonblocking_states * state)
1157 {
1158 unsigned char *data;
1159 size_t data_len;
1160 unsigned char i, all_packets[255];
1161 int ret;
1162
1163 if (*state == libssh2_NB_state_idle) {
1164 for(i = 1; i < 255; i++) {
1165 all_packets[i - 1] = i;
1166 }
1167 all_packets[254] = 0;
1168
1169 if (_libssh2_packet_askv(session, all_packets, &data, &data_len, 0,
1170 NULL, 0) == 0) {
1171 i = data[0];
1172 /* A packet was available in the packet brigade, burn it */
1173 LIBSSH2_FREE(session, data);
1174 return i;
1175 }
1176
1177 _libssh2_debug(session, LIBSSH2_TRACE_TRANS,
1178 "Blocking until packet becomes available to burn");
1179 *state = libssh2_NB_state_created;
1180 }
1181
1182 while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
1183 ret = _libssh2_transport_read(session);
1184 if (ret == LIBSSH2_ERROR_EAGAIN) {
1185 return ret;
1186 } else if (ret < 0) {
1187 *state = libssh2_NB_state_idle;
1188 return ret;
1189 } else if (ret == 0) {
1190 /* FIXME: this might busyloop */
1191 continue;
1192 }
1193
1194 /* Be lazy, let packet_ask pull it out of the brigade */
1195 if (0 ==
1196 _libssh2_packet_ask(session, (unsigned char)ret,
1197 &data, &data_len, 0, NULL, 0)) {
1198 /* Smoke 'em if you got 'em */
1199 LIBSSH2_FREE(session, data);
1200 *state = libssh2_NB_state_idle;
1201 return ret;
1202 }
1203 }
1204
1205 /* Only reached if the socket died */
1206 return LIBSSH2_ERROR_SOCKET_DISCONNECT;
1207 }
1208
1209 /*
1210 * _libssh2_packet_requirev
1211 *
1212 * Loops _libssh2_transport_read() until one of a list of packet types
1213 * requested is available. SSH_DISCONNECT or a SOCKET_DISCONNECTED will cause
1214 * a bailout. packet_types is a null terminated list of packet_type numbers
1215 */
1216
1217 int
_libssh2_packet_requirev(LIBSSH2_SESSION * session,const unsigned char * packet_types,unsigned char ** data,size_t * data_len,int match_ofs,const unsigned char * match_buf,size_t match_len,packet_requirev_state_t * state)1218 _libssh2_packet_requirev(LIBSSH2_SESSION *session,
1219 const unsigned char *packet_types,
1220 unsigned char **data, size_t *data_len,
1221 int match_ofs,
1222 const unsigned char *match_buf, size_t match_len,
1223 packet_requirev_state_t * state)
1224 {
1225 if (_libssh2_packet_askv(session, packet_types, data, data_len, match_ofs,
1226 match_buf, match_len) == 0) {
1227 /* One of the packets listed was available in the packet brigade */
1228 state->start = 0;
1229 return 0;
1230 }
1231
1232 if (state->start == 0) {
1233 state->start = time(NULL);
1234 }
1235
1236 while (session->socket_state != LIBSSH2_SOCKET_DISCONNECTED) {
1237 int ret = _libssh2_transport_read(session);
1238 if ((ret < 0) && (ret != LIBSSH2_ERROR_EAGAIN)) {
1239 state->start = 0;
1240 return ret;
1241 }
1242 if (ret <= 0) {
1243 long left = LIBSSH2_READ_TIMEOUT -
1244 (long)(time(NULL) - state->start);
1245
1246 if (left <= 0) {
1247 state->start = 0;
1248 return LIBSSH2_ERROR_TIMEOUT;
1249 }
1250 else if (ret == LIBSSH2_ERROR_EAGAIN) {
1251 return ret;
1252 }
1253 }
1254
1255 if (strchr((char *) packet_types, ret)) {
1256 /* Be lazy, let packet_ask pull it out of the brigade */
1257 return _libssh2_packet_askv(session, packet_types, data,
1258 data_len, match_ofs, match_buf,
1259 match_len);
1260 }
1261 }
1262
1263 /* Only reached if the socket died */
1264 state->start = 0;
1265 return LIBSSH2_ERROR_SOCKET_DISCONNECT;
1266 }
1267
1268