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