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 * channel_request_auth_agent
1027 * The actual re-entrant method which requests an auth agent.
1028 * */
channel_request_auth_agent(LIBSSH2_CHANNEL * channel,const char * request_str,int request_str_len)1029 static int channel_request_auth_agent(LIBSSH2_CHANNEL *channel,
1030 const char *request_str,
1031 int request_str_len)
1032 {
1033 LIBSSH2_SESSION *session = channel->session;
1034 unsigned char *s;
1035 static const unsigned char reply_codes[3] =
1036 { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
1037 int rc;
1038
1039 if(channel->req_auth_agent_state == libssh2_NB_state_idle) {
1040 /* Only valid options are "auth-agent-req" and
1041 * "auth-agent-req_at_openssh.com" so we make sure it is not
1042 * actually longer than the longest possible. */
1043 if(request_str_len > 26) {
1044 return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
1045 "request_str length too large");
1046 }
1047
1048 /*
1049 * Length: 24 or 36 = packet_type(1) + channel(4) + req_len(4) +
1050 * request_str (variable) + want_reply (1) */
1051 channel->req_auth_agent_packet_len = 10 + request_str_len;
1052
1053 /* Zero out the requireev state to reset */
1054 memset(&channel->req_auth_agent_requirev_state, 0,
1055 sizeof(channel->req_auth_agent_requirev_state));
1056
1057 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
1058 "Requesting auth agent on channel %lu/%lu",
1059 channel->local.id, channel->remote.id);
1060
1061 /*
1062 * byte SSH_MSG_CHANNEL_REQUEST
1063 * uint32 recipient channel
1064 * string "auth-agent-req"
1065 * boolean want reply
1066 * */
1067 s = channel->req_auth_agent_packet;
1068 *(s++) = SSH_MSG_CHANNEL_REQUEST;
1069 _libssh2_store_u32(&s, channel->remote.id);
1070 _libssh2_store_str(&s, (char *)request_str, request_str_len);
1071 *(s++) = 0x01;
1072
1073 channel->req_auth_agent_state = libssh2_NB_state_created;
1074 }
1075
1076 if(channel->req_auth_agent_state == libssh2_NB_state_created) {
1077 /* Send the packet, we can use sizeof() on the packet because it
1078 * is always completely filled; there are no variable length fields. */
1079 rc = _libssh2_transport_send(session, channel->req_auth_agent_packet,
1080 channel->req_auth_agent_packet_len,
1081 NULL, 0);
1082
1083 if(rc == LIBSSH2_ERROR_EAGAIN) {
1084 _libssh2_error(session, rc,
1085 "Would block sending auth-agent request");
1086 }
1087 else if(rc) {
1088 channel->req_auth_agent_state = libssh2_NB_state_idle;
1089 return _libssh2_error(session, rc,
1090 "Unable to send auth-agent request");
1091 }
1092 _libssh2_htonu32(channel->req_auth_agent_local_channel,
1093 channel->local.id);
1094 channel->req_auth_agent_state = libssh2_NB_state_sent;
1095 }
1096
1097 if(channel->req_auth_agent_state == libssh2_NB_state_sent) {
1098 unsigned char *data;
1099 size_t data_len;
1100 unsigned char code;
1101
1102 rc = _libssh2_packet_requirev(
1103 session, reply_codes, &data, &data_len, 1,
1104 channel->req_auth_agent_local_channel,
1105 4, &channel->req_auth_agent_requirev_state);
1106 if(rc == LIBSSH2_ERROR_EAGAIN) {
1107 return rc;
1108 }
1109 else if(rc) {
1110 channel->req_auth_agent_state = libssh2_NB_state_idle;
1111 return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
1112 "Failed to request auth-agent");
1113 }
1114
1115 code = data[0];
1116
1117 LIBSSH2_FREE(session, data);
1118 channel->req_auth_agent_state = libssh2_NB_state_idle;
1119
1120 if(code == SSH_MSG_CHANNEL_SUCCESS)
1121 return 0;
1122 }
1123
1124 return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
1125 "Unable to complete request for auth-agent");
1126 }
1127
1128 /**
1129 * libssh2_channel_request_auth_agent
1130 * Requests that agent forwarding be enabled for the session. The
1131 * request must be sent over a specific channel, which starts the agent
1132 * listener on the remote side. Once the channel is closed, the agent
1133 * listener continues to exist.
1134 * */
1135 LIBSSH2_API int
libssh2_channel_request_auth_agent(LIBSSH2_CHANNEL * channel)1136 libssh2_channel_request_auth_agent(LIBSSH2_CHANNEL *channel)
1137 {
1138 int rc;
1139
1140 if(!channel)
1141 return LIBSSH2_ERROR_BAD_USE;
1142
1143 /* The current RFC draft for agent forwarding says you're supposed to
1144 * send "auth-agent-req," but most SSH servers out there right now
1145 * actually expect "auth-agent-req@openssh.com", so we try that
1146 * first. */
1147 if(channel->req_auth_agent_try_state == libssh2_NB_state_idle) {
1148 BLOCK_ADJUST(rc, channel->session,
1149 channel_request_auth_agent(channel,
1150 "auth-agent-req@openssh.com",
1151 26));
1152
1153 /* If we failed (but not with EAGAIN), then we move onto
1154 * the next step to try another request type. */
1155 if(rc != 0 && rc != LIBSSH2_ERROR_EAGAIN)
1156 channel->req_auth_agent_try_state = libssh2_NB_state_sent;
1157 }
1158
1159 if(channel->req_auth_agent_try_state == libssh2_NB_state_sent) {
1160 BLOCK_ADJUST(rc, channel->session,
1161 channel_request_auth_agent(channel,
1162 "auth-agent-req", 14));
1163
1164 /* If we failed without an EAGAIN, then move on with this
1165 * state machine. */
1166 if(rc != 0 && rc != LIBSSH2_ERROR_EAGAIN)
1167 channel->req_auth_agent_try_state = libssh2_NB_state_sent1;
1168 }
1169
1170 /* If things are good, reset the try state. */
1171 if(rc == 0)
1172 channel->req_auth_agent_try_state = libssh2_NB_state_idle;
1173
1174 return rc;
1175 }
1176
1177 /*
1178 * libssh2_channel_request_pty_ex
1179 * Duh... Request a PTY
1180 */
1181 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)1182 libssh2_channel_request_pty_ex(LIBSSH2_CHANNEL *channel, const char *term,
1183 unsigned int term_len, const char *modes,
1184 unsigned int modes_len, int width, int height,
1185 int width_px, int height_px)
1186 {
1187 int rc;
1188
1189 if(!channel)
1190 return LIBSSH2_ERROR_BAD_USE;
1191
1192 BLOCK_ADJUST(rc, channel->session,
1193 channel_request_pty(channel, term, term_len, modes,
1194 modes_len, width, height,
1195 width_px, height_px));
1196 return rc;
1197 }
1198
1199 static int
channel_request_pty_size(LIBSSH2_CHANNEL * channel,int width,int height,int width_px,int height_px)1200 channel_request_pty_size(LIBSSH2_CHANNEL * channel, int width,
1201 int height, int width_px, int height_px)
1202 {
1203 LIBSSH2_SESSION *session = channel->session;
1204 unsigned char *s;
1205 int rc;
1206 int retcode = LIBSSH2_ERROR_PROTO;
1207
1208 if(channel->reqPTY_state == libssh2_NB_state_idle) {
1209 channel->reqPTY_packet_len = 39;
1210
1211 /* Zero the whole thing out */
1212 memset(&channel->reqPTY_packet_requirev_state, 0,
1213 sizeof(channel->reqPTY_packet_requirev_state));
1214
1215 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
1216 "changing tty size on channel %lu/%lu",
1217 channel->local.id,
1218 channel->remote.id);
1219
1220 s = channel->reqPTY_packet;
1221
1222 *(s++) = SSH_MSG_CHANNEL_REQUEST;
1223 _libssh2_store_u32(&s, channel->remote.id);
1224 _libssh2_store_str(&s, (char *)"window-change",
1225 sizeof("window-change") - 1);
1226 *(s++) = 0x00; /* Don't reply */
1227 _libssh2_store_u32(&s, width);
1228 _libssh2_store_u32(&s, height);
1229 _libssh2_store_u32(&s, width_px);
1230 _libssh2_store_u32(&s, height_px);
1231
1232 channel->reqPTY_state = libssh2_NB_state_created;
1233 }
1234
1235 if(channel->reqPTY_state == libssh2_NB_state_created) {
1236 rc = _libssh2_transport_send(session, channel->reqPTY_packet,
1237 channel->reqPTY_packet_len,
1238 NULL, 0);
1239 if(rc == LIBSSH2_ERROR_EAGAIN) {
1240 _libssh2_error(session, rc,
1241 "Would block sending window-change request");
1242 return rc;
1243 }
1244 else if(rc) {
1245 channel->reqPTY_state = libssh2_NB_state_idle;
1246 return _libssh2_error(session, rc,
1247 "Unable to send window-change packet");
1248 }
1249 _libssh2_htonu32(channel->reqPTY_local_channel, channel->local.id);
1250 retcode = LIBSSH2_ERROR_NONE;
1251 }
1252
1253 channel->reqPTY_state = libssh2_NB_state_idle;
1254 return retcode;
1255 }
1256
1257 LIBSSH2_API int
libssh2_channel_request_pty_size_ex(LIBSSH2_CHANNEL * channel,int width,int height,int width_px,int height_px)1258 libssh2_channel_request_pty_size_ex(LIBSSH2_CHANNEL *channel, int width,
1259 int height, int width_px, int height_px)
1260 {
1261 int rc;
1262
1263 if(!channel)
1264 return LIBSSH2_ERROR_BAD_USE;
1265
1266 BLOCK_ADJUST(rc, channel->session,
1267 channel_request_pty_size(channel, width, height, width_px,
1268 height_px));
1269 return rc;
1270 }
1271
1272 /* Keep this an even number */
1273 #define LIBSSH2_X11_RANDOM_COOKIE_LEN 32
1274
1275 /*
1276 * channel_x11_req
1277 * Request X11 forwarding
1278 */
1279 static int
channel_x11_req(LIBSSH2_CHANNEL * channel,int single_connection,const char * auth_proto,const char * auth_cookie,int screen_number)1280 channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection,
1281 const char *auth_proto, const char *auth_cookie,
1282 int screen_number)
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 size_t proto_len =
1289 auth_proto ? strlen(auth_proto) : (sizeof("MIT-MAGIC-COOKIE-1") - 1);
1290 size_t cookie_len =
1291 auth_cookie ? strlen(auth_cookie) : LIBSSH2_X11_RANDOM_COOKIE_LEN;
1292 int rc;
1293
1294 if(channel->reqX11_state == libssh2_NB_state_idle) {
1295 /* 30 = packet_type(1) + channel(4) + x11_req_len(4) + "x11-req"(7) +
1296 * want_reply(1) + single_cnx(1) + proto_len(4) + cookie_len(4) +
1297 * screen_num(4) */
1298 channel->reqX11_packet_len = proto_len + cookie_len + 30;
1299
1300 /* Zero the whole thing out */
1301 memset(&channel->reqX11_packet_requirev_state, 0,
1302 sizeof(channel->reqX11_packet_requirev_state));
1303
1304 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
1305 "Requesting x11-req for channel %lu/%lu: single=%d "
1306 "proto=%s cookie=%s screen=%d",
1307 channel->local.id, channel->remote.id,
1308 single_connection,
1309 auth_proto ? auth_proto : "MIT-MAGIC-COOKIE-1",
1310 auth_cookie ? auth_cookie : "<random>", screen_number);
1311
1312 s = channel->reqX11_packet =
1313 LIBSSH2_ALLOC(session, channel->reqX11_packet_len);
1314 if(!channel->reqX11_packet) {
1315 return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1316 "Unable to allocate memory for pty-request");
1317 }
1318
1319 *(s++) = SSH_MSG_CHANNEL_REQUEST;
1320 _libssh2_store_u32(&s, channel->remote.id);
1321 _libssh2_store_str(&s, "x11-req", sizeof("x11-req") - 1);
1322
1323 *(s++) = 0x01; /* want_reply */
1324 *(s++) = single_connection ? 0x01 : 0x00;
1325
1326 _libssh2_store_str(&s, auth_proto ? auth_proto : "MIT-MAGIC-COOKIE-1",
1327 proto_len);
1328
1329 _libssh2_store_u32(&s, cookie_len);
1330 if(auth_cookie) {
1331 memcpy(s, auth_cookie, cookie_len);
1332 }
1333 else {
1334 int i;
1335 /* note: the extra +1 below is necessary since the sprintf()
1336 loop will always write 3 bytes so the last one will write
1337 the trailing zero at the LIBSSH2_X11_RANDOM_COOKIE_LEN/2
1338 border */
1339 unsigned char buffer[(LIBSSH2_X11_RANDOM_COOKIE_LEN / 2) + 1];
1340
1341 _libssh2_random(buffer, LIBSSH2_X11_RANDOM_COOKIE_LEN / 2);
1342 for(i = 0; i < (LIBSSH2_X11_RANDOM_COOKIE_LEN / 2); i++) {
1343 snprintf((char *)&s[i*2], 3, "%02X", buffer[i]);
1344 }
1345 }
1346 s += cookie_len;
1347
1348 _libssh2_store_u32(&s, screen_number);
1349 channel->reqX11_state = libssh2_NB_state_created;
1350 }
1351
1352 if(channel->reqX11_state == libssh2_NB_state_created) {
1353 rc = _libssh2_transport_send(session, channel->reqX11_packet,
1354 channel->reqX11_packet_len,
1355 NULL, 0);
1356 if(rc == LIBSSH2_ERROR_EAGAIN) {
1357 _libssh2_error(session, rc,
1358 "Would block sending X11-req packet");
1359 return rc;
1360 }
1361 if(rc) {
1362 LIBSSH2_FREE(session, channel->reqX11_packet);
1363 channel->reqX11_packet = NULL;
1364 channel->reqX11_state = libssh2_NB_state_idle;
1365 return _libssh2_error(session, rc,
1366 "Unable to send x11-req packet");
1367 }
1368 LIBSSH2_FREE(session, channel->reqX11_packet);
1369 channel->reqX11_packet = NULL;
1370
1371 _libssh2_htonu32(channel->reqX11_local_channel, channel->local.id);
1372
1373 channel->reqX11_state = libssh2_NB_state_sent;
1374 }
1375
1376 if(channel->reqX11_state == libssh2_NB_state_sent) {
1377 size_t data_len;
1378 unsigned char *data;
1379 unsigned char code;
1380
1381 rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
1382 1, channel->reqX11_local_channel, 4,
1383 &channel->reqX11_packet_requirev_state);
1384 if(rc == LIBSSH2_ERROR_EAGAIN) {
1385 return rc;
1386 }
1387 else if(rc || data_len < 1) {
1388 channel->reqX11_state = libssh2_NB_state_idle;
1389 return _libssh2_error(session, rc,
1390 "waiting for x11-req response packet");
1391 }
1392
1393 code = data[0];
1394 LIBSSH2_FREE(session, data);
1395 channel->reqX11_state = libssh2_NB_state_idle;
1396
1397 if(code == SSH_MSG_CHANNEL_SUCCESS)
1398 return 0;
1399 }
1400
1401 return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
1402 "Unable to complete request for channel x11-req");
1403 }
1404
1405 /*
1406 * libssh2_channel_x11_req_ex
1407 * Request X11 forwarding
1408 */
1409 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)1410 libssh2_channel_x11_req_ex(LIBSSH2_CHANNEL *channel, int single_connection,
1411 const char *auth_proto, const char *auth_cookie,
1412 int screen_number)
1413 {
1414 int rc;
1415
1416 if(!channel)
1417 return LIBSSH2_ERROR_BAD_USE;
1418
1419 BLOCK_ADJUST(rc, channel->session,
1420 channel_x11_req(channel, single_connection, auth_proto,
1421 auth_cookie, screen_number));
1422 return rc;
1423 }
1424
1425
1426 /*
1427 * _libssh2_channel_process_startup
1428 *
1429 * Primitive for libssh2_channel_(shell|exec|subsystem)
1430 */
1431 int
_libssh2_channel_process_startup(LIBSSH2_CHANNEL * channel,const char * request,size_t request_len,const char * message,size_t message_len)1432 _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
1433 const char *request, size_t request_len,
1434 const char *message, size_t message_len)
1435 {
1436 LIBSSH2_SESSION *session = channel->session;
1437 unsigned char *s;
1438 static const unsigned char reply_codes[3] =
1439 { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
1440 int rc;
1441
1442 if(channel->process_state == libssh2_NB_state_end) {
1443 return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE,
1444 "Channel can not be reused");
1445 }
1446
1447 if(channel->process_state == libssh2_NB_state_idle) {
1448 /* 10 = packet_type(1) + channel(4) + request_len(4) + want_reply(1) */
1449 channel->process_packet_len = request_len + 10;
1450
1451 /* Zero the whole thing out */
1452 memset(&channel->process_packet_requirev_state, 0,
1453 sizeof(channel->process_packet_requirev_state));
1454
1455 if(message)
1456 channel->process_packet_len += + 4;
1457
1458 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
1459 "starting request(%s) on channel %lu/%lu, message=%s",
1460 request, channel->local.id, channel->remote.id,
1461 message ? message : "<null>");
1462 s = channel->process_packet =
1463 LIBSSH2_ALLOC(session, channel->process_packet_len);
1464 if(!channel->process_packet)
1465 return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1466 "Unable to allocate memory "
1467 "for channel-process request");
1468
1469 *(s++) = SSH_MSG_CHANNEL_REQUEST;
1470 _libssh2_store_u32(&s, channel->remote.id);
1471 _libssh2_store_str(&s, request, request_len);
1472 *(s++) = 0x01;
1473
1474 if(message)
1475 _libssh2_store_u32(&s, message_len);
1476
1477 channel->process_state = libssh2_NB_state_created;
1478 }
1479
1480 if(channel->process_state == libssh2_NB_state_created) {
1481 rc = _libssh2_transport_send(session,
1482 channel->process_packet,
1483 channel->process_packet_len,
1484 (unsigned char *)message, message_len);
1485 if(rc == LIBSSH2_ERROR_EAGAIN) {
1486 _libssh2_error(session, rc,
1487 "Would block sending channel request");
1488 return rc;
1489 }
1490 else if(rc) {
1491 LIBSSH2_FREE(session, channel->process_packet);
1492 channel->process_packet = NULL;
1493 channel->process_state = libssh2_NB_state_end;
1494 return _libssh2_error(session, rc,
1495 "Unable to send channel request");
1496 }
1497 LIBSSH2_FREE(session, channel->process_packet);
1498 channel->process_packet = NULL;
1499
1500 _libssh2_htonu32(channel->process_local_channel, channel->local.id);
1501
1502 channel->process_state = libssh2_NB_state_sent;
1503 }
1504
1505 if(channel->process_state == libssh2_NB_state_sent) {
1506 unsigned char *data;
1507 size_t data_len;
1508 unsigned char code;
1509 rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
1510 1, channel->process_local_channel, 4,
1511 &channel->process_packet_requirev_state);
1512 if(rc == LIBSSH2_ERROR_EAGAIN) {
1513 return rc;
1514 }
1515 else if(rc || data_len < 1) {
1516 channel->process_state = libssh2_NB_state_end;
1517 return _libssh2_error(session, rc,
1518 "Failed waiting for channel success");
1519 }
1520
1521 code = data[0];
1522 LIBSSH2_FREE(session, data);
1523 channel->process_state = libssh2_NB_state_end;
1524
1525 if(code == SSH_MSG_CHANNEL_SUCCESS)
1526 return 0;
1527 }
1528
1529 return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
1530 "Unable to complete request for "
1531 "channel-process-startup");
1532 }
1533
1534 /*
1535 * libssh2_channel_process_startup
1536 *
1537 * Primitive for libssh2_channel_(shell|exec|subsystem)
1538 */
1539 LIBSSH2_API int
libssh2_channel_process_startup(LIBSSH2_CHANNEL * channel,const char * req,unsigned int req_len,const char * msg,unsigned int msg_len)1540 libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
1541 const char *req, unsigned int req_len,
1542 const char *msg, unsigned int msg_len)
1543 {
1544 int rc;
1545
1546 if(!channel)
1547 return LIBSSH2_ERROR_BAD_USE;
1548
1549 BLOCK_ADJUST(rc, channel->session,
1550 _libssh2_channel_process_startup(channel, req, req_len,
1551 msg, msg_len));
1552 return rc;
1553 }
1554
1555
1556 /*
1557 * libssh2_channel_set_blocking
1558 *
1559 * Set a channel's BEHAVIOR blocking on or off. The socket will remain non-
1560 * blocking.
1561 */
1562 LIBSSH2_API void
libssh2_channel_set_blocking(LIBSSH2_CHANNEL * channel,int blocking)1563 libssh2_channel_set_blocking(LIBSSH2_CHANNEL * channel, int blocking)
1564 {
1565 if(channel)
1566 (void) _libssh2_session_set_blocking(channel->session, blocking);
1567 }
1568
1569 /*
1570 * _libssh2_channel_flush
1571 *
1572 * Flush data from one (or all) stream
1573 * Returns number of bytes flushed, or negative on failure
1574 */
1575 int
_libssh2_channel_flush(LIBSSH2_CHANNEL * channel,int streamid)1576 _libssh2_channel_flush(LIBSSH2_CHANNEL *channel, int streamid)
1577 {
1578 if(channel->flush_state == libssh2_NB_state_idle) {
1579 LIBSSH2_PACKET *packet =
1580 _libssh2_list_first(&channel->session->packets);
1581 channel->flush_refund_bytes = 0;
1582 channel->flush_flush_bytes = 0;
1583
1584 while(packet) {
1585 unsigned char packet_type;
1586 LIBSSH2_PACKET *next = _libssh2_list_next(&packet->node);
1587
1588 if(packet->data_len < 1) {
1589 packet = next;
1590 _libssh2_debug(channel->session, LIBSSH2_TRACE_ERROR,
1591 "Unexpected packet length");
1592 continue;
1593 }
1594
1595 packet_type = packet->data[0];
1596
1597 if(((packet_type == SSH_MSG_CHANNEL_DATA)
1598 || (packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA))
1599 && ((packet->data_len >= 5)
1600 && (_libssh2_ntohu32(packet->data + 1)
1601 == channel->local.id))) {
1602 /* It's our channel at least */
1603 int packet_stream_id;
1604
1605 if(packet_type == SSH_MSG_CHANNEL_DATA) {
1606 packet_stream_id = 0;
1607 }
1608 else if(packet->data_len >= 9) {
1609 packet_stream_id = _libssh2_ntohu32(packet->data + 5);
1610 }
1611 else {
1612 channel->flush_state = libssh2_NB_state_idle;
1613 return _libssh2_error(channel->session,
1614 LIBSSH2_ERROR_PROTO,
1615 "Unexpected packet length");
1616 }
1617
1618 if((streamid == LIBSSH2_CHANNEL_FLUSH_ALL)
1619 || ((packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA)
1620 && ((streamid == LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA)
1621 || (streamid == packet_stream_id)))
1622 || ((packet_type == SSH_MSG_CHANNEL_DATA)
1623 && (streamid == 0))) {
1624 size_t bytes_to_flush = packet->data_len -
1625 packet->data_head;
1626
1627 _libssh2_debug(channel->session, LIBSSH2_TRACE_CONN,
1628 "Flushing %d bytes of data from stream "
1629 "%lu on channel %lu/%lu",
1630 bytes_to_flush, packet_stream_id,
1631 channel->local.id, channel->remote.id);
1632
1633 /* It's one of the streams we wanted to flush */
1634 channel->flush_refund_bytes += packet->data_len - 13;
1635 channel->flush_flush_bytes += bytes_to_flush;
1636
1637 LIBSSH2_FREE(channel->session, packet->data);
1638
1639 /* remove this packet from the parent's list */
1640 _libssh2_list_remove(&packet->node);
1641 LIBSSH2_FREE(channel->session, packet);
1642 }
1643 }
1644 packet = next;
1645 }
1646
1647 channel->flush_state = libssh2_NB_state_created;
1648 }
1649
1650 channel->read_avail -= channel->flush_flush_bytes;
1651 channel->remote.window_size -= channel->flush_flush_bytes;
1652
1653 if(channel->flush_refund_bytes) {
1654 int rc =
1655 _libssh2_channel_receive_window_adjust(channel,
1656 channel->flush_refund_bytes,
1657 1, NULL);
1658 if(rc == LIBSSH2_ERROR_EAGAIN)
1659 return rc;
1660 }
1661
1662 channel->flush_state = libssh2_NB_state_idle;
1663
1664 return channel->flush_flush_bytes;
1665 }
1666
1667 /*
1668 * libssh2_channel_flush_ex
1669 *
1670 * Flush data from one (or all) stream
1671 * Returns number of bytes flushed, or negative on failure
1672 */
1673 LIBSSH2_API int
libssh2_channel_flush_ex(LIBSSH2_CHANNEL * channel,int stream)1674 libssh2_channel_flush_ex(LIBSSH2_CHANNEL *channel, int stream)
1675 {
1676 int rc;
1677
1678 if(!channel)
1679 return LIBSSH2_ERROR_BAD_USE;
1680
1681 BLOCK_ADJUST(rc, channel->session,
1682 _libssh2_channel_flush(channel, stream));
1683 return rc;
1684 }
1685
1686 /*
1687 * libssh2_channel_get_exit_status
1688 *
1689 * Return the channel's program exit status. Note that the actual protocol
1690 * provides the full 32bit this function returns. We cannot abuse it to
1691 * return error values in case of errors so we return a zero if channel is
1692 * NULL.
1693 */
1694 LIBSSH2_API int
libssh2_channel_get_exit_status(LIBSSH2_CHANNEL * channel)1695 libssh2_channel_get_exit_status(LIBSSH2_CHANNEL *channel)
1696 {
1697 if(!channel)
1698 return 0;
1699
1700 return channel->exit_status;
1701 }
1702
1703 /*
1704 * libssh2_channel_get_exit_signal
1705 *
1706 * Get exit signal (without leading "SIG"), error message, and language
1707 * tag into newly allocated buffers of indicated length. Caller can
1708 * use NULL pointers to indicate that the value should not be set. The
1709 * *_len variables are set if they are non-NULL even if the
1710 * corresponding string parameter is NULL. Returns LIBSSH2_ERROR_NONE
1711 * on success, or an API error code.
1712 */
1713 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)1714 libssh2_channel_get_exit_signal(LIBSSH2_CHANNEL *channel,
1715 char **exitsignal,
1716 size_t *exitsignal_len,
1717 char **errmsg,
1718 size_t *errmsg_len,
1719 char **langtag,
1720 size_t *langtag_len)
1721 {
1722 size_t namelen = 0;
1723
1724 if(channel) {
1725 LIBSSH2_SESSION *session = channel->session;
1726
1727 if(channel->exit_signal) {
1728 namelen = strlen(channel->exit_signal);
1729 if(exitsignal) {
1730 *exitsignal = LIBSSH2_ALLOC(session, namelen + 1);
1731 if(!*exitsignal) {
1732 return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1733 "Unable to allocate memory for signal name");
1734 }
1735 memcpy(*exitsignal, channel->exit_signal, namelen);
1736 (*exitsignal)[namelen] = '\0';
1737 }
1738 if(exitsignal_len)
1739 *exitsignal_len = namelen;
1740 }
1741 else {
1742 if(exitsignal)
1743 *exitsignal = NULL;
1744 if(exitsignal_len)
1745 *exitsignal_len = 0;
1746 }
1747
1748 /* TODO: set error message and language tag */
1749
1750 if(errmsg)
1751 *errmsg = NULL;
1752
1753 if(errmsg_len)
1754 *errmsg_len = 0;
1755
1756 if(langtag)
1757 *langtag = NULL;
1758
1759 if(langtag_len)
1760 *langtag_len = 0;
1761 }
1762
1763 return LIBSSH2_ERROR_NONE;
1764 }
1765
1766 /*
1767 * _libssh2_channel_receive_window_adjust
1768 *
1769 * Adjust the receive window for a channel by adjustment bytes. If the amount
1770 * to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the
1771 * adjustment amount will be queued for a later packet.
1772 *
1773 * Calls _libssh2_error() !
1774 */
1775 int
_libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,uint32_t adjustment,unsigned char force,unsigned int * store)1776 _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
1777 uint32_t adjustment,
1778 unsigned char force,
1779 unsigned int *store)
1780 {
1781 int rc;
1782
1783 if(store)
1784 *store = channel->remote.window_size;
1785
1786 if(channel->adjust_state == libssh2_NB_state_idle) {
1787 if(!force
1788 && (adjustment + channel->adjust_queue <
1789 LIBSSH2_CHANNEL_MINADJUST)) {
1790 _libssh2_debug(channel->session, LIBSSH2_TRACE_CONN,
1791 "Queueing %lu bytes for receive window adjustment "
1792 "for channel %lu/%lu",
1793 adjustment, channel->local.id, channel->remote.id);
1794 channel->adjust_queue += adjustment;
1795 return 0;
1796 }
1797
1798 if(!adjustment && !channel->adjust_queue) {
1799 return 0;
1800 }
1801
1802 adjustment += channel->adjust_queue;
1803 channel->adjust_queue = 0;
1804
1805 /* Adjust the window based on the block we just freed */
1806 channel->adjust_adjust[0] = SSH_MSG_CHANNEL_WINDOW_ADJUST;
1807 _libssh2_htonu32(&channel->adjust_adjust[1], channel->remote.id);
1808 _libssh2_htonu32(&channel->adjust_adjust[5], adjustment);
1809 _libssh2_debug(channel->session, LIBSSH2_TRACE_CONN,
1810 "Adjusting window %lu bytes for data on "
1811 "channel %lu/%lu",
1812 adjustment, channel->local.id, channel->remote.id);
1813
1814 channel->adjust_state = libssh2_NB_state_created;
1815 }
1816
1817 rc = _libssh2_transport_send(channel->session, channel->adjust_adjust, 9,
1818 NULL, 0);
1819 if(rc == LIBSSH2_ERROR_EAGAIN) {
1820 _libssh2_error(channel->session, rc,
1821 "Would block sending window adjust");
1822 return rc;
1823 }
1824 else if(rc) {
1825 channel->adjust_queue = adjustment;
1826 return _libssh2_error(channel->session, LIBSSH2_ERROR_SOCKET_SEND,
1827 "Unable to send transfer-window adjustment "
1828 "packet, deferring");
1829 }
1830 else {
1831 channel->remote.window_size += adjustment;
1832 }
1833
1834 channel->adjust_state = libssh2_NB_state_idle;
1835
1836 return 0;
1837 }
1838
1839 /*
1840 * libssh2_channel_receive_window_adjust
1841 *
1842 * DEPRECATED
1843 *
1844 * Adjust the receive window for a channel by adjustment bytes. If the amount
1845 * to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the
1846 * adjustment amount will be queued for a later packet.
1847 *
1848 * Returns the new size of the receive window (as understood by remote end).
1849 * Note that it might return EAGAIN too which is highly stupid.
1850 *
1851 */
1852 LIBSSH2_API unsigned long
libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,unsigned long adj,unsigned char force)1853 libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL *channel,
1854 unsigned long adj,
1855 unsigned char force)
1856 {
1857 unsigned int window;
1858 int rc;
1859
1860 if(!channel)
1861 return (unsigned long)LIBSSH2_ERROR_BAD_USE;
1862
1863 BLOCK_ADJUST(rc, channel->session,
1864 _libssh2_channel_receive_window_adjust(channel, adj,
1865 force, &window));
1866
1867 /* stupid - but this is how it was made to work before and this is just
1868 kept for backwards compatibility */
1869 return rc ? (unsigned long)rc : window;
1870 }
1871
1872 /*
1873 * libssh2_channel_receive_window_adjust2
1874 *
1875 * Adjust the receive window for a channel by adjustment bytes. If the amount
1876 * to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the
1877 * adjustment amount will be queued for a later packet.
1878 *
1879 * Stores the new size of the receive window in the data 'window' points to.
1880 *
1881 * Returns the "normal" error code: 0 for success, negative for failure.
1882 */
1883 LIBSSH2_API int
libssh2_channel_receive_window_adjust2(LIBSSH2_CHANNEL * channel,unsigned long adj,unsigned char force,unsigned int * window)1884 libssh2_channel_receive_window_adjust2(LIBSSH2_CHANNEL *channel,
1885 unsigned long adj,
1886 unsigned char force,
1887 unsigned int *window)
1888 {
1889 int rc;
1890
1891 if(!channel)
1892 return LIBSSH2_ERROR_BAD_USE;
1893
1894 BLOCK_ADJUST(rc, channel->session,
1895 _libssh2_channel_receive_window_adjust(channel, adj, force,
1896 window));
1897 return rc;
1898 }
1899
1900 int
_libssh2_channel_extended_data(LIBSSH2_CHANNEL * channel,int ignore_mode)1901 _libssh2_channel_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode)
1902 {
1903 if(channel->extData2_state == libssh2_NB_state_idle) {
1904 _libssh2_debug(channel->session, LIBSSH2_TRACE_CONN,
1905 "Setting channel %lu/%lu handle_extended_data"
1906 " mode to %d",
1907 channel->local.id, channel->remote.id, ignore_mode);
1908 channel->remote.extended_data_ignore_mode = (char)ignore_mode;
1909
1910 channel->extData2_state = libssh2_NB_state_created;
1911 }
1912
1913 if(channel->extData2_state == libssh2_NB_state_idle) {
1914 if(ignore_mode == LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) {
1915 int rc =
1916 _libssh2_channel_flush(channel,
1917 LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA);
1918 if(LIBSSH2_ERROR_EAGAIN == rc)
1919 return rc;
1920 }
1921 }
1922
1923 channel->extData2_state = libssh2_NB_state_idle;
1924 return 0;
1925 }
1926
1927 /*
1928 * libssh2_channel_handle_extended_data2()
1929 *
1930 */
1931 LIBSSH2_API int
libssh2_channel_handle_extended_data2(LIBSSH2_CHANNEL * channel,int mode)1932 libssh2_channel_handle_extended_data2(LIBSSH2_CHANNEL *channel,
1933 int mode)
1934 {
1935 int rc;
1936
1937 if(!channel)
1938 return LIBSSH2_ERROR_BAD_USE;
1939
1940 BLOCK_ADJUST(rc, channel->session, _libssh2_channel_extended_data(channel,
1941 mode));
1942 return rc;
1943 }
1944
1945 /*
1946 * libssh2_channel_handle_extended_data
1947 *
1948 * DEPRECATED DO NOTE USE!
1949 *
1950 * How should extended data look to the calling app? Keep it in separate
1951 * channels[_read() _read_stdder()]? (NORMAL) Merge the extended data to the
1952 * standard data? [everything via _read()]? (MERGE) Ignore it entirely [toss
1953 * out packets as they come in]? (IGNORE)
1954 */
1955 LIBSSH2_API void
libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL * channel,int ignore_mode)1956 libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel,
1957 int ignore_mode)
1958 {
1959 (void)libssh2_channel_handle_extended_data2(channel, ignore_mode);
1960 }
1961
1962
1963
1964 /*
1965 * _libssh2_channel_read
1966 *
1967 * Read data from a channel
1968 *
1969 * It is important to not return 0 until the currently read channel is
1970 * complete. If we read stuff from the wire but it was no payload data to fill
1971 * in the buffer with, we MUST make sure to return LIBSSH2_ERROR_EAGAIN.
1972 *
1973 * The receive window must be maintained (enlarged) by the user of this
1974 * function.
1975 */
_libssh2_channel_read(LIBSSH2_CHANNEL * channel,int stream_id,char * buf,size_t buflen)1976 ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
1977 char *buf, size_t buflen)
1978 {
1979 LIBSSH2_SESSION *session = channel->session;
1980 int rc;
1981 size_t bytes_read = 0;
1982 size_t bytes_want;
1983 int unlink_packet;
1984 LIBSSH2_PACKET *read_packet;
1985 LIBSSH2_PACKET *read_next;
1986
1987 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
1988 "channel_read() wants %d bytes from channel %lu/%lu "
1989 "stream #%d",
1990 (int) buflen, channel->local.id, channel->remote.id,
1991 stream_id);
1992
1993 /* expand the receiving window first if it has become too narrow */
1994 if((channel->read_state == libssh2_NB_state_jump1) ||
1995 (channel->remote.window_size <
1996 channel->remote.window_size_initial / 4 * 3 + buflen) ) {
1997
1998 uint32_t adjustment = channel->remote.window_size_initial + buflen -
1999 channel->remote.window_size;
2000 if(adjustment < LIBSSH2_CHANNEL_MINADJUST)
2001 adjustment = LIBSSH2_CHANNEL_MINADJUST;
2002
2003 /* the actual window adjusting may not finish so we need to deal with
2004 this special state here */
2005 channel->read_state = libssh2_NB_state_jump1;
2006 rc = _libssh2_channel_receive_window_adjust(channel, adjustment,
2007 0, NULL);
2008 if(rc)
2009 return rc;
2010
2011 channel->read_state = libssh2_NB_state_idle;
2012 }
2013
2014 /* Process all pending incoming packets. Tests prove that this way
2015 produces faster transfers. */
2016 do {
2017 rc = _libssh2_transport_read(session);
2018 } while(rc > 0);
2019
2020 if((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN))
2021 return _libssh2_error(session, rc, "transport read");
2022
2023 read_packet = _libssh2_list_first(&session->packets);
2024 while(read_packet && (bytes_read < buflen)) {
2025 /* previously this loop condition also checked for
2026 !channel->remote.close but we cannot let it do this:
2027
2028 We may have a series of packets to read that are still pending even
2029 if a close has been received. Acknowledging the close too early
2030 makes us flush buffers prematurely and loose data.
2031 */
2032
2033 LIBSSH2_PACKET *readpkt = read_packet;
2034
2035 /* In case packet gets destroyed during this iteration */
2036 read_next = _libssh2_list_next(&readpkt->node);
2037
2038 if(readpkt->data_len < 5) {
2039 read_packet = read_next;
2040 _libssh2_debug(channel->session, LIBSSH2_TRACE_ERROR,
2041 "Unexpected packet length");
2042 continue;
2043 }
2044
2045 channel->read_local_id =
2046 _libssh2_ntohu32(readpkt->data + 1);
2047
2048 /*
2049 * Either we asked for a specific extended data stream
2050 * (and data was available),
2051 * or the standard stream (and data was available),
2052 * or the standard stream with extended_data_merge
2053 * enabled and data was available
2054 */
2055 if((stream_id
2056 && (readpkt->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)
2057 && (channel->local.id == channel->read_local_id)
2058 && (readpkt->data_len >= 9)
2059 && (stream_id == (int) _libssh2_ntohu32(readpkt->data + 5)))
2060 || (!stream_id && (readpkt->data[0] == SSH_MSG_CHANNEL_DATA)
2061 && (channel->local.id == channel->read_local_id))
2062 || (!stream_id
2063 && (readpkt->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)
2064 && (channel->local.id == channel->read_local_id)
2065 && (channel->remote.extended_data_ignore_mode ==
2066 LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE))) {
2067
2068 /* figure out much more data we want to read */
2069 bytes_want = buflen - bytes_read;
2070 unlink_packet = FALSE;
2071
2072 if(bytes_want >= (readpkt->data_len - readpkt->data_head)) {
2073 /* we want more than this node keeps, so adjust the number and
2074 delete this node after the copy */
2075 bytes_want = readpkt->data_len - readpkt->data_head;
2076 unlink_packet = TRUE;
2077 }
2078
2079 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
2080 "channel_read() got %d of data from %lu/%lu/%d%s",
2081 bytes_want, channel->local.id,
2082 channel->remote.id, stream_id,
2083 unlink_packet?" [ul]":"");
2084
2085 /* copy data from this struct to the target buffer */
2086 memcpy(&buf[bytes_read],
2087 &readpkt->data[readpkt->data_head], bytes_want);
2088
2089 /* advance pointer and counter */
2090 readpkt->data_head += bytes_want;
2091 bytes_read += bytes_want;
2092
2093 /* if drained, remove from list */
2094 if(unlink_packet) {
2095 /* detach readpkt from session->packets list */
2096 _libssh2_list_remove(&readpkt->node);
2097
2098 LIBSSH2_FREE(session, readpkt->data);
2099 LIBSSH2_FREE(session, readpkt);
2100 }
2101 }
2102
2103 /* check the next struct in the chain */
2104 read_packet = read_next;
2105 }
2106
2107 if(!bytes_read) {
2108 /* If the channel is already at EOF or even closed, we need to signal
2109 that back. We may have gotten that info while draining the incoming
2110 transport layer until EAGAIN so we must not be fooled by that
2111 return code. */
2112 if(channel->remote.eof || channel->remote.close)
2113 return 0;
2114 else if(rc != LIBSSH2_ERROR_EAGAIN)
2115 return 0;
2116
2117 /* if the transport layer said EAGAIN then we say so as well */
2118 return _libssh2_error(session, rc, "would block");
2119 }
2120
2121 channel->read_avail -= bytes_read;
2122 channel->remote.window_size -= bytes_read;
2123
2124 return bytes_read;
2125 }
2126
2127 /*
2128 * libssh2_channel_read_ex
2129 *
2130 * Read data from a channel (blocking or non-blocking depending on set state)
2131 *
2132 * When this is done non-blocking, it is important to not return 0 until the
2133 * currently read channel is complete. If we read stuff from the wire but it
2134 * was no payload data to fill in the buffer with, we MUST make sure to return
2135 * LIBSSH2_ERROR_EAGAIN.
2136 *
2137 * This function will first make sure there's a receive window enough to
2138 * receive a full buffer's wort of contents. An application may choose to
2139 * adjust the receive window more to increase transfer performance.
2140 */
2141 LIBSSH2_API ssize_t
libssh2_channel_read_ex(LIBSSH2_CHANNEL * channel,int stream_id,char * buf,size_t buflen)2142 libssh2_channel_read_ex(LIBSSH2_CHANNEL *channel, int stream_id, char *buf,
2143 size_t buflen)
2144 {
2145 int rc;
2146 unsigned long recv_window;
2147
2148 if(!channel)
2149 return LIBSSH2_ERROR_BAD_USE;
2150
2151 recv_window = libssh2_channel_window_read_ex(channel, NULL, NULL);
2152
2153 if(buflen > recv_window) {
2154 BLOCK_ADJUST(rc, channel->session,
2155 _libssh2_channel_receive_window_adjust(channel, buflen,
2156 1, NULL));
2157 }
2158
2159 BLOCK_ADJUST(rc, channel->session,
2160 _libssh2_channel_read(channel, stream_id, buf, buflen));
2161 return rc;
2162 }
2163
2164 /*
2165 * _libssh2_channel_packet_data_len
2166 *
2167 * Return the size of the data block of the current packet, or 0 if there
2168 * isn't a packet.
2169 */
2170 size_t
_libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel,int stream_id)2171 _libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, int stream_id)
2172 {
2173 LIBSSH2_SESSION *session = channel->session;
2174 LIBSSH2_PACKET *read_packet;
2175 LIBSSH2_PACKET *next_packet;
2176 uint32_t read_local_id;
2177
2178 read_packet = _libssh2_list_first(&session->packets);
2179 if(read_packet == NULL)
2180 return 0;
2181
2182 while(read_packet) {
2183
2184 next_packet = _libssh2_list_next(&read_packet->node);
2185
2186 if(read_packet->data_len < 5) {
2187 read_packet = next_packet;
2188 _libssh2_debug(channel->session, LIBSSH2_TRACE_ERROR,
2189 "Unexpected packet length");
2190 continue;
2191 }
2192
2193 read_local_id = _libssh2_ntohu32(read_packet->data + 1);
2194
2195 /*
2196 * Either we asked for a specific extended data stream
2197 * (and data was available),
2198 * or the standard stream (and data was available),
2199 * or the standard stream with extended_data_merge
2200 * enabled and data was available
2201 */
2202 if((stream_id
2203 && (read_packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)
2204 && (channel->local.id == read_local_id)
2205 && (read_packet->data_len >= 9)
2206 && (stream_id == (int) _libssh2_ntohu32(read_packet->data + 5)))
2207 ||
2208 (!stream_id
2209 && (read_packet->data[0] == SSH_MSG_CHANNEL_DATA)
2210 && (channel->local.id == read_local_id))
2211 ||
2212 (!stream_id
2213 && (read_packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)
2214 && (channel->local.id == read_local_id)
2215 && (channel->remote.extended_data_ignore_mode
2216 == LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE))) {
2217 return (read_packet->data_len - read_packet->data_head);
2218 }
2219
2220 read_packet = next_packet;
2221 }
2222
2223 return 0;
2224 }
2225
2226 /*
2227 * _libssh2_channel_write
2228 *
2229 * Send data to a channel. Note that if this returns EAGAIN, the caller must
2230 * call this function again with the SAME input arguments.
2231 *
2232 * Returns: number of bytes sent, or if it returns a negative number, that is
2233 * the error code!
2234 */
2235 ssize_t
_libssh2_channel_write(LIBSSH2_CHANNEL * channel,int stream_id,const unsigned char * buf,size_t buflen)2236 _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
2237 const unsigned char *buf, size_t buflen)
2238 {
2239 int rc = 0;
2240 LIBSSH2_SESSION *session = channel->session;
2241 ssize_t wrote = 0; /* counter for this specific this call */
2242
2243 /* In theory we could split larger buffers into several smaller packets
2244 * but it turns out to be really hard and nasty to do while still offering
2245 * the API/prototype.
2246 *
2247 * Instead we only deal with the first 32K in this call and for the parent
2248 * function to call it again with the remainder! 32K is a conservative
2249 * limit based on the text in RFC4253 section 6.1.
2250 */
2251 if(buflen > 32700)
2252 buflen = 32700;
2253
2254 if(channel->write_state == libssh2_NB_state_idle) {
2255 unsigned char *s = channel->write_packet;
2256
2257 _libssh2_debug(channel->session, LIBSSH2_TRACE_CONN,
2258 "Writing %d bytes on channel %lu/%lu, stream #%d",
2259 (int) buflen, channel->local.id, channel->remote.id,
2260 stream_id);
2261
2262 if(channel->local.close)
2263 return _libssh2_error(channel->session,
2264 LIBSSH2_ERROR_CHANNEL_CLOSED,
2265 "We've already closed this channel");
2266 else if(channel->local.eof)
2267 return _libssh2_error(channel->session,
2268 LIBSSH2_ERROR_CHANNEL_EOF_SENT,
2269 "EOF has already been received, "
2270 "data might be ignored");
2271
2272 /* drain the incoming flow first, mostly to make sure we get all
2273 * pending window adjust packets */
2274 do
2275 rc = _libssh2_transport_read(session);
2276 while(rc > 0);
2277
2278 if((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN)) {
2279 return _libssh2_error(channel->session, rc,
2280 "Failure while draining incoming flow");
2281 }
2282
2283 if(channel->local.window_size <= 0) {
2284 /* there's no room for data so we stop */
2285
2286 /* Waiting on the socket to be writable would be wrong because we
2287 * would be back here immediately, but a readable socket might
2288 * herald an incoming window adjustment.
2289 */
2290 session->socket_block_directions = LIBSSH2_SESSION_BLOCK_INBOUND;
2291
2292 return (rc == LIBSSH2_ERROR_EAGAIN?rc:0);
2293 }
2294
2295 channel->write_bufwrite = buflen;
2296
2297 *(s++) = stream_id ? SSH_MSG_CHANNEL_EXTENDED_DATA :
2298 SSH_MSG_CHANNEL_DATA;
2299 _libssh2_store_u32(&s, channel->remote.id);
2300 if(stream_id)
2301 _libssh2_store_u32(&s, stream_id);
2302
2303 /* Don't exceed the remote end's limits */
2304 /* REMEMBER local means local as the SOURCE of the data */
2305 if(channel->write_bufwrite > channel->local.window_size) {
2306 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
2307 "Splitting write block due to %lu byte "
2308 "window_size on %lu/%lu/%d",
2309 channel->local.window_size, channel->local.id,
2310 channel->remote.id, stream_id);
2311 channel->write_bufwrite = channel->local.window_size;
2312 }
2313 if(channel->write_bufwrite > channel->local.packet_size) {
2314 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
2315 "Splitting write block due to %lu byte "
2316 "packet_size on %lu/%lu/%d",
2317 channel->local.packet_size, channel->local.id,
2318 channel->remote.id, stream_id);
2319 channel->write_bufwrite = channel->local.packet_size;
2320 }
2321 /* store the size here only, the buffer is passed in as-is to
2322 _libssh2_transport_send() */
2323 _libssh2_store_u32(&s, channel->write_bufwrite);
2324 channel->write_packet_len = s - channel->write_packet;
2325
2326 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
2327 "Sending %d bytes on channel %lu/%lu, stream_id=%d",
2328 (int) channel->write_bufwrite, channel->local.id,
2329 channel->remote.id, stream_id);
2330
2331 channel->write_state = libssh2_NB_state_created;
2332 }
2333
2334 if(channel->write_state == libssh2_NB_state_created) {
2335 rc = _libssh2_transport_send(session, channel->write_packet,
2336 channel->write_packet_len,
2337 buf, channel->write_bufwrite);
2338 if(rc == LIBSSH2_ERROR_EAGAIN) {
2339 return _libssh2_error(session, rc,
2340 "Unable to send channel data");
2341 }
2342 else if(rc) {
2343 channel->write_state = libssh2_NB_state_idle;
2344 return _libssh2_error(session, rc,
2345 "Unable to send channel data");
2346 }
2347 /* Shrink local window size */
2348 channel->local.window_size -= channel->write_bufwrite;
2349
2350 wrote += channel->write_bufwrite;
2351
2352 /* Since _libssh2_transport_write() succeeded, we must return
2353 now to allow the caller to provide the next chunk of data.
2354
2355 We cannot move on to send the next piece of data that may
2356 already have been provided in this same function call, as we
2357 risk getting EAGAIN for that and we can't return information
2358 both about sent data as well as EAGAIN. So, by returning short
2359 now, the caller will call this function again with new data to
2360 send */
2361
2362 channel->write_state = libssh2_NB_state_idle;
2363
2364 return wrote;
2365 }
2366
2367 return LIBSSH2_ERROR_INVAL; /* reaching this point is really bad */
2368 }
2369
2370 /*
2371 * libssh2_channel_write_ex
2372 *
2373 * Send data to a channel
2374 */
2375 LIBSSH2_API ssize_t
libssh2_channel_write_ex(LIBSSH2_CHANNEL * channel,int stream_id,const char * buf,size_t buflen)2376 libssh2_channel_write_ex(LIBSSH2_CHANNEL *channel, int stream_id,
2377 const char *buf, size_t buflen)
2378 {
2379 ssize_t rc;
2380
2381 if(!channel)
2382 return LIBSSH2_ERROR_BAD_USE;
2383
2384 BLOCK_ADJUST(rc, channel->session,
2385 _libssh2_channel_write(channel, stream_id,
2386 (unsigned char *)buf, buflen));
2387 return rc;
2388 }
2389
2390 /*
2391 * channel_send_eof
2392 *
2393 * Send EOF on channel
2394 */
channel_send_eof(LIBSSH2_CHANNEL * channel)2395 static int channel_send_eof(LIBSSH2_CHANNEL *channel)
2396 {
2397 LIBSSH2_SESSION *session = channel->session;
2398 unsigned char packet[5]; /* packet_type(1) + channelno(4) */
2399 int rc;
2400
2401 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
2402 "Sending EOF on channel %lu/%lu",
2403 channel->local.id, channel->remote.id);
2404 packet[0] = SSH_MSG_CHANNEL_EOF;
2405 _libssh2_htonu32(packet + 1, channel->remote.id);
2406 rc = _libssh2_transport_send(session, packet, 5, NULL, 0);
2407 if(rc == LIBSSH2_ERROR_EAGAIN) {
2408 _libssh2_error(session, rc,
2409 "Would block sending EOF");
2410 return rc;
2411 }
2412 else if(rc) {
2413 return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
2414 "Unable to send EOF on channel");
2415 }
2416 channel->local.eof = 1;
2417
2418 return 0;
2419 }
2420
2421 /*
2422 * libssh2_channel_send_eof
2423 *
2424 * Send EOF on channel
2425 */
2426 LIBSSH2_API int
libssh2_channel_send_eof(LIBSSH2_CHANNEL * channel)2427 libssh2_channel_send_eof(LIBSSH2_CHANNEL *channel)
2428 {
2429 int rc;
2430
2431 if(!channel)
2432 return LIBSSH2_ERROR_BAD_USE;
2433
2434 BLOCK_ADJUST(rc, channel->session, channel_send_eof(channel));
2435 return rc;
2436 }
2437
2438 /*
2439 * libssh2_channel_eof
2440 *
2441 * Read channel's eof status
2442 */
2443 LIBSSH2_API int
libssh2_channel_eof(LIBSSH2_CHANNEL * channel)2444 libssh2_channel_eof(LIBSSH2_CHANNEL * channel)
2445 {
2446 LIBSSH2_SESSION *session;
2447 LIBSSH2_PACKET *packet;
2448 LIBSSH2_PACKET *next_packet;
2449
2450 if(!channel)
2451 return LIBSSH2_ERROR_BAD_USE;
2452
2453 session = channel->session;
2454 packet = _libssh2_list_first(&session->packets);
2455
2456 while(packet) {
2457
2458 next_packet = _libssh2_list_next(&packet->node);
2459
2460 if(packet->data_len < 1) {
2461 packet = next_packet;
2462 _libssh2_debug(channel->session, LIBSSH2_TRACE_ERROR,
2463 "Unexpected packet length");
2464 continue;
2465 }
2466
2467 if(((packet->data[0] == SSH_MSG_CHANNEL_DATA)
2468 || (packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA))
2469 && ((packet->data_len >= 5)
2470 && (channel->local.id == _libssh2_ntohu32(packet->data + 1)))) {
2471 /* There's data waiting to be read yet, mask the EOF status */
2472 return 0;
2473 }
2474 packet = next_packet;
2475 }
2476
2477 return channel->remote.eof;
2478 }
2479
2480 /*
2481 * channel_wait_eof
2482 *
2483 * Awaiting channel EOF
2484 */
channel_wait_eof(LIBSSH2_CHANNEL * channel)2485 static int channel_wait_eof(LIBSSH2_CHANNEL *channel)
2486 {
2487 LIBSSH2_SESSION *session = channel->session;
2488 int rc;
2489
2490 if(channel->wait_eof_state == libssh2_NB_state_idle) {
2491 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
2492 "Awaiting EOF for channel %lu/%lu", channel->local.id,
2493 channel->remote.id);
2494
2495 channel->wait_eof_state = libssh2_NB_state_created;
2496 }
2497
2498 /*
2499 * While channel is not eof, read more packets from the network.
2500 * Either the EOF will be set or network timeout will occur.
2501 */
2502 do {
2503 if(channel->remote.eof) {
2504 break;
2505 }
2506
2507 if((channel->remote.window_size == channel->read_avail) &&
2508 session->api_block_mode)
2509 return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_WINDOW_FULL,
2510 "Receiving channel window "
2511 "has been exhausted");
2512
2513 rc = _libssh2_transport_read(session);
2514 if(rc == LIBSSH2_ERROR_EAGAIN) {
2515 return rc;
2516 }
2517 else if(rc < 0) {
2518 channel->wait_eof_state = libssh2_NB_state_idle;
2519 return _libssh2_error(session, rc,
2520 "_libssh2_transport_read() bailed out!");
2521 }
2522 } while(1);
2523
2524 channel->wait_eof_state = libssh2_NB_state_idle;
2525
2526 return 0;
2527 }
2528
2529 /*
2530 * libssh2_channel_wait_eof
2531 *
2532 * Awaiting channel EOF
2533 */
2534 LIBSSH2_API int
libssh2_channel_wait_eof(LIBSSH2_CHANNEL * channel)2535 libssh2_channel_wait_eof(LIBSSH2_CHANNEL *channel)
2536 {
2537 int rc;
2538
2539 if(!channel)
2540 return LIBSSH2_ERROR_BAD_USE;
2541
2542 BLOCK_ADJUST(rc, channel->session, channel_wait_eof(channel));
2543 return rc;
2544 }
2545
_libssh2_channel_close(LIBSSH2_CHANNEL * channel)2546 int _libssh2_channel_close(LIBSSH2_CHANNEL * channel)
2547 {
2548 LIBSSH2_SESSION *session = channel->session;
2549 int rc = 0;
2550
2551 if(channel->local.close) {
2552 /* Already closed, act like we sent another close,
2553 * even though we didn't... shhhhhh */
2554 channel->close_state = libssh2_NB_state_idle;
2555 return 0;
2556 }
2557
2558 if(!channel->local.eof) {
2559 rc = channel_send_eof(channel);
2560 if(rc) {
2561 if(rc == LIBSSH2_ERROR_EAGAIN) {
2562 return rc;
2563 }
2564 _libssh2_error(session, rc,
2565 "Unable to send EOF, but closing channel anyway");
2566 }
2567 }
2568
2569 /* ignore if we have received a remote eof or not, as it is now too
2570 late for us to wait for it. Continue closing! */
2571
2572 if(channel->close_state == libssh2_NB_state_idle) {
2573 _libssh2_debug(session, LIBSSH2_TRACE_CONN, "Closing channel %lu/%lu",
2574 channel->local.id, channel->remote.id);
2575
2576 channel->close_packet[0] = SSH_MSG_CHANNEL_CLOSE;
2577 _libssh2_htonu32(channel->close_packet + 1, channel->remote.id);
2578
2579 channel->close_state = libssh2_NB_state_created;
2580 }
2581
2582 if(channel->close_state == libssh2_NB_state_created) {
2583 rc = _libssh2_transport_send(session, channel->close_packet, 5,
2584 NULL, 0);
2585 if(rc == LIBSSH2_ERROR_EAGAIN) {
2586 _libssh2_error(session, rc,
2587 "Would block sending close-channel");
2588 return rc;
2589
2590 }
2591 else if(rc) {
2592 _libssh2_error(session, rc,
2593 "Unable to send close-channel request, "
2594 "but closing anyway");
2595 /* skip waiting for the response and fall through to
2596 LIBSSH2_CHANNEL_CLOSE below */
2597
2598 }
2599 else
2600 channel->close_state = libssh2_NB_state_sent;
2601 }
2602
2603 if(channel->close_state == libssh2_NB_state_sent) {
2604 /* We must wait for the remote SSH_MSG_CHANNEL_CLOSE message */
2605
2606 while(!channel->remote.close && !rc &&
2607 (session->socket_state != LIBSSH2_SOCKET_DISCONNECTED))
2608 rc = _libssh2_transport_read(session);
2609 }
2610
2611 if(rc != LIBSSH2_ERROR_EAGAIN) {
2612 /* set the local close state first when we're perfectly confirmed to
2613 not do any more EAGAINs */
2614 channel->local.close = 1;
2615
2616 /* We call the callback last in this function to make it keep the local
2617 data as long as EAGAIN is returned. */
2618 if(channel->close_cb) {
2619 LIBSSH2_CHANNEL_CLOSE(session, channel);
2620 }
2621
2622 channel->close_state = libssh2_NB_state_idle;
2623 }
2624
2625 /* return 0 or an error */
2626 return rc >= 0 ? 0 : rc;
2627 }
2628
2629 /*
2630 * libssh2_channel_close
2631 *
2632 * Close a channel
2633 */
2634 LIBSSH2_API int
libssh2_channel_close(LIBSSH2_CHANNEL * channel)2635 libssh2_channel_close(LIBSSH2_CHANNEL *channel)
2636 {
2637 int rc;
2638
2639 if(!channel)
2640 return LIBSSH2_ERROR_BAD_USE;
2641
2642 BLOCK_ADJUST(rc, channel->session, _libssh2_channel_close(channel) );
2643 return rc;
2644 }
2645
2646 /*
2647 * channel_wait_closed
2648 *
2649 * Awaiting channel close after EOF
2650 */
channel_wait_closed(LIBSSH2_CHANNEL * channel)2651 static int channel_wait_closed(LIBSSH2_CHANNEL *channel)
2652 {
2653 LIBSSH2_SESSION *session = channel->session;
2654 int rc;
2655
2656 if(!channel->remote.eof) {
2657 return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
2658 "libssh2_channel_wait_closed() invoked when "
2659 "channel is not in EOF state");
2660 }
2661
2662 if(channel->wait_closed_state == libssh2_NB_state_idle) {
2663 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
2664 "Awaiting close of channel %lu/%lu", channel->local.id,
2665 channel->remote.id);
2666
2667 channel->wait_closed_state = libssh2_NB_state_created;
2668 }
2669
2670 /*
2671 * While channel is not closed, read more packets from the network.
2672 * Either the channel will be closed or network timeout will occur.
2673 */
2674 if(!channel->remote.close) {
2675 do {
2676 rc = _libssh2_transport_read(session);
2677 if(channel->remote.close)
2678 /* it is now closed, move on! */
2679 break;
2680 } while(rc > 0);
2681 if(rc < 0)
2682 return rc;
2683 }
2684
2685 channel->wait_closed_state = libssh2_NB_state_idle;
2686
2687 return 0;
2688 }
2689
2690 /*
2691 * libssh2_channel_wait_closed
2692 *
2693 * Awaiting channel close after EOF
2694 */
2695 LIBSSH2_API int
libssh2_channel_wait_closed(LIBSSH2_CHANNEL * channel)2696 libssh2_channel_wait_closed(LIBSSH2_CHANNEL *channel)
2697 {
2698 int rc;
2699
2700 if(!channel)
2701 return LIBSSH2_ERROR_BAD_USE;
2702
2703 BLOCK_ADJUST(rc, channel->session, channel_wait_closed(channel));
2704 return rc;
2705 }
2706
2707 /*
2708 * _libssh2_channel_free
2709 *
2710 * Make sure a channel is closed, then remove the channel from the session
2711 * and free its resource(s)
2712 *
2713 * Returns 0 on success, negative on failure
2714 */
_libssh2_channel_free(LIBSSH2_CHANNEL * channel)2715 int _libssh2_channel_free(LIBSSH2_CHANNEL *channel)
2716 {
2717 LIBSSH2_SESSION *session = channel->session;
2718 unsigned char channel_id[4];
2719 unsigned char *data;
2720 size_t data_len;
2721 int rc;
2722
2723 assert(session);
2724
2725 if(channel->free_state == libssh2_NB_state_idle) {
2726 _libssh2_debug(session, LIBSSH2_TRACE_CONN,
2727 "Freeing channel %lu/%lu resources", channel->local.id,
2728 channel->remote.id);
2729
2730 channel->free_state = libssh2_NB_state_created;
2731 }
2732
2733 /* Allow channel freeing even when the socket has lost its connection */
2734 if(!channel->local.close
2735 && (session->socket_state == LIBSSH2_SOCKET_CONNECTED)) {
2736 rc = _libssh2_channel_close(channel);
2737
2738 if(rc == LIBSSH2_ERROR_EAGAIN)
2739 return rc;
2740
2741 /* ignore all other errors as they otherwise risk blocking the channel
2742 free from happening */
2743 }
2744
2745 channel->free_state = libssh2_NB_state_idle;
2746
2747 if(channel->exit_signal) {
2748 LIBSSH2_FREE(session, channel->exit_signal);
2749 }
2750
2751 /*
2752 * channel->remote.close *might* not be set yet, Well...
2753 * We've sent the close packet, what more do you want?
2754 * Just let packet_add ignore it when it finally arrives
2755 */
2756
2757 /* Clear out packets meant for this channel */
2758 _libssh2_htonu32(channel_id, channel->local.id);
2759 while((_libssh2_packet_ask(session, SSH_MSG_CHANNEL_DATA, &data,
2760 &data_len, 1, channel_id, 4) >= 0)
2761 ||
2762 (_libssh2_packet_ask(session, SSH_MSG_CHANNEL_EXTENDED_DATA, &data,
2763 &data_len, 1, channel_id, 4) >= 0)) {
2764 LIBSSH2_FREE(session, data);
2765 }
2766
2767 /* free "channel_type" */
2768 if(channel->channel_type) {
2769 LIBSSH2_FREE(session, channel->channel_type);
2770 }
2771
2772 /* Unlink from channel list */
2773 _libssh2_list_remove(&channel->node);
2774
2775 /*
2776 * Make sure all memory used in the state variables are free
2777 */
2778 if(channel->setenv_packet) {
2779 LIBSSH2_FREE(session, channel->setenv_packet);
2780 }
2781 if(channel->reqX11_packet) {
2782 LIBSSH2_FREE(session, channel->reqX11_packet);
2783 }
2784 if(channel->process_packet) {
2785 LIBSSH2_FREE(session, channel->process_packet);
2786 }
2787
2788 LIBSSH2_FREE(session, channel);
2789
2790 return 0;
2791 }
2792
2793 /*
2794 * libssh2_channel_free
2795 *
2796 * Make sure a channel is closed, then remove the channel from the session
2797 * and free its resource(s)
2798 *
2799 * Returns 0 on success, negative on failure
2800 */
2801 LIBSSH2_API int
libssh2_channel_free(LIBSSH2_CHANNEL * channel)2802 libssh2_channel_free(LIBSSH2_CHANNEL *channel)
2803 {
2804 int rc;
2805
2806 if(!channel)
2807 return LIBSSH2_ERROR_BAD_USE;
2808
2809 BLOCK_ADJUST(rc, channel->session, _libssh2_channel_free(channel));
2810 return rc;
2811 }
2812 /*
2813 * libssh2_channel_window_read_ex
2814 *
2815 * Check the status of the read window. Returns the number of bytes which the
2816 * remote end may send without overflowing the window limit read_avail (if
2817 * passed) will be populated with the number of bytes actually available to be
2818 * read window_size_initial (if passed) will be populated with the
2819 * window_size_initial as defined by the channel_open request
2820 */
2821 LIBSSH2_API unsigned long
libssh2_channel_window_read_ex(LIBSSH2_CHANNEL * channel,unsigned long * read_avail,unsigned long * window_size_initial)2822 libssh2_channel_window_read_ex(LIBSSH2_CHANNEL *channel,
2823 unsigned long *read_avail,
2824 unsigned long *window_size_initial)
2825 {
2826 if(!channel)
2827 return 0; /* no channel, no window! */
2828
2829 if(window_size_initial) {
2830 *window_size_initial = channel->remote.window_size_initial;
2831 }
2832
2833 if(read_avail) {
2834 size_t bytes_queued = 0;
2835 LIBSSH2_PACKET *next_packet;
2836 LIBSSH2_PACKET *packet =
2837 _libssh2_list_first(&channel->session->packets);
2838
2839 while(packet) {
2840 unsigned char packet_type;
2841 next_packet = _libssh2_list_next(&packet->node);
2842
2843 if(packet->data_len < 1) {
2844 packet = next_packet;
2845 _libssh2_debug(channel->session, LIBSSH2_TRACE_ERROR,
2846 "Unexpected packet length");
2847 continue;
2848 }
2849
2850 packet_type = packet->data[0];
2851
2852 if(((packet_type == SSH_MSG_CHANNEL_DATA)
2853 || (packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA))
2854 && ((packet->data_len >= 5)
2855 && (_libssh2_ntohu32(packet->data + 1) ==
2856 channel->local.id))) {
2857 bytes_queued += packet->data_len - packet->data_head;
2858 }
2859
2860 packet = next_packet;
2861 }
2862
2863 *read_avail = bytes_queued;
2864 }
2865
2866 return channel->remote.window_size;
2867 }
2868
2869 /*
2870 * libssh2_channel_window_write_ex
2871 *
2872 * Check the status of the write window Returns the number of bytes which may
2873 * be safely written on the channel without blocking window_size_initial (if
2874 * passed) will be populated with the size of the initial window as defined by
2875 * the channel_open request
2876 */
2877 LIBSSH2_API unsigned long
libssh2_channel_window_write_ex(LIBSSH2_CHANNEL * channel,unsigned long * window_size_initial)2878 libssh2_channel_window_write_ex(LIBSSH2_CHANNEL *channel,
2879 unsigned long *window_size_initial)
2880 {
2881 if(!channel)
2882 return 0; /* no channel, no window! */
2883
2884 if(window_size_initial) {
2885 /* For locally initiated channels this is very often 0, so it's not
2886 * *that* useful as information goes */
2887 *window_size_initial = channel->local.window_size_initial;
2888 }
2889
2890 return channel->local.window_size;
2891 }
2892