1 /* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>
2 * Copyright (c) 2005 Mikhail Gusarov <dottedmag@dottedmag.net>
3 * Copyright (c) 2008-2019 by Daniel Stenberg
4 *
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 #ifdef HAVE_UNISTD_H
43 #include <unistd.h>
44 #endif
45 #include <fcntl.h>
46 #ifdef HAVE_INTTYPES_H
47 #include <inttypes.h>
48 #endif
49 #include <assert.h>
50
51 #include "channel.h"
52 #include "transport.h"
53 #include "packet.h"
54 #include "session.h"
55
56 /*
57 * _libssh2_channel_nextid
58 *
59 * Determine the next channel ID we can use at our end
60 */
61 uint32_t
_libssh2_channel_nextid(LIBSSH2_SESSION * session)62 _libssh2_channel_nextid(LIBSSH2_SESSION * session)
63 {
64 uint32_t id = session->next_channel;
65 LIBSSH2_CHANNEL *channel;
66
67 channel = _libssh2_list_first(&session->channels);
68
69 while(channel) {
70 if(channel->local.id > id) {
71 id = channel->local.id;
72 }
73 channel = _libssh2_list_next(&channel->node);
74 }
75
76 /* This is a shortcut to avoid waiting for close packets on channels we've
77 * forgotten about, This *could* be a problem if we request and close 4
78 * billion or so channels in too rapid succession for the remote end to
79 * respond, but the worst case scenario is that some data meant for
80 * another channel Gets picked up by the new one.... Pretty unlikely all
81 * told...
82 */
83 session->next_channel = id + 1;
84 _libssh2_debug(session, LIBSSH2_TRACE_CONN, "Allocated new channel ID#%lu",
85 id);
86 return id;
87 }
88
89 /*
90 * _libssh2_channel_locate
91 *
92 * Locate a channel pointer by number
93 */
94 LIBSSH2_CHANNEL *
_libssh2_channel_locate(LIBSSH2_SESSION * session,uint32_t channel_id)95 _libssh2_channel_locate(LIBSSH2_SESSION *session, uint32_t channel_id)
96 {
97 LIBSSH2_CHANNEL *channel;
98 LIBSSH2_LISTENER *l;
99
100 for(channel = _libssh2_list_first(&session->channels);
101 channel;
102 channel = _libssh2_list_next(&channel->node)) {
103 if(channel->local.id == channel_id)
104 return channel;
105 }
106
107 /* We didn't find the channel in the session, let's then check its
108 listeners since each listener may have its own set of pending channels
109 */
110 for(l = _libssh2_list_first(&session->listeners); l;
111 l = _libssh2_list_next(&l->node)) {
112 for(channel = _libssh2_list_first(&l->queue);
113 channel;
114 channel = _libssh2_list_next(&channel->node)) {
115 if(channel->local.id == channel_id)
116 return channel;
117 }
118 }
119
120 return NULL;
121 }
122
123 /*
124 * _libssh2_channel_open
125 *
126 * Establish a generic session channel
127 */
128 LIBSSH2_CHANNEL *
_libssh2_channel_open(LIBSSH2_SESSION * session,const char * channel_type,uint32_t channel_type_len,uint32_t window_size,uint32_t packet_size,const unsigned char * message,size_t message_len)129 _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
130 uint32_t channel_type_len,
131 uint32_t window_size,
132 uint32_t packet_size,
133 const unsigned char *message,
134 size_t message_len)
135 {
136 static const unsigned char reply_codes[3] = {
137 SSH_MSG_CHANNEL_OPEN_CONFIRMATION,
138 SSH_MSG_CHANNEL_OPEN_FAILURE,
139 0
140 };
141 unsigned char *s;
142 int rc;
143
144 if(session->open_state == libssh2_NB_state_idle) {
145 session->open_channel = NULL;
146 session->open_packet = NULL;
147 session->open_data = NULL;
148 /* 17 = packet_type(1) + channel_type_len(4) + sender_channel(4) +
149 * window_size(4) + packet_size(4) */
150 session->open_packet_len = channel_type_len + 17;
151 session->open_local_channel = _libssh2_channel_nextid(session);
152
153 /* Zero the whole thing out */
154 memset(&session->open_packet_requirev_state, 0,
155 sizeof(session->open_packet_requirev_state));
156
157 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
158 "Opening Channel - win %d pack %d", window_size,
159 packet_size);
160 session->open_channel =
161 LIBSSH2_CALLOC(session, sizeof(LIBSSH2_CHANNEL));
162 if(!session->open_channel) {
163 _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
164 "Unable to allocate space for channel data");
165 return NULL;
166 }
167 session->open_channel->channel_type_len = channel_type_len;
168 session->open_channel->channel_type =
169 LIBSSH2_ALLOC(session, channel_type_len);
170 if(!session->open_channel->channel_type) {
171 _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
172 "Failed allocating memory for channel type name");
173 LIBSSH2_FREE(session, session->open_channel);
174 session->open_channel = NULL;
175 return NULL;
176 }
177 memcpy(session->open_channel->channel_type, channel_type,
178 channel_type_len);
179
180 /* REMEMBER: local as in locally sourced */
181 session->open_channel->local.id = session->open_local_channel;
182 session->open_channel->remote.window_size = window_size;
183 session->open_channel->remote.window_size_initial = window_size;
184 session->open_channel->remote.packet_size = packet_size;
185 session->open_channel->session = session;
186
187 _libssh2_list_add(&session->channels,
188 &session->open_channel->node);
189
190 s = session->open_packet =
191 LIBSSH2_ALLOC(session, session->open_packet_len);
192 if(!session->open_packet) {
193 _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
194 "Unable to allocate temporary space for packet");
195 goto channel_error;
196 }
197 *(s++) = SSH_MSG_CHANNEL_OPEN;
198 _libssh2_store_str(&s, channel_type, channel_type_len);
199 _libssh2_store_u32(&s, session->open_local_channel);
200 _libssh2_store_u32(&s, window_size);
201 _libssh2_store_u32(&s, packet_size);
202
203 /* Do not copy the message */
204
205 session->open_state = libssh2_NB_state_created;
206 }
207
208 if(session->open_state == libssh2_NB_state_created) {
209 rc = _libssh2_transport_send(session,
210 session->open_packet,
211 session->open_packet_len,
212 message, message_len);
213 if(rc == LIBSSH2_ERROR_EAGAIN) {
214 _libssh2_error(session, rc,
215 "Would block sending channel-open request");
216 return NULL;
217 }
218 else if(rc) {
219 _libssh2_error(session, rc,
220 "Unable to send channel-open request");
221 goto channel_error;
222 }
223
224 session->open_state = libssh2_NB_state_sent;
225 }
226
227 if(session->open_state == libssh2_NB_state_sent) {
228 rc = _libssh2_packet_requirev(session, reply_codes,
229 &session->open_data,
230 &session->open_data_len, 1,
231 session->open_packet + 5 +
232 channel_type_len, 4,
233 &session->open_packet_requirev_state);
234 if(rc == LIBSSH2_ERROR_EAGAIN) {
235 _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
236 return NULL;
237 }
238 else if(rc) {
239 _libssh2_error(session, rc, "Unexpected error");
240 goto channel_error;
241 }
242
243 if(session->open_data_len < 1) {
244 _libssh2_error(session, LIBSSH2_ERROR_PROTO,
245 "Unexpected packet size");
246 goto channel_error;
247 }
248
249 if(session->open_data[0] == SSH_MSG_CHANNEL_OPEN_CONFIRMATION) {
250
251 if(session->open_data_len < 17) {
252 _libssh2_error(session, LIBSSH2_ERROR_PROTO,
253 "Unexpected packet size");
254 goto channel_error;
255 }
256
257 session->open_channel->remote.id =
258 _libssh2_ntohu32(session->open_data + 5);
259 session->open_channel->local.window_size =
260 _libssh2_ntohu32(session->open_data + 9);
261 session->open_channel->local.window_size_initial =
262 _libssh2_ntohu32(session->open_data + 9);
263 session->open_channel->local.packet_size =
264 _libssh2_ntohu32(session->open_data + 13);
265 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
266 "Connection Established - ID: %lu/%lu win: %lu/%lu"
267 " pack: %lu/%lu",
268 session->open_channel->local.id,
269 session->open_channel->remote.id,
270 session->open_channel->local.window_size,
271 session->open_channel->remote.window_size,
272 session->open_channel->local.packet_size,
273 session->open_channel->remote.packet_size);
274 LIBSSH2_FREE(session, session->open_packet);
275 session->open_packet = NULL;
276 LIBSSH2_FREE(session, session->open_data);
277 session->open_data = NULL;
278
279 session->open_state = libssh2_NB_state_idle;
280 return session->open_channel;
281 }
282
283 if(session->open_data[0] == SSH_MSG_CHANNEL_OPEN_FAILURE) {
284 unsigned int reason_code =
285 _libssh2_ntohu32(session->open_data + 5);
286 switch(reason_code) {
287 case SSH_OPEN_ADMINISTRATIVELY_PROHIBITED:
288 _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
289 "Channel open failure "
290 "(administratively prohibited)");
291 break;
292 case SSH_OPEN_CONNECT_FAILED:
293 _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
294 "Channel open failure (connect failed)");
295 break;
296 case SSH_OPEN_UNKNOWN_CHANNELTYPE:
297 _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
298 "Channel open failure (unknown channel type)");
299 break;
300 case SSH_OPEN_RESOURCE_SHORTAGE:
301 _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
302 "Channel open failure (resource shortage)");
303 break;
304 default:
305 _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
306 "Channel open failure");
307 }
308 }
309 }
310
311 channel_error:
312
313 if(session->open_data) {
314 LIBSSH2_FREE(session, session->open_data);
315 session->open_data = NULL;
316 }
317 if(session->open_packet) {
318 LIBSSH2_FREE(session, session->open_packet);
319 session->open_packet = NULL;
320 }
321 if(session->open_channel) {
322 unsigned char channel_id[4];
323 LIBSSH2_FREE(session, session->open_channel->channel_type);
324
325 _libssh2_list_remove(&session->open_channel->node);
326
327 /* Clear out packets meant for this channel */
328 _libssh2_htonu32(channel_id, session->open_channel->local.id);
329 while((_libssh2_packet_ask(session, SSH_MSG_CHANNEL_DATA,
330 &session->open_data,
331 &session->open_data_len, 1,
332 channel_id, 4) >= 0)
333 ||
334 (_libssh2_packet_ask(session, SSH_MSG_CHANNEL_EXTENDED_DATA,
335 &session->open_data,
336 &session->open_data_len, 1,
337 channel_id, 4) >= 0)) {
338 LIBSSH2_FREE(session, session->open_data);
339 session->open_data = NULL;
340 }
341
342 LIBSSH2_FREE(session, session->open_channel);
343 session->open_channel = NULL;
344 }
345
346 session->open_state = libssh2_NB_state_idle;
347 return NULL;
348 }
349
350 /*
351 * libssh2_channel_open_ex
352 *
353 * Establish a generic session channel
354 */
355 LIBSSH2_API LIBSSH2_CHANNEL *
libssh2_channel_open_ex(LIBSSH2_SESSION * session,const char * type,unsigned int type_len,unsigned int window_size,unsigned int packet_size,const char * msg,unsigned int msg_len)356 libssh2_channel_open_ex(LIBSSH2_SESSION *session, const char *type,
357 unsigned int type_len,
358 unsigned int window_size, unsigned int packet_size,
359 const char *msg, unsigned int msg_len)
360 {
361 LIBSSH2_CHANNEL *ptr;
362
363 if(!session)
364 return NULL;
365
366 BLOCK_ADJUST_ERRNO(ptr, session,
367 _libssh2_channel_open(session, type, type_len,
368 window_size, packet_size,
369 (unsigned char *)msg,
370 msg_len));
371 return ptr;
372 }
373
374 /*
375 * libssh2_channel_direct_tcpip_ex
376 *
377 * Tunnel TCP/IP connect through the SSH session to direct host/port
378 */
379 static LIBSSH2_CHANNEL *
channel_direct_tcpip(LIBSSH2_SESSION * session,const char * host,int port,const char * shost,int sport)380 channel_direct_tcpip(LIBSSH2_SESSION * session, const char *host,
381 int port, const char *shost, int sport)
382 {
383 LIBSSH2_CHANNEL *channel;
384 unsigned char *s;
385
386 if(session->direct_state == libssh2_NB_state_idle) {
387 session->direct_host_len = strlen(host);
388 session->direct_shost_len = strlen(shost);
389 /* host_len(4) + port(4) + shost_len(4) + sport(4) */
390 session->direct_message_len =
391 session->direct_host_len + session->direct_shost_len + 16;
392
393 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
394 "Requesting direct-tcpip session from %s:%d to %s:%d",
395 shost, sport, host, port);
396
397 s = session->direct_message =
398 LIBSSH2_ALLOC(session, session->direct_message_len);
399 if(!session->direct_message) {
400 _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
401 "Unable to allocate memory for "
402 "direct-tcpip connection");
403 return NULL;
404 }
405 _libssh2_store_str(&s, host, session->direct_host_len);
406 _libssh2_store_u32(&s, port);
407 _libssh2_store_str(&s, shost, session->direct_shost_len);
408 _libssh2_store_u32(&s, sport);
409 }
410
411 channel =
412 _libssh2_channel_open(session, "direct-tcpip",
413 sizeof("direct-tcpip") - 1,
414 LIBSSH2_CHANNEL_WINDOW_DEFAULT,
415 LIBSSH2_CHANNEL_PACKET_DEFAULT,
416 session->direct_message,
417 session->direct_message_len);
418
419 if(!channel &&
420 libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) {
421 /* The error code is still set to LIBSSH2_ERROR_EAGAIN, set our state
422 to created to avoid re-creating the package on next invoke */
423 session->direct_state = libssh2_NB_state_created;
424 return NULL;
425 }
426 /* by default we set (keep?) idle state... */
427 session->direct_state = libssh2_NB_state_idle;
428
429 LIBSSH2_FREE(session, session->direct_message);
430 session->direct_message = NULL;
431
432 return channel;
433 }
434
435 /*
436 * libssh2_channel_direct_tcpip_ex
437 *
438 * Tunnel TCP/IP connect through the SSH session to direct host/port
439 */
440 LIBSSH2_API LIBSSH2_CHANNEL *
libssh2_channel_direct_tcpip_ex(LIBSSH2_SESSION * session,const char * host,int port,const char * shost,int sport)441 libssh2_channel_direct_tcpip_ex(LIBSSH2_SESSION *session, const char *host,
442 int port, const char *shost, int sport)
443 {
444 LIBSSH2_CHANNEL *ptr;
445
446 if(!session)
447 return NULL;
448
449 BLOCK_ADJUST_ERRNO(ptr, session,
450 channel_direct_tcpip(session, host, port,
451 shost, sport));
452 return ptr;
453 }
454
455 /*
456 * channel_forward_listen
457 *
458 * Bind a port on the remote host and listen for connections
459 */
460 static LIBSSH2_LISTENER *
channel_forward_listen(LIBSSH2_SESSION * session,const char * host,int port,int * bound_port,int queue_maxsize)461 channel_forward_listen(LIBSSH2_SESSION * session, const char *host,
462 int port, int *bound_port, int queue_maxsize)
463 {
464 unsigned char *s;
465 static const unsigned char reply_codes[3] =
466 { SSH_MSG_REQUEST_SUCCESS, SSH_MSG_REQUEST_FAILURE, 0 };
467 int rc;
468
469 if(!host)
470 host = "0.0.0.0";
471
472 if(session->fwdLstn_state == libssh2_NB_state_idle) {
473 session->fwdLstn_host_len = strlen(host);
474 /* 14 = packet_type(1) + request_len(4) + want_replay(1) + host_len(4)
475 + port(4) */
476 session->fwdLstn_packet_len =
477 session->fwdLstn_host_len + (sizeof("tcpip-forward") - 1) + 14;
478
479 /* Zero the whole thing out */
480 memset(&session->fwdLstn_packet_requirev_state, 0,
481 sizeof(session->fwdLstn_packet_requirev_state));
482
483 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
484 "Requesting tcpip-forward session for %s:%d", host,
485 port);
486
487 s = session->fwdLstn_packet =
488 LIBSSH2_ALLOC(session, session->fwdLstn_packet_len);
489 if(!session->fwdLstn_packet) {
490 _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
491 "Unable to allocate memory for setenv packet");
492 return NULL;
493 }
494
495 *(s++) = SSH_MSG_GLOBAL_REQUEST;
496 _libssh2_store_str(&s, "tcpip-forward", sizeof("tcpip-forward") - 1);
497 *(s++) = 0x01; /* want_reply */
498
499 _libssh2_store_str(&s, host, session->fwdLstn_host_len);
500 _libssh2_store_u32(&s, port);
501
502 session->fwdLstn_state = libssh2_NB_state_created;
503 }
504
505 if(session->fwdLstn_state == libssh2_NB_state_created) {
506 rc = _libssh2_transport_send(session,
507 session->fwdLstn_packet,
508 session->fwdLstn_packet_len,
509 NULL, 0);
510 if(rc == LIBSSH2_ERROR_EAGAIN) {
511 _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
512 "Would block sending global-request packet for "
513 "forward listen request");
514 return NULL;
515 }
516 else if(rc) {
517 _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
518 "Unable to send global-request packet for forward "
519 "listen request");
520 LIBSSH2_FREE(session, session->fwdLstn_packet);
521 session->fwdLstn_packet = NULL;
522 session->fwdLstn_state = libssh2_NB_state_idle;
523 return NULL;
524 }
525 LIBSSH2_FREE(session, session->fwdLstn_packet);
526 session->fwdLstn_packet = NULL;
527
528 session->fwdLstn_state = libssh2_NB_state_sent;
529 }
530
531 if(session->fwdLstn_state == libssh2_NB_state_sent) {
532 unsigned char *data;
533 size_t data_len;
534 rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
535 0, NULL, 0,
536 &session->fwdLstn_packet_requirev_state);
537 if(rc == LIBSSH2_ERROR_EAGAIN) {
538 _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
539 return NULL;
540 }
541 else if(rc || (data_len < 1)) {
542 _libssh2_error(session, LIBSSH2_ERROR_PROTO, "Unknown");
543 session->fwdLstn_state = libssh2_NB_state_idle;
544 return NULL;
545 }
546
547 if(data[0] == SSH_MSG_REQUEST_SUCCESS) {
548 LIBSSH2_LISTENER *listener;
549
550 listener = LIBSSH2_CALLOC(session, sizeof(LIBSSH2_LISTENER));
551 if(!listener)
552 _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
553 "Unable to allocate memory for listener queue");
554 else {
555 listener->host =
556 LIBSSH2_ALLOC(session, session->fwdLstn_host_len + 1);
557 if(!listener->host) {
558 _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
559 "Unable to allocate memory "
560 "for listener queue");
561 LIBSSH2_FREE(session, listener);
562 listener = NULL;
563 }
564 else {
565 listener->session = session;
566 memcpy(listener->host, host, session->fwdLstn_host_len);
567 listener->host[session->fwdLstn_host_len] = 0;
568 if(data_len >= 5 && !port) {
569 listener->port = _libssh2_ntohu32(data + 1);
570 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
571 "Dynamic tcpip-forward port "
572 "allocated: %d",
573 listener->port);
574 }
575 else
576 listener->port = port;
577
578 listener->queue_size = 0;
579 listener->queue_maxsize = queue_maxsize;
580
581 /* append this to the parent's list of listeners */
582 _libssh2_list_add(&session->listeners, &listener->node);
583
584 if(bound_port) {
585 *bound_port = listener->port;
586 }
587 }
588 }
589
590 LIBSSH2_FREE(session, data);
591 session->fwdLstn_state = libssh2_NB_state_idle;
592 return listener;
593 }
594 else if(data[0] == SSH_MSG_REQUEST_FAILURE) {
595 LIBSSH2_FREE(session, data);
596 _libssh2_error(session, LIBSSH2_ERROR_REQUEST_DENIED,
597 "Unable to complete request for forward-listen");
598 session->fwdLstn_state = libssh2_NB_state_idle;
599 return NULL;
600 }
601 }
602
603 session->fwdLstn_state = libssh2_NB_state_idle;
604
605 return NULL;
606 }
607
608 /*
609 * libssh2_channel_forward_listen_ex
610 *
611 * Bind a port on the remote host and listen for connections
612 */
613 LIBSSH2_API LIBSSH2_LISTENER *
libssh2_channel_forward_listen_ex(LIBSSH2_SESSION * session,const char * host,int port,int * bound_port,int queue_maxsize)614 libssh2_channel_forward_listen_ex(LIBSSH2_SESSION *session, const char *host,
615 int port, int *bound_port, int queue_maxsize)
616 {
617 LIBSSH2_LISTENER *ptr;
618
619 if(!session)
620 return NULL;
621
622 BLOCK_ADJUST_ERRNO(ptr, session,
623 channel_forward_listen(session, host, port, bound_port,
624 queue_maxsize));
625 return ptr;
626 }
627
628 /*
629 * _libssh2_channel_forward_cancel
630 *
631 * Stop listening on a remote port and free the listener
632 * Toss out any pending (un-accept()ed) connections
633 *
634 * Return 0 on success, LIBSSH2_ERROR_EAGAIN if would block, -1 on error
635 */
_libssh2_channel_forward_cancel(LIBSSH2_LISTENER * listener)636 int _libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener)
637 {
638 LIBSSH2_SESSION *session = listener->session;
639 LIBSSH2_CHANNEL *queued;
640 unsigned char *packet, *s;
641 size_t host_len = strlen(listener->host);
642 /* 14 = packet_type(1) + request_len(4) + want_replay(1) + host_len(4) +
643 port(4) */
644 size_t packet_len =
645 host_len + 14 + sizeof("cancel-tcpip-forward") - 1;
646 int rc;
647 int retcode = 0;
648
649 if(listener->chanFwdCncl_state == libssh2_NB_state_idle) {
650 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
651 "Cancelling tcpip-forward session for %s:%d",
652 listener->host, listener->port);
653
654 s = packet = LIBSSH2_ALLOC(session, packet_len);
655 if(!packet) {
656 _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
657 "Unable to allocate memory for setenv packet");
658 return LIBSSH2_ERROR_ALLOC;
659 }
660
661 *(s++) = SSH_MSG_GLOBAL_REQUEST;
662 _libssh2_store_str(&s, "cancel-tcpip-forward",
663 sizeof("cancel-tcpip-forward") - 1);
664 *(s++) = 0x00; /* want_reply */
665
666 _libssh2_store_str(&s, listener->host, host_len);
667 _libssh2_store_u32(&s, listener->port);
668
669 listener->chanFwdCncl_state = libssh2_NB_state_created;
670 }
671 else {
672 packet = listener->chanFwdCncl_data;
673 }
674
675 if(listener->chanFwdCncl_state == libssh2_NB_state_created) {
676 rc = _libssh2_transport_send(session, packet, packet_len, NULL, 0);
677 if(rc == LIBSSH2_ERROR_EAGAIN) {
678 _libssh2_error(session, rc,
679 "Would block sending forward request");
680 listener->chanFwdCncl_data = packet;
681 return rc;
682 }
683 else if(rc) {
684 _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
685 "Unable to send global-request packet for forward "
686 "listen request");
687 /* set the state to something we don't check for, for the
688 unfortunate situation where we get an EAGAIN further down
689 when trying to bail out due to errors! */
690 listener->chanFwdCncl_state = libssh2_NB_state_sent;
691 retcode = LIBSSH2_ERROR_SOCKET_SEND;
692 }
693 LIBSSH2_FREE(session, packet);
694
695 listener->chanFwdCncl_state = libssh2_NB_state_sent;
696 }
697
698 queued = _libssh2_list_first(&listener->queue);
699 while(queued) {
700 LIBSSH2_CHANNEL *next = _libssh2_list_next(&queued->node);
701
702 rc = _libssh2_channel_free(queued);
703 if(rc == LIBSSH2_ERROR_EAGAIN) {
704 return rc;
705 }
706 queued = next;
707 }
708 LIBSSH2_FREE(session, listener->host);
709
710 /* remove this entry from the parent's list of listeners */
711 _libssh2_list_remove(&listener->node);
712
713 LIBSSH2_FREE(session, listener);
714
715 return retcode;
716 }
717
718 /*
719 * libssh2_channel_forward_cancel
720 *
721 * Stop listening on a remote port and free the listener
722 * Toss out any pending (un-accept()ed) connections
723 *
724 * Return 0 on success, LIBSSH2_ERROR_EAGAIN if would block, -1 on error
725 */
726 LIBSSH2_API int
libssh2_channel_forward_cancel(LIBSSH2_LISTENER * listener)727 libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener)
728 {
729 int rc;
730
731 if(!listener)
732 return LIBSSH2_ERROR_BAD_USE;
733
734 BLOCK_ADJUST(rc, listener->session,
735 _libssh2_channel_forward_cancel(listener));
736 return rc;
737 }
738
739 /*
740 * channel_forward_accept
741 *
742 * Accept a connection
743 */
744 static LIBSSH2_CHANNEL *
channel_forward_accept(LIBSSH2_LISTENER * listener)745 channel_forward_accept(LIBSSH2_LISTENER *listener)
746 {
747 int rc;
748
749 do {
750 rc = _libssh2_transport_read(listener->session);
751 } while(rc > 0);
752
753 if(_libssh2_list_first(&listener->queue)) {
754 LIBSSH2_CHANNEL *channel = _libssh2_list_first(&listener->queue);
755
756 /* detach channel from listener's queue */
757 _libssh2_list_remove(&channel->node);
758
759 listener->queue_size--;
760
761 /* add channel to session's channel list */
762 _libssh2_list_add(&channel->session->channels, &channel->node);
763
764 return channel;
765 }
766
767 if(rc == LIBSSH2_ERROR_EAGAIN) {
768 _libssh2_error(listener->session, LIBSSH2_ERROR_EAGAIN,
769 "Would block waiting for packet");
770 }
771 else
772 _libssh2_error(listener->session, LIBSSH2_ERROR_CHANNEL_UNKNOWN,
773 "Channel not found");
774 return NULL;
775 }
776
777 /*
778 * libssh2_channel_forward_accept
779 *
780 * Accept a connection
781 */
782 LIBSSH2_API LIBSSH2_CHANNEL *
libssh2_channel_forward_accept(LIBSSH2_LISTENER * listener)783 libssh2_channel_forward_accept(LIBSSH2_LISTENER *listener)
784 {
785 LIBSSH2_CHANNEL *ptr;
786
787 if(!listener)
788 return NULL;
789
790 BLOCK_ADJUST_ERRNO(ptr, listener->session,
791 channel_forward_accept(listener));
792 return ptr;
793
794 }
795
796 /*
797 * channel_setenv
798 *
799 * Set an environment variable prior to requesting a shell/program/subsystem
800 */
channel_setenv(LIBSSH2_CHANNEL * channel,const char * varname,unsigned int varname_len,const char * value,unsigned int value_len)801 static int channel_setenv(LIBSSH2_CHANNEL *channel,
802 const char *varname, unsigned int varname_len,
803 const char *value, unsigned int value_len)
804 {
805 LIBSSH2_SESSION *session = channel->session;
806 unsigned char *s, *data;
807 static const unsigned char reply_codes[3] =
808 { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
809 size_t data_len;
810 int rc;
811
812 if(channel->setenv_state == libssh2_NB_state_idle) {
813 /* 21 = packet_type(1) + channel_id(4) + request_len(4) +
814 * request(3)"env" + want_reply(1) + varname_len(4) + value_len(4) */
815 channel->setenv_packet_len = varname_len + value_len + 21;
816
817 /* Zero the whole thing out */
818 memset(&channel->setenv_packet_requirev_state, 0,
819 sizeof(channel->setenv_packet_requirev_state));
820
821 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
822 "Setting remote environment variable: %s=%s on "
823 "channel %lu/%lu",
824 varname, value, channel->local.id, channel->remote.id);
825
826 s = channel->setenv_packet =
827 LIBSSH2_ALLOC(session, channel->setenv_packet_len);
828 if(!channel->setenv_packet) {
829 return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
830 "Unable to allocate memory "
831 "for setenv packet");
832 }
833
834 *(s++) = SSH_MSG_CHANNEL_REQUEST;
835 _libssh2_store_u32(&s, channel->remote.id);
836 _libssh2_store_str(&s, "env", sizeof("env") - 1);
837 *(s++) = 0x01;
838 _libssh2_store_str(&s, varname, varname_len);
839 _libssh2_store_str(&s, value, value_len);
840
841 channel->setenv_state = libssh2_NB_state_created;
842 }
843
844 if(channel->setenv_state == libssh2_NB_state_created) {
845 rc = _libssh2_transport_send(session,
846 channel->setenv_packet,
847 channel->setenv_packet_len,
848 NULL, 0);
849 if(rc == LIBSSH2_ERROR_EAGAIN) {
850 _libssh2_error(session, rc,
851 "Would block sending setenv request");
852 return rc;
853 }
854 else if(rc) {
855 LIBSSH2_FREE(session, channel->setenv_packet);
856 channel->setenv_packet = NULL;
857 channel->setenv_state = libssh2_NB_state_idle;
858 return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
859 "Unable to send channel-request packet for "
860 "setenv request");
861 }
862 LIBSSH2_FREE(session, channel->setenv_packet);
863 channel->setenv_packet = NULL;
864
865 _libssh2_htonu32(channel->setenv_local_channel, channel->local.id);
866
867 channel->setenv_state = libssh2_NB_state_sent;
868 }
869
870 if(channel->setenv_state == libssh2_NB_state_sent) {
871 rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
872 1, channel->setenv_local_channel, 4,
873 &channel->
874 setenv_packet_requirev_state);
875 if(rc == LIBSSH2_ERROR_EAGAIN) {
876 return rc;
877 }
878 if(rc) {
879 channel->setenv_state = libssh2_NB_state_idle;
880 return rc;
881 }
882 else if(data_len < 1) {
883 channel->setenv_state = libssh2_NB_state_idle;
884 return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
885 "Unexpected packet size");
886 }
887
888 if(data[0] == SSH_MSG_CHANNEL_SUCCESS) {
889 LIBSSH2_FREE(session, data);
890 channel->setenv_state = libssh2_NB_state_idle;
891 return 0;
892 }
893
894 LIBSSH2_FREE(session, data);
895 }
896
897 channel->setenv_state = libssh2_NB_state_idle;
898 return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
899 "Unable to complete request for channel-setenv");
900 }
901
902 /*
903 * libssh2_channel_setenv_ex
904 *
905 * Set an environment variable prior to requesting a shell/program/subsystem
906 */
907 LIBSSH2_API int
libssh2_channel_setenv_ex(LIBSSH2_CHANNEL * channel,const char * varname,unsigned int varname_len,const char * value,unsigned int value_len)908 libssh2_channel_setenv_ex(LIBSSH2_CHANNEL *channel,
909 const char *varname, unsigned int varname_len,
910 const char *value, unsigned int value_len)
911 {
912 int rc;
913
914 if(!channel)
915 return LIBSSH2_ERROR_BAD_USE;
916
917 BLOCK_ADJUST(rc, channel->session,
918 channel_setenv(channel, varname, varname_len,
919 value, value_len));
920 return rc;
921 }
922
923 /*
924 * channel_request_pty
925 * Duh... Request a PTY
926 */
channel_request_pty(LIBSSH2_CHANNEL * channel,const char * term,unsigned int term_len,const char * modes,unsigned int modes_len,int width,int height,int width_px,int height_px)927 static int channel_request_pty(LIBSSH2_CHANNEL *channel,
928 const char *term, unsigned int term_len,
929 const char *modes, unsigned int modes_len,
930 int width, int height,
931 int width_px, int height_px)
932 {
933 LIBSSH2_SESSION *session = channel->session;
934 unsigned char *s;
935 static const unsigned char reply_codes[3] =
936 { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
937 int rc;
938
939 if(channel->reqPTY_state == libssh2_NB_state_idle) {
940 /* 41 = packet_type(1) + channel(4) + pty_req_len(4) + "pty_req"(7) +
941 * want_reply(1) + term_len(4) + width(4) + height(4) + width_px(4) +
942 * height_px(4) + modes_len(4) */
943 if(term_len + modes_len > 256) {
944 return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
945 "term + mode lengths too large");
946 }
947
948 channel->reqPTY_packet_len = term_len + modes_len + 41;
949
950 /* Zero the whole thing out */
951 memset(&channel->reqPTY_packet_requirev_state, 0,
952 sizeof(channel->reqPTY_packet_requirev_state));
953
954 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
955 "Allocating tty on channel %lu/%lu", channel->local.id,
956 channel->remote.id);
957
958 s = channel->reqPTY_packet;
959
960 *(s++) = SSH_MSG_CHANNEL_REQUEST;
961 _libssh2_store_u32(&s, channel->remote.id);
962 _libssh2_store_str(&s, (char *)"pty-req", sizeof("pty-req") - 1);
963
964 *(s++) = 0x01;
965
966 _libssh2_store_str(&s, term, term_len);
967 _libssh2_store_u32(&s, width);
968 _libssh2_store_u32(&s, height);
969 _libssh2_store_u32(&s, width_px);
970 _libssh2_store_u32(&s, height_px);
971 _libssh2_store_str(&s, modes, modes_len);
972
973 channel->reqPTY_state = libssh2_NB_state_created;
974 }
975
976 if(channel->reqPTY_state == libssh2_NB_state_created) {
977 rc = _libssh2_transport_send(session, channel->reqPTY_packet,
978 channel->reqPTY_packet_len,
979 NULL, 0);
980 if(rc == LIBSSH2_ERROR_EAGAIN) {
981 _libssh2_error(session, rc,
982 "Would block sending pty request");
983 return rc;
984 }
985 else if(rc) {
986 channel->reqPTY_state = libssh2_NB_state_idle;
987 return _libssh2_error(session, rc,
988 "Unable to send pty-request packet");
989 }
990 _libssh2_htonu32(channel->reqPTY_local_channel, channel->local.id);
991
992 channel->reqPTY_state = libssh2_NB_state_sent;
993 }
994
995 if(channel->reqPTY_state == libssh2_NB_state_sent) {
996 unsigned char *data;
997 size_t data_len;
998 unsigned char code;
999 rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
1000 1, channel->reqPTY_local_channel, 4,
1001 &channel->reqPTY_packet_requirev_state);
1002 if(rc == LIBSSH2_ERROR_EAGAIN) {
1003 return rc;
1004 }
1005 else if(rc || data_len < 1) {
1006 channel->reqPTY_state = libssh2_NB_state_idle;
1007 return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
1008 "Failed to require the PTY package");
1009 }
1010
1011 code = data[0];
1012
1013 LIBSSH2_FREE(session, data);
1014 channel->reqPTY_state = libssh2_NB_state_idle;
1015
1016 if(code == SSH_MSG_CHANNEL_SUCCESS)
1017 return 0;
1018 }
1019
1020 return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
1021 "Unable to complete request for "
1022 "channel request-pty");
1023 }
1024
1025 /*
1026 * libssh2_channel_request_pty_ex
1027 * Duh... Request a PTY
1028 */
1029 LIBSSH2_API int
libssh2_channel_request_pty_ex(LIBSSH2_CHANNEL * channel,const char * term,unsigned int term_len,const char * modes,unsigned int modes_len,int width,int height,int width_px,int height_px)1030 libssh2_channel_request_pty_ex(LIBSSH2_CHANNEL *channel, const char *term,
1031 unsigned int term_len, const char *modes,
1032 unsigned int modes_len, int width, int height,
1033 int width_px, int height_px)
1034 {
1035 int rc;
1036
1037 if(!channel)
1038 return LIBSSH2_ERROR_BAD_USE;
1039
1040 BLOCK_ADJUST(rc, channel->session,
1041 channel_request_pty(channel, term, term_len, modes,
1042 modes_len, width, height,
1043 width_px, height_px));
1044 return rc;
1045 }
1046
1047 static int
channel_request_pty_size(LIBSSH2_CHANNEL * channel,int width,int height,int width_px,int height_px)1048 channel_request_pty_size(LIBSSH2_CHANNEL * channel, int width,
1049 int height, int width_px, int height_px)
1050 {
1051 LIBSSH2_SESSION *session = channel->session;
1052 unsigned char *s;
1053 int rc;
1054 int retcode = LIBSSH2_ERROR_PROTO;
1055
1056 if(channel->reqPTY_state == libssh2_NB_state_idle) {
1057 channel->reqPTY_packet_len = 39;
1058
1059 /* Zero the whole thing out */
1060 memset(&channel->reqPTY_packet_requirev_state, 0,
1061 sizeof(channel->reqPTY_packet_requirev_state));
1062
1063 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
1064 "changing tty size on channel %lu/%lu",
1065 channel->local.id,
1066 channel->remote.id);
1067
1068 s = channel->reqPTY_packet;
1069
1070 *(s++) = SSH_MSG_CHANNEL_REQUEST;
1071 _libssh2_store_u32(&s, channel->remote.id);
1072 _libssh2_store_str(&s, (char *)"window-change",
1073 sizeof("window-change") - 1);
1074 *(s++) = 0x00; /* Don't reply */
1075 _libssh2_store_u32(&s, width);
1076 _libssh2_store_u32(&s, height);
1077 _libssh2_store_u32(&s, width_px);
1078 _libssh2_store_u32(&s, height_px);
1079
1080 channel->reqPTY_state = libssh2_NB_state_created;
1081 }
1082
1083 if(channel->reqPTY_state == libssh2_NB_state_created) {
1084 rc = _libssh2_transport_send(session, channel->reqPTY_packet,
1085 channel->reqPTY_packet_len,
1086 NULL, 0);
1087 if(rc == LIBSSH2_ERROR_EAGAIN) {
1088 _libssh2_error(session, rc,
1089 "Would block sending window-change request");
1090 return rc;
1091 }
1092 else if(rc) {
1093 channel->reqPTY_state = libssh2_NB_state_idle;
1094 return _libssh2_error(session, rc,
1095 "Unable to send window-change packet");
1096 }
1097 _libssh2_htonu32(channel->reqPTY_local_channel, channel->local.id);
1098 retcode = LIBSSH2_ERROR_NONE;
1099 }
1100
1101 channel->reqPTY_state = libssh2_NB_state_idle;
1102 return retcode;
1103 }
1104
1105 LIBSSH2_API int
libssh2_channel_request_pty_size_ex(LIBSSH2_CHANNEL * channel,int width,int height,int width_px,int height_px)1106 libssh2_channel_request_pty_size_ex(LIBSSH2_CHANNEL *channel, int width,
1107 int height, int width_px, int height_px)
1108 {
1109 int rc;
1110
1111 if(!channel)
1112 return LIBSSH2_ERROR_BAD_USE;
1113
1114 BLOCK_ADJUST(rc, channel->session,
1115 channel_request_pty_size(channel, width, height, width_px,
1116 height_px));
1117 return rc;
1118 }
1119
1120 /* Keep this an even number */
1121 #define LIBSSH2_X11_RANDOM_COOKIE_LEN 32
1122
1123 /*
1124 * channel_x11_req
1125 * Request X11 forwarding
1126 */
1127 static int
channel_x11_req(LIBSSH2_CHANNEL * channel,int single_connection,const char * auth_proto,const char * auth_cookie,int screen_number)1128 channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection,
1129 const char *auth_proto, const char *auth_cookie,
1130 int screen_number)
1131 {
1132 LIBSSH2_SESSION *session = channel->session;
1133 unsigned char *s;
1134 static const unsigned char reply_codes[3] =
1135 { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
1136 size_t proto_len =
1137 auth_proto ? strlen(auth_proto) : (sizeof("MIT-MAGIC-COOKIE-1") - 1);
1138 size_t cookie_len =
1139 auth_cookie ? strlen(auth_cookie) : LIBSSH2_X11_RANDOM_COOKIE_LEN;
1140 int rc;
1141
1142 if(channel->reqX11_state == libssh2_NB_state_idle) {
1143 /* 30 = packet_type(1) + channel(4) + x11_req_len(4) + "x11-req"(7) +
1144 * want_reply(1) + single_cnx(1) + proto_len(4) + cookie_len(4) +
1145 * screen_num(4) */
1146 channel->reqX11_packet_len = proto_len + cookie_len + 30;
1147
1148 /* Zero the whole thing out */
1149 memset(&channel->reqX11_packet_requirev_state, 0,
1150 sizeof(channel->reqX11_packet_requirev_state));
1151
1152 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
1153 "Requesting x11-req for channel %lu/%lu: single=%d "
1154 "proto=%s cookie=%s screen=%d",
1155 channel->local.id, channel->remote.id,
1156 single_connection,
1157 auth_proto ? auth_proto : "MIT-MAGIC-COOKIE-1",
1158 auth_cookie ? auth_cookie : "<random>", screen_number);
1159
1160 s = channel->reqX11_packet =
1161 LIBSSH2_ALLOC(session, channel->reqX11_packet_len);
1162 if(!channel->reqX11_packet) {
1163 return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1164 "Unable to allocate memory for pty-request");
1165 }
1166
1167 *(s++) = SSH_MSG_CHANNEL_REQUEST;
1168 _libssh2_store_u32(&s, channel->remote.id);
1169 _libssh2_store_str(&s, "x11-req", sizeof("x11-req") - 1);
1170
1171 *(s++) = 0x01; /* want_reply */
1172 *(s++) = single_connection ? 0x01 : 0x00;
1173
1174 _libssh2_store_str(&s, auth_proto ? auth_proto : "MIT-MAGIC-COOKIE-1",
1175 proto_len);
1176
1177 _libssh2_store_u32(&s, cookie_len);
1178 if(auth_cookie) {
1179 memcpy(s, auth_cookie, cookie_len);
1180 }
1181 else {
1182 int i;
1183 /* note: the extra +1 below is necessary since the sprintf()
1184 loop will always write 3 bytes so the last one will write
1185 the trailing zero at the LIBSSH2_X11_RANDOM_COOKIE_LEN/2
1186 border */
1187 unsigned char buffer[(LIBSSH2_X11_RANDOM_COOKIE_LEN / 2) + 1];
1188
1189 _libssh2_random(buffer, LIBSSH2_X11_RANDOM_COOKIE_LEN / 2);
1190 for(i = 0; i < (LIBSSH2_X11_RANDOM_COOKIE_LEN / 2); i++) {
1191 snprintf((char *)&s[i*2], 3, "%02X", buffer[i]);
1192 }
1193 }
1194 s += cookie_len;
1195
1196 _libssh2_store_u32(&s, screen_number);
1197 channel->reqX11_state = libssh2_NB_state_created;
1198 }
1199
1200 if(channel->reqX11_state == libssh2_NB_state_created) {
1201 rc = _libssh2_transport_send(session, channel->reqX11_packet,
1202 channel->reqX11_packet_len,
1203 NULL, 0);
1204 if(rc == LIBSSH2_ERROR_EAGAIN) {
1205 _libssh2_error(session, rc,
1206 "Would block sending X11-req packet");
1207 return rc;
1208 }
1209 if(rc) {
1210 LIBSSH2_FREE(session, channel->reqX11_packet);
1211 channel->reqX11_packet = NULL;
1212 channel->reqX11_state = libssh2_NB_state_idle;
1213 return _libssh2_error(session, rc,
1214 "Unable to send x11-req packet");
1215 }
1216 LIBSSH2_FREE(session, channel->reqX11_packet);
1217 channel->reqX11_packet = NULL;
1218
1219 _libssh2_htonu32(channel->reqX11_local_channel, channel->local.id);
1220
1221 channel->reqX11_state = libssh2_NB_state_sent;
1222 }
1223
1224 if(channel->reqX11_state == libssh2_NB_state_sent) {
1225 size_t data_len;
1226 unsigned char *data;
1227 unsigned char code;
1228
1229 rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
1230 1, channel->reqX11_local_channel, 4,
1231 &channel->reqX11_packet_requirev_state);
1232 if(rc == LIBSSH2_ERROR_EAGAIN) {
1233 return rc;
1234 }
1235 else if(rc || data_len < 1) {
1236 channel->reqX11_state = libssh2_NB_state_idle;
1237 return _libssh2_error(session, rc,
1238 "waiting for x11-req response packet");
1239 }
1240
1241 code = data[0];
1242 LIBSSH2_FREE(session, data);
1243 channel->reqX11_state = libssh2_NB_state_idle;
1244
1245 if(code == SSH_MSG_CHANNEL_SUCCESS)
1246 return 0;
1247 }
1248
1249 return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
1250 "Unable to complete request for channel x11-req");
1251 }
1252
1253 /*
1254 * libssh2_channel_x11_req_ex
1255 * Request X11 forwarding
1256 */
1257 LIBSSH2_API int
libssh2_channel_x11_req_ex(LIBSSH2_CHANNEL * channel,int single_connection,const char * auth_proto,const char * auth_cookie,int screen_number)1258 libssh2_channel_x11_req_ex(LIBSSH2_CHANNEL *channel, int single_connection,
1259 const char *auth_proto, const char *auth_cookie,
1260 int screen_number)
1261 {
1262 int rc;
1263
1264 if(!channel)
1265 return LIBSSH2_ERROR_BAD_USE;
1266
1267 BLOCK_ADJUST(rc, channel->session,
1268 channel_x11_req(channel, single_connection, auth_proto,
1269 auth_cookie, screen_number));
1270 return rc;
1271 }
1272
1273
1274 /*
1275 * _libssh2_channel_process_startup
1276 *
1277 * Primitive for libssh2_channel_(shell|exec|subsystem)
1278 */
1279 int
_libssh2_channel_process_startup(LIBSSH2_CHANNEL * channel,const char * request,size_t request_len,const char * message,size_t message_len)1280 _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
1281 const char *request, size_t request_len,
1282 const char *message, size_t message_len)
1283 {
1284 LIBSSH2_SESSION *session = channel->session;
1285 unsigned char *s;
1286 static const unsigned char reply_codes[3] =
1287 { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
1288 int rc;
1289
1290 if(channel->process_state == libssh2_NB_state_end) {
1291 return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE,
1292 "Channel can not be reused");
1293 }
1294
1295 if(channel->process_state == libssh2_NB_state_idle) {
1296 /* 10 = packet_type(1) + channel(4) + request_len(4) + want_reply(1) */
1297 channel->process_packet_len = request_len + 10;
1298
1299 /* Zero the whole thing out */
1300 memset(&channel->process_packet_requirev_state, 0,
1301 sizeof(channel->process_packet_requirev_state));
1302
1303 if(message)
1304 channel->process_packet_len += + 4;
1305
1306 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
1307 "starting request(%s) on channel %lu/%lu, message=%s",
1308 request, channel->local.id, channel->remote.id,
1309 message ? message : "<null>");
1310 s = channel->process_packet =
1311 LIBSSH2_ALLOC(session, channel->process_packet_len);
1312 if(!channel->process_packet)
1313 return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1314 "Unable to allocate memory "
1315 "for channel-process request");
1316
1317 *(s++) = SSH_MSG_CHANNEL_REQUEST;
1318 _libssh2_store_u32(&s, channel->remote.id);
1319 _libssh2_store_str(&s, request, request_len);
1320 *(s++) = 0x01;
1321
1322 if(message)
1323 _libssh2_store_u32(&s, message_len);
1324
1325 channel->process_state = libssh2_NB_state_created;
1326 }
1327
1328 if(channel->process_state == libssh2_NB_state_created) {
1329 rc = _libssh2_transport_send(session,
1330 channel->process_packet,
1331 channel->process_packet_len,
1332 (unsigned char *)message, message_len);
1333 if(rc == LIBSSH2_ERROR_EAGAIN) {
1334 _libssh2_error(session, rc,
1335 "Would block sending channel request");
1336 return rc;
1337 }
1338 else if(rc) {
1339 LIBSSH2_FREE(session, channel->process_packet);
1340 channel->process_packet = NULL;
1341 channel->process_state = libssh2_NB_state_end;
1342 return _libssh2_error(session, rc,
1343 "Unable to send channel request");
1344 }
1345 LIBSSH2_FREE(session, channel->process_packet);
1346 channel->process_packet = NULL;
1347
1348 _libssh2_htonu32(channel->process_local_channel, channel->local.id);
1349
1350 channel->process_state = libssh2_NB_state_sent;
1351 }
1352
1353 if(channel->process_state == libssh2_NB_state_sent) {
1354 unsigned char *data;
1355 size_t data_len;
1356 unsigned char code;
1357 rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
1358 1, channel->process_local_channel, 4,
1359 &channel->process_packet_requirev_state);
1360 if(rc == LIBSSH2_ERROR_EAGAIN) {
1361 return rc;
1362 }
1363 else if(rc || data_len < 1) {
1364 channel->process_state = libssh2_NB_state_end;
1365 return _libssh2_error(session, rc,
1366 "Failed waiting for channel success");
1367 }
1368
1369 code = data[0];
1370 LIBSSH2_FREE(session, data);
1371 channel->process_state = libssh2_NB_state_end;
1372
1373 if(code == SSH_MSG_CHANNEL_SUCCESS)
1374 return 0;
1375 }
1376
1377 return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
1378 "Unable to complete request for "
1379 "channel-process-startup");
1380 }
1381
1382 /*
1383 * libssh2_channel_process_startup
1384 *
1385 * Primitive for libssh2_channel_(shell|exec|subsystem)
1386 */
1387 LIBSSH2_API int
libssh2_channel_process_startup(LIBSSH2_CHANNEL * channel,const char * req,unsigned int req_len,const char * msg,unsigned int msg_len)1388 libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
1389 const char *req, unsigned int req_len,
1390 const char *msg, unsigned int msg_len)
1391 {
1392 int rc;
1393
1394 if(!channel)
1395 return LIBSSH2_ERROR_BAD_USE;
1396
1397 BLOCK_ADJUST(rc, channel->session,
1398 _libssh2_channel_process_startup(channel, req, req_len,
1399 msg, msg_len));
1400 return rc;
1401 }
1402
1403
1404 /*
1405 * libssh2_channel_set_blocking
1406 *
1407 * Set a channel's BEHAVIOR blocking on or off. The socket will remain non-
1408 * blocking.
1409 */
1410 LIBSSH2_API void
libssh2_channel_set_blocking(LIBSSH2_CHANNEL * channel,int blocking)1411 libssh2_channel_set_blocking(LIBSSH2_CHANNEL * channel, int blocking)
1412 {
1413 if(channel)
1414 (void) _libssh2_session_set_blocking(channel->session, blocking);
1415 }
1416
1417 /*
1418 * _libssh2_channel_flush
1419 *
1420 * Flush data from one (or all) stream
1421 * Returns number of bytes flushed, or negative on failure
1422 */
1423 int
_libssh2_channel_flush(LIBSSH2_CHANNEL * channel,int streamid)1424 _libssh2_channel_flush(LIBSSH2_CHANNEL *channel, int streamid)
1425 {
1426 if(channel->flush_state == libssh2_NB_state_idle) {
1427 LIBSSH2_PACKET *packet =
1428 _libssh2_list_first(&channel->session->packets);
1429 channel->flush_refund_bytes = 0;
1430 channel->flush_flush_bytes = 0;
1431
1432 while(packet) {
1433 unsigned char packet_type;
1434 LIBSSH2_PACKET *next = _libssh2_list_next(&packet->node);
1435
1436 if(packet->data_len < 1) {
1437 packet = next;
1438 _libssh2_debug(channel->session, LIBSSH2_TRACE_ERROR,
1439 "Unexpected packet length");
1440 continue;
1441 }
1442
1443 packet_type = packet->data[0];
1444
1445 if(((packet_type == SSH_MSG_CHANNEL_DATA)
1446 || (packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA))
1447 && ((packet->data_len >= 5)
1448 && (_libssh2_ntohu32(packet->data + 1)
1449 == channel->local.id))) {
1450 /* It's our channel at least */
1451 int packet_stream_id;
1452
1453 if(packet_type == SSH_MSG_CHANNEL_DATA) {
1454 packet_stream_id = 0;
1455 }
1456 else if(packet->data_len >= 9) {
1457 packet_stream_id = _libssh2_ntohu32(packet->data + 5);
1458 }
1459 else {
1460 channel->flush_state = libssh2_NB_state_idle;
1461 return _libssh2_error(channel->session,
1462 LIBSSH2_ERROR_PROTO,
1463 "Unexpected packet length");
1464 }
1465
1466 if((streamid == LIBSSH2_CHANNEL_FLUSH_ALL)
1467 || ((packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA)
1468 && ((streamid == LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA)
1469 || (streamid == packet_stream_id)))
1470 || ((packet_type == SSH_MSG_CHANNEL_DATA)
1471 && (streamid == 0))) {
1472 size_t bytes_to_flush = packet->data_len -
1473 packet->data_head;
1474
1475 _libssh2_debug(channel->session, LIBSSH2_TRACE_CONN,
1476 "Flushing %d bytes of data from stream "
1477 "%lu on channel %lu/%lu",
1478 bytes_to_flush, packet_stream_id,
1479 channel->local.id, channel->remote.id);
1480
1481 /* It's one of the streams we wanted to flush */
1482 channel->flush_refund_bytes += packet->data_len - 13;
1483 channel->flush_flush_bytes += bytes_to_flush;
1484
1485 LIBSSH2_FREE(channel->session, packet->data);
1486
1487 /* remove this packet from the parent's list */
1488 _libssh2_list_remove(&packet->node);
1489 LIBSSH2_FREE(channel->session, packet);
1490 }
1491 }
1492 packet = next;
1493 }
1494
1495 channel->flush_state = libssh2_NB_state_created;
1496 }
1497
1498 channel->read_avail -= channel->flush_flush_bytes;
1499 channel->remote.window_size -= channel->flush_flush_bytes;
1500
1501 if(channel->flush_refund_bytes) {
1502 int rc =
1503 _libssh2_channel_receive_window_adjust(channel,
1504 channel->flush_refund_bytes,
1505 1, NULL);
1506 if(rc == LIBSSH2_ERROR_EAGAIN)
1507 return rc;
1508 }
1509
1510 channel->flush_state = libssh2_NB_state_idle;
1511
1512 return channel->flush_flush_bytes;
1513 }
1514
1515 /*
1516 * libssh2_channel_flush_ex
1517 *
1518 * Flush data from one (or all) stream
1519 * Returns number of bytes flushed, or negative on failure
1520 */
1521 LIBSSH2_API int
libssh2_channel_flush_ex(LIBSSH2_CHANNEL * channel,int stream)1522 libssh2_channel_flush_ex(LIBSSH2_CHANNEL *channel, int stream)
1523 {
1524 int rc;
1525
1526 if(!channel)
1527 return LIBSSH2_ERROR_BAD_USE;
1528
1529 BLOCK_ADJUST(rc, channel->session,
1530 _libssh2_channel_flush(channel, stream));
1531 return rc;
1532 }
1533
1534 /*
1535 * libssh2_channel_get_exit_status
1536 *
1537 * Return the channel's program exit status. Note that the actual protocol
1538 * provides the full 32bit this function returns. We cannot abuse it to
1539 * return error values in case of errors so we return a zero if channel is
1540 * NULL.
1541 */
1542 LIBSSH2_API int
libssh2_channel_get_exit_status(LIBSSH2_CHANNEL * channel)1543 libssh2_channel_get_exit_status(LIBSSH2_CHANNEL *channel)
1544 {
1545 if(!channel)
1546 return 0;
1547
1548 return channel->exit_status;
1549 }
1550
1551 /*
1552 * libssh2_channel_get_exit_signal
1553 *
1554 * Get exit signal (without leading "SIG"), error message, and language
1555 * tag into newly allocated buffers of indicated length. Caller can
1556 * use NULL pointers to indicate that the value should not be set. The
1557 * *_len variables are set if they are non-NULL even if the
1558 * corresponding string parameter is NULL. Returns LIBSSH2_ERROR_NONE
1559 * on success, or an API error code.
1560 */
1561 LIBSSH2_API int
libssh2_channel_get_exit_signal(LIBSSH2_CHANNEL * channel,char ** exitsignal,size_t * exitsignal_len,char ** errmsg,size_t * errmsg_len,char ** langtag,size_t * langtag_len)1562 libssh2_channel_get_exit_signal(LIBSSH2_CHANNEL *channel,
1563 char **exitsignal,
1564 size_t *exitsignal_len,
1565 char **errmsg,
1566 size_t *errmsg_len,
1567 char **langtag,
1568 size_t *langtag_len)
1569 {
1570 size_t namelen = 0;
1571
1572 if(channel) {
1573 LIBSSH2_SESSION *session = channel->session;
1574
1575 if(channel->exit_signal) {
1576 namelen = strlen(channel->exit_signal);
1577 if(exitsignal) {
1578 *exitsignal = LIBSSH2_ALLOC(session, namelen + 1);
1579 if(!*exitsignal) {
1580 return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1581 "Unable to allocate memory for signal name");
1582 }
1583 memcpy(*exitsignal, channel->exit_signal, namelen);
1584 (*exitsignal)[namelen] = '\0';
1585 }
1586 if(exitsignal_len)
1587 *exitsignal_len = namelen;
1588 }
1589 else {
1590 if(exitsignal)
1591 *exitsignal = NULL;
1592 if(exitsignal_len)
1593 *exitsignal_len = 0;
1594 }
1595
1596 /* TODO: set error message and language tag */
1597
1598 if(errmsg)
1599 *errmsg = NULL;
1600
1601 if(errmsg_len)
1602 *errmsg_len = 0;
1603
1604 if(langtag)
1605 *langtag = NULL;
1606
1607 if(langtag_len)
1608 *langtag_len = 0;
1609 }
1610
1611 return LIBSSH2_ERROR_NONE;
1612 }
1613
1614 /*
1615 * _libssh2_channel_receive_window_adjust
1616 *
1617 * Adjust the receive window for a channel by adjustment bytes. If the amount
1618 * to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the
1619 * adjustment amount will be queued for a later packet.
1620 *
1621 * Calls _libssh2_error() !
1622 */
1623 int
_libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,uint32_t adjustment,unsigned char force,unsigned int * store)1624 _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
1625 uint32_t adjustment,
1626 unsigned char force,
1627 unsigned int *store)
1628 {
1629 int rc;
1630
1631 if(store)
1632 *store = channel->remote.window_size;
1633
1634 if(channel->adjust_state == libssh2_NB_state_idle) {
1635 if(!force
1636 && (adjustment + channel->adjust_queue <
1637 LIBSSH2_CHANNEL_MINADJUST)) {
1638 _libssh2_debug(channel->session, LIBSSH2_TRACE_CONN,
1639 "Queueing %lu bytes for receive window adjustment "
1640 "for channel %lu/%lu",
1641 adjustment, channel->local.id, channel->remote.id);
1642 channel->adjust_queue += adjustment;
1643 return 0;
1644 }
1645
1646 if(!adjustment && !channel->adjust_queue) {
1647 return 0;
1648 }
1649
1650 adjustment += channel->adjust_queue;
1651 channel->adjust_queue = 0;
1652
1653 /* Adjust the window based on the block we just freed */
1654 channel->adjust_adjust[0] = SSH_MSG_CHANNEL_WINDOW_ADJUST;
1655 _libssh2_htonu32(&channel->adjust_adjust[1], channel->remote.id);
1656 _libssh2_htonu32(&channel->adjust_adjust[5], adjustment);
1657 _libssh2_debug(channel->session, LIBSSH2_TRACE_CONN,
1658 "Adjusting window %lu bytes for data on "
1659 "channel %lu/%lu",
1660 adjustment, channel->local.id, channel->remote.id);
1661
1662 channel->adjust_state = libssh2_NB_state_created;
1663 }
1664
1665 rc = _libssh2_transport_send(channel->session, channel->adjust_adjust, 9,
1666 NULL, 0);
1667 if(rc == LIBSSH2_ERROR_EAGAIN) {
1668 _libssh2_error(channel->session, rc,
1669 "Would block sending window adjust");
1670 return rc;
1671 }
1672 else if(rc) {
1673 channel->adjust_queue = adjustment;
1674 return _libssh2_error(channel->session, LIBSSH2_ERROR_SOCKET_SEND,
1675 "Unable to send transfer-window adjustment "
1676 "packet, deferring");
1677 }
1678 else {
1679 channel->remote.window_size += adjustment;
1680 }
1681
1682 channel->adjust_state = libssh2_NB_state_idle;
1683
1684 return 0;
1685 }
1686
1687 /*
1688 * libssh2_channel_receive_window_adjust
1689 *
1690 * DEPRECATED
1691 *
1692 * Adjust the receive window for a channel by adjustment bytes. If the amount
1693 * to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the
1694 * adjustment amount will be queued for a later packet.
1695 *
1696 * Returns the new size of the receive window (as understood by remote end).
1697 * Note that it might return EAGAIN too which is highly stupid.
1698 *
1699 */
1700 LIBSSH2_API unsigned long
libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,unsigned long adj,unsigned char force)1701 libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL *channel,
1702 unsigned long adj,
1703 unsigned char force)
1704 {
1705 unsigned int window;
1706 int rc;
1707
1708 if(!channel)
1709 return (unsigned long)LIBSSH2_ERROR_BAD_USE;
1710
1711 BLOCK_ADJUST(rc, channel->session,
1712 _libssh2_channel_receive_window_adjust(channel, adj,
1713 force, &window));
1714
1715 /* stupid - but this is how it was made to work before and this is just
1716 kept for backwards compatibility */
1717 return rc ? (unsigned long)rc : window;
1718 }
1719
1720 /*
1721 * libssh2_channel_receive_window_adjust2
1722 *
1723 * Adjust the receive window for a channel by adjustment bytes. If the amount
1724 * to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the
1725 * adjustment amount will be queued for a later packet.
1726 *
1727 * Stores the new size of the receive window in the data 'window' points to.
1728 *
1729 * Returns the "normal" error code: 0 for success, negative for failure.
1730 */
1731 LIBSSH2_API int
libssh2_channel_receive_window_adjust2(LIBSSH2_CHANNEL * channel,unsigned long adj,unsigned char force,unsigned int * window)1732 libssh2_channel_receive_window_adjust2(LIBSSH2_CHANNEL *channel,
1733 unsigned long adj,
1734 unsigned char force,
1735 unsigned int *window)
1736 {
1737 int rc;
1738
1739 if(!channel)
1740 return LIBSSH2_ERROR_BAD_USE;
1741
1742 BLOCK_ADJUST(rc, channel->session,
1743 _libssh2_channel_receive_window_adjust(channel, adj, force,
1744 window));
1745 return rc;
1746 }
1747
1748 int
_libssh2_channel_extended_data(LIBSSH2_CHANNEL * channel,int ignore_mode)1749 _libssh2_channel_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode)
1750 {
1751 if(channel->extData2_state == libssh2_NB_state_idle) {
1752 _libssh2_debug(channel->session, LIBSSH2_TRACE_CONN,
1753 "Setting channel %lu/%lu handle_extended_data"
1754 " mode to %d",
1755 channel->local.id, channel->remote.id, ignore_mode);
1756 channel->remote.extended_data_ignore_mode = (char)ignore_mode;
1757
1758 channel->extData2_state = libssh2_NB_state_created;
1759 }
1760
1761 if(channel->extData2_state == libssh2_NB_state_idle) {
1762 if(ignore_mode == LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) {
1763 int rc =
1764 _libssh2_channel_flush(channel,
1765 LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA);
1766 if(LIBSSH2_ERROR_EAGAIN == rc)
1767 return rc;
1768 }
1769 }
1770
1771 channel->extData2_state = libssh2_NB_state_idle;
1772 return 0;
1773 }
1774
1775 /*
1776 * libssh2_channel_handle_extended_data2()
1777 *
1778 */
1779 LIBSSH2_API int
libssh2_channel_handle_extended_data2(LIBSSH2_CHANNEL * channel,int mode)1780 libssh2_channel_handle_extended_data2(LIBSSH2_CHANNEL *channel,
1781 int mode)
1782 {
1783 int rc;
1784
1785 if(!channel)
1786 return LIBSSH2_ERROR_BAD_USE;
1787
1788 BLOCK_ADJUST(rc, channel->session, _libssh2_channel_extended_data(channel,
1789 mode));
1790 return rc;
1791 }
1792
1793 /*
1794 * libssh2_channel_handle_extended_data
1795 *
1796 * DEPRECATED DO NOTE USE!
1797 *
1798 * How should extended data look to the calling app? Keep it in separate
1799 * channels[_read() _read_stdder()]? (NORMAL) Merge the extended data to the
1800 * standard data? [everything via _read()]? (MERGE) Ignore it entirely [toss
1801 * out packets as they come in]? (IGNORE)
1802 */
1803 LIBSSH2_API void
libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL * channel,int ignore_mode)1804 libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel,
1805 int ignore_mode)
1806 {
1807 (void)libssh2_channel_handle_extended_data2(channel, ignore_mode);
1808 }
1809
1810
1811
1812 /*
1813 * _libssh2_channel_read
1814 *
1815 * Read data from a channel
1816 *
1817 * It is important to not return 0 until the currently read channel is
1818 * complete. If we read stuff from the wire but it was no payload data to fill
1819 * in the buffer with, we MUST make sure to return LIBSSH2_ERROR_EAGAIN.
1820 *
1821 * The receive window must be maintained (enlarged) by the user of this
1822 * function.
1823 */
_libssh2_channel_read(LIBSSH2_CHANNEL * channel,int stream_id,char * buf,size_t buflen)1824 ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
1825 char *buf, size_t buflen)
1826 {
1827 LIBSSH2_SESSION *session = channel->session;
1828 int rc;
1829 size_t bytes_read = 0;
1830 size_t bytes_want;
1831 int unlink_packet;
1832 LIBSSH2_PACKET *read_packet;
1833 LIBSSH2_PACKET *read_next;
1834
1835 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
1836 "channel_read() wants %d bytes from channel %lu/%lu "
1837 "stream #%d",
1838 (int) buflen, channel->local.id, channel->remote.id,
1839 stream_id);
1840
1841 /* expand the receiving window first if it has become too narrow */
1842 if((channel->read_state == libssh2_NB_state_jump1) ||
1843 (channel->remote.window_size <
1844 channel->remote.window_size_initial / 4 * 3 + buflen) ) {
1845
1846 uint32_t adjustment = channel->remote.window_size_initial + buflen -
1847 channel->remote.window_size;
1848 if(adjustment < LIBSSH2_CHANNEL_MINADJUST)
1849 adjustment = LIBSSH2_CHANNEL_MINADJUST;
1850
1851 /* the actual window adjusting may not finish so we need to deal with
1852 this special state here */
1853 channel->read_state = libssh2_NB_state_jump1;
1854 rc = _libssh2_channel_receive_window_adjust(channel, adjustment,
1855 0, NULL);
1856 if(rc)
1857 return rc;
1858
1859 channel->read_state = libssh2_NB_state_idle;
1860 }
1861
1862 /* Process all pending incoming packets. Tests prove that this way
1863 produces faster transfers. */
1864 do {
1865 rc = _libssh2_transport_read(session);
1866 } while(rc > 0);
1867
1868 if((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN))
1869 return _libssh2_error(session, rc, "transport read");
1870
1871 read_packet = _libssh2_list_first(&session->packets);
1872 while(read_packet && (bytes_read < buflen)) {
1873 /* previously this loop condition also checked for
1874 !channel->remote.close but we cannot let it do this:
1875
1876 We may have a series of packets to read that are still pending even
1877 if a close has been received. Acknowledging the close too early
1878 makes us flush buffers prematurely and loose data.
1879 */
1880
1881 LIBSSH2_PACKET *readpkt = read_packet;
1882
1883 /* In case packet gets destroyed during this iteration */
1884 read_next = _libssh2_list_next(&readpkt->node);
1885
1886 if(readpkt->data_len < 5) {
1887 read_packet = read_next;
1888 _libssh2_debug(channel->session, LIBSSH2_TRACE_ERROR,
1889 "Unexpected packet length");
1890 continue;
1891 }
1892
1893 channel->read_local_id =
1894 _libssh2_ntohu32(readpkt->data + 1);
1895
1896 /*
1897 * Either we asked for a specific extended data stream
1898 * (and data was available),
1899 * or the standard stream (and data was available),
1900 * or the standard stream with extended_data_merge
1901 * enabled and data was available
1902 */
1903 if((stream_id
1904 && (readpkt->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)
1905 && (channel->local.id == channel->read_local_id)
1906 && (readpkt->data_len >= 9)
1907 && (stream_id == (int) _libssh2_ntohu32(readpkt->data + 5)))
1908 || (!stream_id && (readpkt->data[0] == SSH_MSG_CHANNEL_DATA)
1909 && (channel->local.id == channel->read_local_id))
1910 || (!stream_id
1911 && (readpkt->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)
1912 && (channel->local.id == channel->read_local_id)
1913 && (channel->remote.extended_data_ignore_mode ==
1914 LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE))) {
1915
1916 /* figure out much more data we want to read */
1917 bytes_want = buflen - bytes_read;
1918 unlink_packet = FALSE;
1919
1920 if(bytes_want >= (readpkt->data_len - readpkt->data_head)) {
1921 /* we want more than this node keeps, so adjust the number and
1922 delete this node after the copy */
1923 bytes_want = readpkt->data_len - readpkt->data_head;
1924 unlink_packet = TRUE;
1925 }
1926
1927 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
1928 "channel_read() got %d of data from %lu/%lu/%d%s",
1929 bytes_want, channel->local.id,
1930 channel->remote.id, stream_id,
1931 unlink_packet?" [ul]":"");
1932
1933 /* copy data from this struct to the target buffer */
1934 memcpy(&buf[bytes_read],
1935 &readpkt->data[readpkt->data_head], bytes_want);
1936
1937 /* advance pointer and counter */
1938 readpkt->data_head += bytes_want;
1939 bytes_read += bytes_want;
1940
1941 /* if drained, remove from list */
1942 if(unlink_packet) {
1943 /* detach readpkt from session->packets list */
1944 _libssh2_list_remove(&readpkt->node);
1945
1946 LIBSSH2_FREE(session, readpkt->data);
1947 LIBSSH2_FREE(session, readpkt);
1948 }
1949 }
1950
1951 /* check the next struct in the chain */
1952 read_packet = read_next;
1953 }
1954
1955 if(!bytes_read) {
1956 /* If the channel is already at EOF or even closed, we need to signal
1957 that back. We may have gotten that info while draining the incoming
1958 transport layer until EAGAIN so we must not be fooled by that
1959 return code. */
1960 if(channel->remote.eof || channel->remote.close)
1961 return 0;
1962 else if(rc != LIBSSH2_ERROR_EAGAIN)
1963 return 0;
1964
1965 /* if the transport layer said EAGAIN then we say so as well */
1966 return _libssh2_error(session, rc, "would block");
1967 }
1968
1969 channel->read_avail -= bytes_read;
1970 channel->remote.window_size -= bytes_read;
1971
1972 return bytes_read;
1973 }
1974
1975 /*
1976 * libssh2_channel_read_ex
1977 *
1978 * Read data from a channel (blocking or non-blocking depending on set state)
1979 *
1980 * When this is done non-blocking, it is important to not return 0 until the
1981 * currently read channel is complete. If we read stuff from the wire but it
1982 * was no payload data to fill in the buffer with, we MUST make sure to return
1983 * LIBSSH2_ERROR_EAGAIN.
1984 *
1985 * This function will first make sure there's a receive window enough to
1986 * receive a full buffer's wort of contents. An application may choose to
1987 * adjust the receive window more to increase transfer performance.
1988 */
1989 LIBSSH2_API ssize_t
libssh2_channel_read_ex(LIBSSH2_CHANNEL * channel,int stream_id,char * buf,size_t buflen)1990 libssh2_channel_read_ex(LIBSSH2_CHANNEL *channel, int stream_id, char *buf,
1991 size_t buflen)
1992 {
1993 int rc;
1994 unsigned long recv_window;
1995
1996 if(!channel)
1997 return LIBSSH2_ERROR_BAD_USE;
1998
1999 recv_window = libssh2_channel_window_read_ex(channel, NULL, NULL);
2000
2001 if(buflen > recv_window) {
2002 BLOCK_ADJUST(rc, channel->session,
2003 _libssh2_channel_receive_window_adjust(channel, buflen,
2004 1, NULL));
2005 }
2006
2007 BLOCK_ADJUST(rc, channel->session,
2008 _libssh2_channel_read(channel, stream_id, buf, buflen));
2009 return rc;
2010 }
2011
2012 /*
2013 * _libssh2_channel_packet_data_len
2014 *
2015 * Return the size of the data block of the current packet, or 0 if there
2016 * isn't a packet.
2017 */
2018 size_t
_libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel,int stream_id)2019 _libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, int stream_id)
2020 {
2021 LIBSSH2_SESSION *session = channel->session;
2022 LIBSSH2_PACKET *read_packet;
2023 LIBSSH2_PACKET *next_packet;
2024 uint32_t read_local_id;
2025
2026 read_packet = _libssh2_list_first(&session->packets);
2027 if(read_packet == NULL)
2028 return 0;
2029
2030 while(read_packet) {
2031
2032 next_packet = _libssh2_list_next(&read_packet->node);
2033
2034 if(read_packet->data_len < 5) {
2035 read_packet = next_packet;
2036 _libssh2_debug(channel->session, LIBSSH2_TRACE_ERROR,
2037 "Unexpected packet length");
2038 continue;
2039 }
2040
2041 read_local_id = _libssh2_ntohu32(read_packet->data + 1);
2042
2043 /*
2044 * Either we asked for a specific extended data stream
2045 * (and data was available),
2046 * or the standard stream (and data was available),
2047 * or the standard stream with extended_data_merge
2048 * enabled and data was available
2049 */
2050 if((stream_id
2051 && (read_packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)
2052 && (channel->local.id == read_local_id)
2053 && (read_packet->data_len >= 9)
2054 && (stream_id == (int) _libssh2_ntohu32(read_packet->data + 5)))
2055 ||
2056 (!stream_id
2057 && (read_packet->data[0] == SSH_MSG_CHANNEL_DATA)
2058 && (channel->local.id == read_local_id))
2059 ||
2060 (!stream_id
2061 && (read_packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)
2062 && (channel->local.id == read_local_id)
2063 && (channel->remote.extended_data_ignore_mode
2064 == LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE))) {
2065 return (read_packet->data_len - read_packet->data_head);
2066 }
2067
2068 read_packet = next_packet;
2069 }
2070
2071 return 0;
2072 }
2073
2074 /*
2075 * _libssh2_channel_write
2076 *
2077 * Send data to a channel. Note that if this returns EAGAIN, the caller must
2078 * call this function again with the SAME input arguments.
2079 *
2080 * Returns: number of bytes sent, or if it returns a negative number, that is
2081 * the error code!
2082 */
2083 ssize_t
_libssh2_channel_write(LIBSSH2_CHANNEL * channel,int stream_id,const unsigned char * buf,size_t buflen)2084 _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
2085 const unsigned char *buf, size_t buflen)
2086 {
2087 int rc = 0;
2088 LIBSSH2_SESSION *session = channel->session;
2089 ssize_t wrote = 0; /* counter for this specific this call */
2090
2091 /* In theory we could split larger buffers into several smaller packets
2092 * but it turns out to be really hard and nasty to do while still offering
2093 * the API/prototype.
2094 *
2095 * Instead we only deal with the first 32K in this call and for the parent
2096 * function to call it again with the remainder! 32K is a conservative
2097 * limit based on the text in RFC4253 section 6.1.
2098 */
2099 if(buflen > 32700)
2100 buflen = 32700;
2101
2102 if(channel->write_state == libssh2_NB_state_idle) {
2103 unsigned char *s = channel->write_packet;
2104
2105 _libssh2_debug(channel->session, LIBSSH2_TRACE_CONN,
2106 "Writing %d bytes on channel %lu/%lu, stream #%d",
2107 (int) buflen, channel->local.id, channel->remote.id,
2108 stream_id);
2109
2110 if(channel->local.close)
2111 return _libssh2_error(channel->session,
2112 LIBSSH2_ERROR_CHANNEL_CLOSED,
2113 "We've already closed this channel");
2114 else if(channel->local.eof)
2115 return _libssh2_error(channel->session,
2116 LIBSSH2_ERROR_CHANNEL_EOF_SENT,
2117 "EOF has already been received, "
2118 "data might be ignored");
2119
2120 /* drain the incoming flow first, mostly to make sure we get all
2121 * pending window adjust packets */
2122 do
2123 rc = _libssh2_transport_read(session);
2124 while(rc > 0);
2125
2126 if((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN)) {
2127 return _libssh2_error(channel->session, rc,
2128 "Failure while draining incoming flow");
2129 }
2130
2131 if(channel->local.window_size <= 0) {
2132 /* there's no room for data so we stop */
2133
2134 /* Waiting on the socket to be writable would be wrong because we
2135 * would be back here immediately, but a readable socket might
2136 * herald an incoming window adjustment.
2137 */
2138 session->socket_block_directions = LIBSSH2_SESSION_BLOCK_INBOUND;
2139
2140 return (rc == LIBSSH2_ERROR_EAGAIN?rc:0);
2141 }
2142
2143 channel->write_bufwrite = buflen;
2144
2145 *(s++) = stream_id ? SSH_MSG_CHANNEL_EXTENDED_DATA :
2146 SSH_MSG_CHANNEL_DATA;
2147 _libssh2_store_u32(&s, channel->remote.id);
2148 if(stream_id)
2149 _libssh2_store_u32(&s, stream_id);
2150
2151 /* Don't exceed the remote end's limits */
2152 /* REMEMBER local means local as the SOURCE of the data */
2153 if(channel->write_bufwrite > channel->local.window_size) {
2154 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
2155 "Splitting write block due to %lu byte "
2156 "window_size on %lu/%lu/%d",
2157 channel->local.window_size, channel->local.id,
2158 channel->remote.id, stream_id);
2159 channel->write_bufwrite = channel->local.window_size;
2160 }
2161 if(channel->write_bufwrite > channel->local.packet_size) {
2162 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
2163 "Splitting write block due to %lu byte "
2164 "packet_size on %lu/%lu/%d",
2165 channel->local.packet_size, channel->local.id,
2166 channel->remote.id, stream_id);
2167 channel->write_bufwrite = channel->local.packet_size;
2168 }
2169 /* store the size here only, the buffer is passed in as-is to
2170 _libssh2_transport_send() */
2171 _libssh2_store_u32(&s, channel->write_bufwrite);
2172 channel->write_packet_len = s - channel->write_packet;
2173
2174 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
2175 "Sending %d bytes on channel %lu/%lu, stream_id=%d",
2176 (int) channel->write_bufwrite, channel->local.id,
2177 channel->remote.id, stream_id);
2178
2179 channel->write_state = libssh2_NB_state_created;
2180 }
2181
2182 if(channel->write_state == libssh2_NB_state_created) {
2183 rc = _libssh2_transport_send(session, channel->write_packet,
2184 channel->write_packet_len,
2185 buf, channel->write_bufwrite);
2186 if(rc == LIBSSH2_ERROR_EAGAIN) {
2187 return _libssh2_error(session, rc,
2188 "Unable to send channel data");
2189 }
2190 else if(rc) {
2191 channel->write_state = libssh2_NB_state_idle;
2192 return _libssh2_error(session, rc,
2193 "Unable to send channel data");
2194 }
2195 /* Shrink local window size */
2196 channel->local.window_size -= channel->write_bufwrite;
2197
2198 wrote += channel->write_bufwrite;
2199
2200 /* Since _libssh2_transport_write() succeeded, we must return
2201 now to allow the caller to provide the next chunk of data.
2202
2203 We cannot move on to send the next piece of data that may
2204 already have been provided in this same function call, as we
2205 risk getting EAGAIN for that and we can't return information
2206 both about sent data as well as EAGAIN. So, by returning short
2207 now, the caller will call this function again with new data to
2208 send */
2209
2210 channel->write_state = libssh2_NB_state_idle;
2211
2212 return wrote;
2213 }
2214
2215 return LIBSSH2_ERROR_INVAL; /* reaching this point is really bad */
2216 }
2217
2218 /*
2219 * libssh2_channel_write_ex
2220 *
2221 * Send data to a channel
2222 */
2223 LIBSSH2_API ssize_t
libssh2_channel_write_ex(LIBSSH2_CHANNEL * channel,int stream_id,const char * buf,size_t buflen)2224 libssh2_channel_write_ex(LIBSSH2_CHANNEL *channel, int stream_id,
2225 const char *buf, size_t buflen)
2226 {
2227 ssize_t rc;
2228
2229 if(!channel)
2230 return LIBSSH2_ERROR_BAD_USE;
2231
2232 BLOCK_ADJUST(rc, channel->session,
2233 _libssh2_channel_write(channel, stream_id,
2234 (unsigned char *)buf, buflen));
2235 return rc;
2236 }
2237
2238 /*
2239 * channel_send_eof
2240 *
2241 * Send EOF on channel
2242 */
channel_send_eof(LIBSSH2_CHANNEL * channel)2243 static int channel_send_eof(LIBSSH2_CHANNEL *channel)
2244 {
2245 LIBSSH2_SESSION *session = channel->session;
2246 unsigned char packet[5]; /* packet_type(1) + channelno(4) */
2247 int rc;
2248
2249 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
2250 "Sending EOF on channel %lu/%lu",
2251 channel->local.id, channel->remote.id);
2252 packet[0] = SSH_MSG_CHANNEL_EOF;
2253 _libssh2_htonu32(packet + 1, channel->remote.id);
2254 rc = _libssh2_transport_send(session, packet, 5, NULL, 0);
2255 if(rc == LIBSSH2_ERROR_EAGAIN) {
2256 _libssh2_error(session, rc,
2257 "Would block sending EOF");
2258 return rc;
2259 }
2260 else if(rc) {
2261 return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
2262 "Unable to send EOF on channel");
2263 }
2264 channel->local.eof = 1;
2265
2266 return 0;
2267 }
2268
2269 /*
2270 * libssh2_channel_send_eof
2271 *
2272 * Send EOF on channel
2273 */
2274 LIBSSH2_API int
libssh2_channel_send_eof(LIBSSH2_CHANNEL * channel)2275 libssh2_channel_send_eof(LIBSSH2_CHANNEL *channel)
2276 {
2277 int rc;
2278
2279 if(!channel)
2280 return LIBSSH2_ERROR_BAD_USE;
2281
2282 BLOCK_ADJUST(rc, channel->session, channel_send_eof(channel));
2283 return rc;
2284 }
2285
2286 /*
2287 * libssh2_channel_eof
2288 *
2289 * Read channel's eof status
2290 */
2291 LIBSSH2_API int
libssh2_channel_eof(LIBSSH2_CHANNEL * channel)2292 libssh2_channel_eof(LIBSSH2_CHANNEL * channel)
2293 {
2294 LIBSSH2_SESSION *session;
2295 LIBSSH2_PACKET *packet;
2296 LIBSSH2_PACKET *next_packet;
2297
2298 if(!channel)
2299 return LIBSSH2_ERROR_BAD_USE;
2300
2301 session = channel->session;
2302 packet = _libssh2_list_first(&session->packets);
2303
2304 while(packet) {
2305
2306 next_packet = _libssh2_list_next(&packet->node);
2307
2308 if(packet->data_len < 1) {
2309 packet = next_packet;
2310 _libssh2_debug(channel->session, LIBSSH2_TRACE_ERROR,
2311 "Unexpected packet length");
2312 continue;
2313 }
2314
2315 if(((packet->data[0] == SSH_MSG_CHANNEL_DATA)
2316 || (packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA))
2317 && ((packet->data_len >= 5)
2318 && (channel->local.id == _libssh2_ntohu32(packet->data + 1)))) {
2319 /* There's data waiting to be read yet, mask the EOF status */
2320 return 0;
2321 }
2322 packet = next_packet;
2323 }
2324
2325 return channel->remote.eof;
2326 }
2327
2328 /*
2329 * channel_wait_eof
2330 *
2331 * Awaiting channel EOF
2332 */
channel_wait_eof(LIBSSH2_CHANNEL * channel)2333 static int channel_wait_eof(LIBSSH2_CHANNEL *channel)
2334 {
2335 LIBSSH2_SESSION *session = channel->session;
2336 int rc;
2337
2338 if(channel->wait_eof_state == libssh2_NB_state_idle) {
2339 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
2340 "Awaiting EOF for channel %lu/%lu", channel->local.id,
2341 channel->remote.id);
2342
2343 channel->wait_eof_state = libssh2_NB_state_created;
2344 }
2345
2346 /*
2347 * While channel is not eof, read more packets from the network.
2348 * Either the EOF will be set or network timeout will occur.
2349 */
2350 do {
2351 if(channel->remote.eof) {
2352 break;
2353 }
2354
2355 if((channel->remote.window_size == channel->read_avail) &&
2356 session->api_block_mode)
2357 return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_WINDOW_FULL,
2358 "Receiving channel window "
2359 "has been exhausted");
2360
2361 rc = _libssh2_transport_read(session);
2362 if(rc == LIBSSH2_ERROR_EAGAIN) {
2363 return rc;
2364 }
2365 else if(rc < 0) {
2366 channel->wait_eof_state = libssh2_NB_state_idle;
2367 return _libssh2_error(session, rc,
2368 "_libssh2_transport_read() bailed out!");
2369 }
2370 } while(1);
2371
2372 channel->wait_eof_state = libssh2_NB_state_idle;
2373
2374 return 0;
2375 }
2376
2377 /*
2378 * libssh2_channel_wait_eof
2379 *
2380 * Awaiting channel EOF
2381 */
2382 LIBSSH2_API int
libssh2_channel_wait_eof(LIBSSH2_CHANNEL * channel)2383 libssh2_channel_wait_eof(LIBSSH2_CHANNEL *channel)
2384 {
2385 int rc;
2386
2387 if(!channel)
2388 return LIBSSH2_ERROR_BAD_USE;
2389
2390 BLOCK_ADJUST(rc, channel->session, channel_wait_eof(channel));
2391 return rc;
2392 }
2393
_libssh2_channel_close(LIBSSH2_CHANNEL * channel)2394 int _libssh2_channel_close(LIBSSH2_CHANNEL * channel)
2395 {
2396 LIBSSH2_SESSION *session = channel->session;
2397 int rc = 0;
2398
2399 if(channel->local.close) {
2400 /* Already closed, act like we sent another close,
2401 * even though we didn't... shhhhhh */
2402 channel->close_state = libssh2_NB_state_idle;
2403 return 0;
2404 }
2405
2406 if(!channel->local.eof) {
2407 rc = channel_send_eof(channel);
2408 if(rc) {
2409 if(rc == LIBSSH2_ERROR_EAGAIN) {
2410 return rc;
2411 }
2412 _libssh2_error(session, rc,
2413 "Unable to send EOF, but closing channel anyway");
2414 }
2415 }
2416
2417 /* ignore if we have received a remote eof or not, as it is now too
2418 late for us to wait for it. Continue closing! */
2419
2420 if(channel->close_state == libssh2_NB_state_idle) {
2421 _libssh2_debug(session, LIBSSH2_TRACE_CONN, "Closing channel %lu/%lu",
2422 channel->local.id, channel->remote.id);
2423
2424 channel->close_packet[0] = SSH_MSG_CHANNEL_CLOSE;
2425 _libssh2_htonu32(channel->close_packet + 1, channel->remote.id);
2426
2427 channel->close_state = libssh2_NB_state_created;
2428 }
2429
2430 if(channel->close_state == libssh2_NB_state_created) {
2431 rc = _libssh2_transport_send(session, channel->close_packet, 5,
2432 NULL, 0);
2433 if(rc == LIBSSH2_ERROR_EAGAIN) {
2434 _libssh2_error(session, rc,
2435 "Would block sending close-channel");
2436 return rc;
2437
2438 }
2439 else if(rc) {
2440 _libssh2_error(session, rc,
2441 "Unable to send close-channel request, "
2442 "but closing anyway");
2443 /* skip waiting for the response and fall through to
2444 LIBSSH2_CHANNEL_CLOSE below */
2445
2446 }
2447 else
2448 channel->close_state = libssh2_NB_state_sent;
2449 }
2450
2451 if(channel->close_state == libssh2_NB_state_sent) {
2452 /* We must wait for the remote SSH_MSG_CHANNEL_CLOSE message */
2453
2454 while(!channel->remote.close && !rc &&
2455 (session->socket_state != LIBSSH2_SOCKET_DISCONNECTED))
2456 rc = _libssh2_transport_read(session);
2457 }
2458
2459 if(rc != LIBSSH2_ERROR_EAGAIN) {
2460 /* set the local close state first when we're perfectly confirmed to
2461 not do any more EAGAINs */
2462 channel->local.close = 1;
2463
2464 /* We call the callback last in this function to make it keep the local
2465 data as long as EAGAIN is returned. */
2466 if(channel->close_cb) {
2467 LIBSSH2_CHANNEL_CLOSE(session, channel);
2468 }
2469
2470 channel->close_state = libssh2_NB_state_idle;
2471 }
2472
2473 /* return 0 or an error */
2474 return rc >= 0 ? 0 : rc;
2475 }
2476
2477 /*
2478 * libssh2_channel_close
2479 *
2480 * Close a channel
2481 */
2482 LIBSSH2_API int
libssh2_channel_close(LIBSSH2_CHANNEL * channel)2483 libssh2_channel_close(LIBSSH2_CHANNEL *channel)
2484 {
2485 int rc;
2486
2487 if(!channel)
2488 return LIBSSH2_ERROR_BAD_USE;
2489
2490 BLOCK_ADJUST(rc, channel->session, _libssh2_channel_close(channel) );
2491 return rc;
2492 }
2493
2494 /*
2495 * channel_wait_closed
2496 *
2497 * Awaiting channel close after EOF
2498 */
channel_wait_closed(LIBSSH2_CHANNEL * channel)2499 static int channel_wait_closed(LIBSSH2_CHANNEL *channel)
2500 {
2501 LIBSSH2_SESSION *session = channel->session;
2502 int rc;
2503
2504 if(!channel->remote.eof) {
2505 return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
2506 "libssh2_channel_wait_closed() invoked when "
2507 "channel is not in EOF state");
2508 }
2509
2510 if(channel->wait_closed_state == libssh2_NB_state_idle) {
2511 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
2512 "Awaiting close of channel %lu/%lu", channel->local.id,
2513 channel->remote.id);
2514
2515 channel->wait_closed_state = libssh2_NB_state_created;
2516 }
2517
2518 /*
2519 * While channel is not closed, read more packets from the network.
2520 * Either the channel will be closed or network timeout will occur.
2521 */
2522 if(!channel->remote.close) {
2523 do {
2524 rc = _libssh2_transport_read(session);
2525 if(channel->remote.close)
2526 /* it is now closed, move on! */
2527 break;
2528 } while(rc > 0);
2529 if(rc < 0)
2530 return rc;
2531 }
2532
2533 channel->wait_closed_state = libssh2_NB_state_idle;
2534
2535 return 0;
2536 }
2537
2538 /*
2539 * libssh2_channel_wait_closed
2540 *
2541 * Awaiting channel close after EOF
2542 */
2543 LIBSSH2_API int
libssh2_channel_wait_closed(LIBSSH2_CHANNEL * channel)2544 libssh2_channel_wait_closed(LIBSSH2_CHANNEL *channel)
2545 {
2546 int rc;
2547
2548 if(!channel)
2549 return LIBSSH2_ERROR_BAD_USE;
2550
2551 BLOCK_ADJUST(rc, channel->session, channel_wait_closed(channel));
2552 return rc;
2553 }
2554
2555 /*
2556 * _libssh2_channel_free
2557 *
2558 * Make sure a channel is closed, then remove the channel from the session
2559 * and free its resource(s)
2560 *
2561 * Returns 0 on success, negative on failure
2562 */
_libssh2_channel_free(LIBSSH2_CHANNEL * channel)2563 int _libssh2_channel_free(LIBSSH2_CHANNEL *channel)
2564 {
2565 LIBSSH2_SESSION *session = channel->session;
2566 unsigned char channel_id[4];
2567 unsigned char *data;
2568 size_t data_len;
2569 int rc;
2570
2571 assert(session);
2572
2573 if(channel->free_state == libssh2_NB_state_idle) {
2574 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
2575 "Freeing channel %lu/%lu resources", channel->local.id,
2576 channel->remote.id);
2577
2578 channel->free_state = libssh2_NB_state_created;
2579 }
2580
2581 /* Allow channel freeing even when the socket has lost its connection */
2582 if(!channel->local.close
2583 && (session->socket_state == LIBSSH2_SOCKET_CONNECTED)) {
2584 rc = _libssh2_channel_close(channel);
2585
2586 if(rc == LIBSSH2_ERROR_EAGAIN)
2587 return rc;
2588
2589 /* ignore all other errors as they otherwise risk blocking the channel
2590 free from happening */
2591 }
2592
2593 channel->free_state = libssh2_NB_state_idle;
2594
2595 if(channel->exit_signal) {
2596 LIBSSH2_FREE(session, channel->exit_signal);
2597 }
2598
2599 /*
2600 * channel->remote.close *might* not be set yet, Well...
2601 * We've sent the close packet, what more do you want?
2602 * Just let packet_add ignore it when it finally arrives
2603 */
2604
2605 /* Clear out packets meant for this channel */
2606 _libssh2_htonu32(channel_id, channel->local.id);
2607 while((_libssh2_packet_ask(session, SSH_MSG_CHANNEL_DATA, &data,
2608 &data_len, 1, channel_id, 4) >= 0)
2609 ||
2610 (_libssh2_packet_ask(session, SSH_MSG_CHANNEL_EXTENDED_DATA, &data,
2611 &data_len, 1, channel_id, 4) >= 0)) {
2612 LIBSSH2_FREE(session, data);
2613 }
2614
2615 /* free "channel_type" */
2616 if(channel->channel_type) {
2617 LIBSSH2_FREE(session, channel->channel_type);
2618 }
2619
2620 /* Unlink from channel list */
2621 _libssh2_list_remove(&channel->node);
2622
2623 /*
2624 * Make sure all memory used in the state variables are free
2625 */
2626 if(channel->setenv_packet) {
2627 LIBSSH2_FREE(session, channel->setenv_packet);
2628 }
2629 if(channel->reqX11_packet) {
2630 LIBSSH2_FREE(session, channel->reqX11_packet);
2631 }
2632 if(channel->process_packet) {
2633 LIBSSH2_FREE(session, channel->process_packet);
2634 }
2635
2636 LIBSSH2_FREE(session, channel);
2637
2638 return 0;
2639 }
2640
2641 /*
2642 * libssh2_channel_free
2643 *
2644 * Make sure a channel is closed, then remove the channel from the session
2645 * and free its resource(s)
2646 *
2647 * Returns 0 on success, negative on failure
2648 */
2649 LIBSSH2_API int
libssh2_channel_free(LIBSSH2_CHANNEL * channel)2650 libssh2_channel_free(LIBSSH2_CHANNEL *channel)
2651 {
2652 int rc;
2653
2654 if(!channel)
2655 return LIBSSH2_ERROR_BAD_USE;
2656
2657 BLOCK_ADJUST(rc, channel->session, _libssh2_channel_free(channel));
2658 return rc;
2659 }
2660 /*
2661 * libssh2_channel_window_read_ex
2662 *
2663 * Check the status of the read window. Returns the number of bytes which the
2664 * remote end may send without overflowing the window limit read_avail (if
2665 * passed) will be populated with the number of bytes actually available to be
2666 * read window_size_initial (if passed) will be populated with the
2667 * window_size_initial as defined by the channel_open request
2668 */
2669 LIBSSH2_API unsigned long
libssh2_channel_window_read_ex(LIBSSH2_CHANNEL * channel,unsigned long * read_avail,unsigned long * window_size_initial)2670 libssh2_channel_window_read_ex(LIBSSH2_CHANNEL *channel,
2671 unsigned long *read_avail,
2672 unsigned long *window_size_initial)
2673 {
2674 if(!channel)
2675 return 0; /* no channel, no window! */
2676
2677 if(window_size_initial) {
2678 *window_size_initial = channel->remote.window_size_initial;
2679 }
2680
2681 if(read_avail) {
2682 size_t bytes_queued = 0;
2683 LIBSSH2_PACKET *next_packet;
2684 LIBSSH2_PACKET *packet =
2685 _libssh2_list_first(&channel->session->packets);
2686
2687 while(packet) {
2688 unsigned char packet_type;
2689 next_packet = _libssh2_list_next(&packet->node);
2690
2691 if(packet->data_len < 1) {
2692 packet = next_packet;
2693 _libssh2_debug(channel->session, LIBSSH2_TRACE_ERROR,
2694 "Unexpected packet length");
2695 continue;
2696 }
2697
2698 packet_type = packet->data[0];
2699
2700 if(((packet_type == SSH_MSG_CHANNEL_DATA)
2701 || (packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA))
2702 && ((packet->data_len >= 5)
2703 && (_libssh2_ntohu32(packet->data + 1) ==
2704 channel->local.id))) {
2705 bytes_queued += packet->data_len - packet->data_head;
2706 }
2707
2708 packet = next_packet;
2709 }
2710
2711 *read_avail = bytes_queued;
2712 }
2713
2714 return channel->remote.window_size;
2715 }
2716
2717 /*
2718 * libssh2_channel_window_write_ex
2719 *
2720 * Check the status of the write window Returns the number of bytes which may
2721 * be safely written on the channel without blocking window_size_initial (if
2722 * passed) will be populated with the size of the initial window as defined by
2723 * the channel_open request
2724 */
2725 LIBSSH2_API unsigned long
libssh2_channel_window_write_ex(LIBSSH2_CHANNEL * channel,unsigned long * window_size_initial)2726 libssh2_channel_window_write_ex(LIBSSH2_CHANNEL *channel,
2727 unsigned long *window_size_initial)
2728 {
2729 if(!channel)
2730 return 0; /* no channel, no window! */
2731
2732 if(window_size_initial) {
2733 /* For locally initiated channels this is very often 0, so it's not
2734 * *that* useful as information goes */
2735 *window_size_initial = channel->local.window_size_initial;
2736 }
2737
2738 return channel->local.window_size;
2739 }
2740