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