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