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