Coverage Report

Created: 2025-11-03 07:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libssh2/src/session.c
Line
Count
Source
1
/* Copyright (C) Sara Golemon <sarag@libssh2.org>
2
 * Copyright (C) Daniel Stenberg
3
 * Copyright (C) Simon Josefsson <simon@josefsson.org>
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms,
7
 * with or without modification, are permitted provided
8
 * that the following conditions are met:
9
 *
10
 *   Redistributions of source code must retain the above
11
 *   copyright notice, this list of conditions and the
12
 *   following disclaimer.
13
 *
14
 *   Redistributions in binary form must reproduce the above
15
 *   copyright notice, this list of conditions and the following
16
 *   disclaimer in the documentation and/or other materials
17
 *   provided with the distribution.
18
 *
19
 *   Neither the name of the copyright holder nor the names
20
 *   of any other contributors may be used to endorse or
21
 *   promote products derived from this software without
22
 *   specific prior written permission.
23
 *
24
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
25
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
26
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
29
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
34
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
36
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
37
 * OF SUCH DAMAGE.
38
 *
39
 * SPDX-License-Identifier: BSD-3-Clause
40
 */
41
42
#include "libssh2_priv.h"
43
44
#ifdef _WIN32
45
#include <ws2tcpip.h>  /* for socklen_t */
46
#endif
47
#ifdef HAVE_UNISTD_H
48
#include <unistd.h>
49
#endif
50
#ifdef HAVE_ALLOCA_H
51
#include <alloca.h>
52
#endif
53
54
#include <errno.h>
55
#include <stdlib.h>
56
#include <fcntl.h>
57
58
#include "transport.h"
59
#include "session.h"
60
#include "channel.h"
61
#include "mac.h"
62
63
#ifdef _WIN32
64
#define libssh2_usec_t long
65
#elif defined(__APPLE__)
66
#define libssh2_usec_t suseconds_t
67
#else
68
#undef libssh2_usec_t
69
#endif
70
71
/* libssh2_default_alloc
72
 */
73
static
74
LIBSSH2_ALLOC_FUNC(libssh2_default_alloc)
75
289k
{
76
289k
    (void)abstract;
77
289k
    return malloc(count);
78
289k
}
79
80
/* libssh2_default_free
81
 */
82
static
83
LIBSSH2_FREE_FUNC(libssh2_default_free)
84
288k
{
85
288k
    (void)abstract;
86
288k
    free(ptr);
87
288k
}
88
89
/* libssh2_default_realloc
90
 */
91
static
92
LIBSSH2_REALLOC_FUNC(libssh2_default_realloc)
93
0
{
94
0
    (void)abstract;
95
0
    return realloc(ptr, count);
96
0
}
97
98
/*
99
 * banner_receive
100
 *
101
 * Wait for a hello from the remote host
102
 * Allocate a buffer and store the banner in session->remote.banner
103
 * Returns: 0 on success, LIBSSH2_ERROR_EAGAIN if read would block, negative
104
 * on failure
105
 */
106
static int
107
banner_receive(LIBSSH2_SESSION * session)
108
4.29k
{
109
4.29k
    ssize_t ret;
110
4.29k
    size_t banner_len;
111
112
4.29k
    if(session->banner_TxRx_state == libssh2_NB_state_idle) {
113
4.29k
        banner_len = 0;
114
115
4.29k
        session->banner_TxRx_state = libssh2_NB_state_created;
116
4.29k
    }
117
0
    else {
118
0
        banner_len = session->banner_TxRx_total_send;
119
0
    }
120
121
408k
    while((banner_len < sizeof(session->banner_TxRx_banner)) &&
122
408k
          ((banner_len == 0)
123
404k
           || (session->banner_TxRx_banner[banner_len - 1] != '\n'))) {
124
404k
        char c = '\0';
125
126
        /* no incoming block yet! */
127
404k
        session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_INBOUND;
128
129
404k
        ret = LIBSSH2_RECV(session, &c, 1,
130
404k
                           LIBSSH2_SOCKET_RECV_FLAGS(session));
131
404k
        if(ret < 0) {
132
0
            if(session->api_block_mode || (ret != -EAGAIN))
133
                /* ignore EAGAIN when non-blocking */
134
0
                _libssh2_debug((session, LIBSSH2_TRACE_SOCKET,
135
0
                               "Error recving %d bytes: %ld", 1, (long)-ret));
136
0
        }
137
404k
        else
138
404k
            _libssh2_debug((session, LIBSSH2_TRACE_SOCKET,
139
404k
                           "Recved %ld bytes banner", (long)ret));
140
141
404k
        if(ret < 0) {
142
0
            if(ret == -EAGAIN) {
143
0
                session->socket_block_directions =
144
0
                    LIBSSH2_SESSION_BLOCK_INBOUND;
145
0
                session->banner_TxRx_total_send = banner_len;
146
0
                return LIBSSH2_ERROR_EAGAIN;
147
0
            }
148
149
            /* Some kinda error */
150
0
            session->banner_TxRx_state = libssh2_NB_state_idle;
151
0
            session->banner_TxRx_total_send = 0;
152
0
            return LIBSSH2_ERROR_SOCKET_RECV;
153
0
        }
154
155
404k
        if(ret == 0) {
156
161
            session->socket_state = LIBSSH2_SOCKET_DISCONNECTED;
157
161
            return LIBSSH2_ERROR_SOCKET_DISCONNECT;
158
161
        }
159
160
404k
        if((c == '\r' || c == '\n') && banner_len == 0) {
161
577
            continue;
162
577
        }
163
164
403k
        if(c == '\0') {
165
            /* NULLs are not allowed in SSH banners */
166
9
            session->banner_TxRx_state = libssh2_NB_state_idle;
167
9
            session->banner_TxRx_total_send = 0;
168
9
            return LIBSSH2_ERROR_BANNER_RECV;
169
9
        }
170
171
403k
        session->banner_TxRx_banner[banner_len++] = c;
172
403k
    }
173
174
8.74k
    while(banner_len &&
175
8.74k
          ((session->banner_TxRx_banner[banner_len - 1] == '\n') ||
176
4.65k
           (session->banner_TxRx_banner[banner_len - 1] == '\r'))) {
177
4.62k
        banner_len--;
178
4.62k
    }
179
180
    /* From this point on, we are done here */
181
4.12k
    session->banner_TxRx_state = libssh2_NB_state_idle;
182
4.12k
    session->banner_TxRx_total_send = 0;
183
184
4.12k
    if(!banner_len)
185
0
        return LIBSSH2_ERROR_BANNER_RECV;
186
187
4.12k
    if(session->remote.banner)
188
758
        LIBSSH2_FREE(session, session->remote.banner);
189
190
4.12k
    session->remote.banner = LIBSSH2_ALLOC(session, banner_len + 1);
191
4.12k
    if(!session->remote.banner) {
192
0
        return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
193
0
                              "Error allocating space for remote banner");
194
0
    }
195
4.12k
    memcpy(session->remote.banner, session->banner_TxRx_banner, banner_len);
196
4.12k
    session->remote.banner[banner_len] = '\0';
197
4.12k
    _libssh2_debug((session, LIBSSH2_TRACE_TRANS, "Received Banner: %s",
198
4.12k
                   session->remote.banner));
199
4.12k
    return LIBSSH2_ERROR_NONE;
200
4.12k
}
201
202
/*
203
 * banner_send
204
 *
205
 * Send the default banner, or the one set via libssh2_setopt_string
206
 *
207
 * Returns LIBSSH2_ERROR_EAGAIN if it would block - and if it does so, you
208
 * should call this function again as soon as it is likely that more data can
209
 * be sent, and this function should then be called with the same argument set
210
 * (same data pointer and same data_len) until zero or failure is returned.
211
 */
212
static int
213
banner_send(LIBSSH2_SESSION * session)
214
3.42k
{
215
3.42k
    const char *banner = LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF;
216
3.42k
    size_t banner_len = sizeof(LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF) - 1;
217
3.42k
    ssize_t ret;
218
219
3.42k
    if(session->banner_TxRx_state == libssh2_NB_state_idle) {
220
3.42k
        if(session->local.banner) {
221
            /* setopt_string will have given us our \r\n characters */
222
0
            banner_len = strlen((char *) session->local.banner);
223
0
            banner = (char *) session->local.banner;
224
0
        }
225
3.42k
#ifdef LIBSSH2DEBUG
226
3.42k
        {
227
3.42k
            char banner_dup[256];
228
229
            /* Hack and slash to avoid sending CRLF in debug output */
230
3.42k
            if(banner_len < 256) {
231
3.42k
                memcpy(banner_dup, banner, banner_len - 2);
232
3.42k
                banner_dup[banner_len - 2] = '\0';
233
3.42k
            }
234
0
            else {
235
0
                memcpy(banner_dup, banner, 255);
236
0
                banner_dup[255] = '\0';
237
0
            }
238
239
3.42k
            _libssh2_debug((session, LIBSSH2_TRACE_TRANS,
240
3.42k
                           "Sending Banner: %s", banner_dup));
241
3.42k
        }
242
3.42k
#endif
243
244
3.42k
        session->banner_TxRx_state = libssh2_NB_state_created;
245
3.42k
    }
246
247
    /* no outgoing block yet! */
248
3.42k
    session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_OUTBOUND;
249
250
3.42k
    ret = LIBSSH2_SEND(session,
251
3.42k
                       banner + session->banner_TxRx_total_send,
252
3.42k
                       banner_len - session->banner_TxRx_total_send,
253
3.42k
                       LIBSSH2_SOCKET_SEND_FLAGS(session));
254
3.42k
    if(ret < 0)
255
0
        _libssh2_debug((session, LIBSSH2_TRACE_SOCKET,
256
3.42k
                       "Error sending %ld bytes: %ld",
257
3.42k
                       (long)(banner_len - session->banner_TxRx_total_send),
258
3.42k
                       (long)-ret));
259
3.42k
    else
260
3.42k
        _libssh2_debug((session, LIBSSH2_TRACE_SOCKET,
261
3.42k
                       "Sent %ld/%ld bytes at %p+%ld", (long)ret,
262
3.42k
                       (long)(banner_len - session->banner_TxRx_total_send),
263
3.42k
                       (const void *)banner,
264
3.42k
                       (long)session->banner_TxRx_total_send));
265
266
3.42k
    if(ret != (ssize_t)(banner_len - session->banner_TxRx_total_send)) {
267
0
        if(ret >= 0 || ret == -EAGAIN) {
268
            /* the whole packet could not be sent, save the what was */
269
0
            session->socket_block_directions =
270
0
                LIBSSH2_SESSION_BLOCK_OUTBOUND;
271
0
            if(ret > 0)
272
0
                session->banner_TxRx_total_send += ret;
273
0
            return LIBSSH2_ERROR_EAGAIN;
274
0
        }
275
0
        session->banner_TxRx_state = libssh2_NB_state_idle;
276
0
        session->banner_TxRx_total_send = 0;
277
0
        return LIBSSH2_ERROR_SOCKET_RECV;
278
0
    }
279
280
    /* Set the state back to idle */
281
3.42k
    session->banner_TxRx_state = libssh2_NB_state_idle;
282
3.42k
    session->banner_TxRx_total_send = 0;
283
284
3.42k
    return 0;
285
3.42k
}
286
287
/*
288
 * session_nonblock() sets the given socket to either blocking or
289
 * non-blocking mode based on the 'nonblock' boolean argument. This function
290
 * is copied from the libcurl sources with permission.
291
 */
292
static int
293
session_nonblock(libssh2_socket_t sockfd,   /* operate on this */
294
                 int nonblock /* TRUE or FALSE */ )
295
6.84k
{
296
6.84k
#ifdef HAVE_O_NONBLOCK
297
    /* most recent unix versions */
298
6.84k
    int flags;
299
300
6.84k
    flags = fcntl(sockfd, F_GETFL, 0);
301
6.84k
    if(nonblock)
302
3.42k
        return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
303
3.42k
    else
304
3.42k
        return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK));
305
#elif defined(HAVE_FIONBIO)
306
    /* older unix versions and VMS */
307
    int flags;
308
309
    flags = nonblock;
310
    return ioctl(sockfd, FIONBIO, &flags);
311
#elif defined(HAVE_IOCTLSOCKET_CASE)
312
    /* presumably for Amiga */
313
    return IoctlSocket(sockfd, FIONBIO, (long) nonblock);
314
#elif defined(HAVE_SO_NONBLOCK)
315
    /* BeOS */
316
    long b = nonblock ? 1 : 0;
317
    return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));
318
#elif defined(_WIN32)
319
    unsigned long flags;
320
321
    flags = nonblock;
322
    return ioctlsocket(sockfd, FIONBIO, &flags);
323
#else
324
    (void)sockfd;
325
    (void)nonblock;
326
    return 0;                   /* returns success */
327
#endif
328
6.84k
}
329
330
/*
331
 * get_socket_nonblocking
332
 *
333
 * gets the given blocking or non-blocking state of the socket.
334
 */
335
static int
336
get_socket_nonblocking(libssh2_socket_t sockfd)
337
3.42k
{                               /* operate on this */
338
3.42k
#ifdef HAVE_O_NONBLOCK
339
    /* most recent unix versions */
340
3.42k
    int flags = fcntl(sockfd, F_GETFL, 0);
341
342
3.42k
    if(flags == -1) {
343
        /* Assume blocking on error */
344
0
        return 1;
345
0
    }
346
3.42k
    return (flags & O_NONBLOCK);
347
#elif defined(HAVE_SO_NONBLOCK)
348
    /* BeOS */
349
    long b;
350
    if(getsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b))) {
351
        /* Assume blocking on error */
352
        return 1;
353
    }
354
    return (int) b;
355
#elif defined(SO_STATE) && defined(__VMS)
356
    /* VMS TCP/IP Services */
357
358
    size_t sockstat = 0;
359
    int    callstat = 0;
360
    size_t size = sizeof(int);
361
362
    callstat = getsockopt(sockfd, SOL_SOCKET, SO_STATE,
363
                          (char *)&sockstat, &size);
364
    if(callstat == -1) {
365
        return 0;
366
    }
367
    if((sockstat&SS_NBIO) != 0) {
368
        return 1;
369
    }
370
    return 0;
371
#elif defined(_WIN32)
372
    unsigned int option_value;
373
    socklen_t option_len = sizeof(option_value);
374
375
    if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR,
376
                  (void *) &option_value, &option_len)) {
377
        /* Assume blocking on error */
378
        return 1;
379
    }
380
    return (int) option_value;
381
#else
382
    (void)sockfd;
383
    return 1;                   /* returns blocking */
384
#endif
385
3.42k
}
386
387
/* libssh2_session_banner_set
388
 * Set the local banner to use in the server handshake.
389
 */
390
LIBSSH2_API int
391
libssh2_session_banner_set(LIBSSH2_SESSION * session, const char *banner)
392
0
{
393
0
    size_t banner_len = banner ? strlen(banner) : 0;
394
395
0
    if(session->local.banner) {
396
0
        LIBSSH2_FREE(session, session->local.banner);
397
0
        session->local.banner = NULL;
398
0
    }
399
400
0
    if(!banner_len)
401
0
        return 0;
402
403
0
    session->local.banner = LIBSSH2_ALLOC(session, banner_len + 3);
404
0
    if(!session->local.banner) {
405
0
        return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
406
0
                              "Unable to allocate memory for local banner");
407
0
    }
408
409
0
    memcpy(session->local.banner, banner, banner_len);
410
411
    /* first zero terminate like this so that the debug output is nice */
412
0
    session->local.banner[banner_len] = '\0';
413
0
    _libssh2_debug((session, LIBSSH2_TRACE_TRANS, "Setting local Banner: %s",
414
0
                   session->local.banner));
415
0
    session->local.banner[banner_len++] = '\r';
416
0
    session->local.banner[banner_len++] = '\n';
417
0
    session->local.banner[banner_len] = '\0';
418
419
0
    return 0;
420
0
}
421
422
#ifndef LIBSSH2_NO_DEPRECATED
423
/* libssh2_banner_set
424
 * Set the local banner. DEPRECATED VERSION
425
 */
426
LIBSSH2_API int
427
libssh2_banner_set(LIBSSH2_SESSION * session, const char *banner)
428
0
{
429
0
    return libssh2_session_banner_set(session, banner);
430
0
}
431
#endif
432
433
/*
434
 * libssh2_session_init_ex
435
 *
436
 * Allocate and initialize a libssh2 session structure. Allows for malloc
437
 * callbacks in case the calling program has its own memory manager It's
438
 * allowable (but unadvisable) to define some but not all of the malloc
439
 * callbacks An additional pointer value may be optionally passed to be sent
440
 * to the callbacks (so they know who's asking)
441
 */
442
LIBSSH2_API LIBSSH2_SESSION *
443
libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)),
444
                        LIBSSH2_FREE_FUNC((*my_free)),
445
                        LIBSSH2_REALLOC_FUNC((*my_realloc)), void *abstract)
446
3.42k
{
447
3.42k
    LIBSSH2_ALLOC_FUNC((*local_alloc)) = libssh2_default_alloc;
448
3.42k
    LIBSSH2_FREE_FUNC((*local_free)) = libssh2_default_free;
449
3.42k
    LIBSSH2_REALLOC_FUNC((*local_realloc)) = libssh2_default_realloc;
450
3.42k
    LIBSSH2_SESSION *session;
451
452
3.42k
    if(my_alloc) {
453
0
        local_alloc = my_alloc;
454
0
    }
455
3.42k
    if(my_free) {
456
0
        local_free = my_free;
457
0
    }
458
3.42k
    if(my_realloc) {
459
0
        local_realloc = my_realloc;
460
0
    }
461
462
3.42k
    session = local_alloc(sizeof(LIBSSH2_SESSION), &abstract);
463
3.42k
    if(session) {
464
3.42k
        memset(session, 0, sizeof(LIBSSH2_SESSION));
465
3.42k
        session->alloc = local_alloc;
466
3.42k
        session->free = local_free;
467
3.42k
        session->realloc = local_realloc;
468
3.42k
        session->send = _libssh2_send;
469
3.42k
        session->recv = _libssh2_recv;
470
3.42k
        session->abstract = abstract;
471
3.42k
        session->api_timeout = 0; /* timeout-free API by default */
472
3.42k
        session->api_block_mode = 1; /* blocking API by default */
473
3.42k
        session->state = LIBSSH2_STATE_INITIAL_KEX;
474
3.42k
        session->fullpacket_required_type = 0;
475
3.42k
        session->packet_read_timeout = LIBSSH2_DEFAULT_READ_TIMEOUT;
476
3.42k
        session->flag.quote_paths = 1; /* default behavior is to quote paths
477
                                          for the scp subsystem */
478
3.42k
        session->kex = NULL;
479
3.42k
        _libssh2_debug((session, LIBSSH2_TRACE_TRANS,
480
3.42k
                       "New session resource allocated"));
481
3.42k
        _libssh2_init_if_needed();
482
3.42k
    }
483
3.42k
    return session;
484
3.42k
}
485
486
/*
487
 * libssh2_session_callback_set2
488
 *
489
 * Set (or reset) a callback function
490
 * Returns the prior address
491
 */
492
#ifdef __clang__
493
#pragma clang diagnostic push
494
#pragma clang diagnostic ignored "-Wcast-function-type"
495
#endif
496
LIBSSH2_API libssh2_cb_generic *
497
libssh2_session_callback_set2(LIBSSH2_SESSION *session, int cbtype,
498
                              libssh2_cb_generic *callback)
499
0
{
500
0
    libssh2_cb_generic *oldcb;
501
502
0
    switch(cbtype) {
503
0
    case LIBSSH2_CALLBACK_IGNORE:
504
0
        oldcb = (libssh2_cb_generic *)session->ssh_msg_ignore;
505
0
        session->ssh_msg_ignore = (LIBSSH2_IGNORE_FUNC((*)))callback;
506
0
        return oldcb;
507
508
0
    case LIBSSH2_CALLBACK_DEBUG:
509
0
        oldcb = (libssh2_cb_generic *)session->ssh_msg_debug;
510
0
        session->ssh_msg_debug = (LIBSSH2_DEBUG_FUNC((*)))callback;
511
0
        return oldcb;
512
513
0
    case LIBSSH2_CALLBACK_DISCONNECT:
514
0
        oldcb = (libssh2_cb_generic *)session->ssh_msg_disconnect;
515
0
        session->ssh_msg_disconnect = (LIBSSH2_DISCONNECT_FUNC((*)))callback;
516
0
        return oldcb;
517
518
0
    case LIBSSH2_CALLBACK_MACERROR:
519
0
        oldcb = (libssh2_cb_generic *)session->macerror;
520
0
        session->macerror = (LIBSSH2_MACERROR_FUNC((*)))callback;
521
0
        return oldcb;
522
523
0
    case LIBSSH2_CALLBACK_X11:
524
0
        oldcb = (libssh2_cb_generic *)session->x11;
525
0
        session->x11 = (LIBSSH2_X11_OPEN_FUNC((*)))callback;
526
0
        return oldcb;
527
528
0
    case LIBSSH2_CALLBACK_SEND:
529
0
        oldcb = (libssh2_cb_generic *)session->send;
530
0
        session->send = (LIBSSH2_SEND_FUNC((*)))callback;
531
0
        return oldcb;
532
533
0
    case LIBSSH2_CALLBACK_RECV:
534
0
        oldcb = (libssh2_cb_generic *)session->recv;
535
0
        session->recv = (LIBSSH2_RECV_FUNC((*)))callback;
536
0
        return oldcb;
537
538
0
    case LIBSSH2_CALLBACK_AUTHAGENT:
539
0
        oldcb = (libssh2_cb_generic *)session->authagent;
540
0
        session->authagent = (LIBSSH2_AUTHAGENT_FUNC((*)))callback;
541
0
        return oldcb;
542
543
0
    case LIBSSH2_CALLBACK_AUTHAGENT_IDENTITIES:
544
0
        oldcb = (libssh2_cb_generic *)session->addLocalIdentities;
545
0
        session->addLocalIdentities =
546
0
            (LIBSSH2_ADD_IDENTITIES_FUNC((*)))callback;
547
0
        return oldcb;
548
549
0
    case LIBSSH2_CALLBACK_AUTHAGENT_SIGN:
550
0
        oldcb = (libssh2_cb_generic *)session->agentSignCallback;
551
0
        session->agentSignCallback =
552
0
            (LIBSSH2_AUTHAGENT_SIGN_FUNC((*)))callback;
553
0
        return oldcb;
554
0
    }
555
0
    _libssh2_debug((session, LIBSSH2_TRACE_TRANS, "Setting Callback %d",
556
0
                   cbtype));
557
558
0
    return NULL;
559
0
}
560
#ifdef __clang__
561
#pragma clang diagnostic pop
562
#endif
563
564
/*
565
 * libssh2_session_callback_set (DEPRECATED, DO NOT USE!)
566
 *
567
 * Set (or reset) a callback function
568
 * Returns the prior address
569
 *
570
 * ALERT: this function relies on that we can typecast function pointers
571
 * to void pointers, which isn't allowed in ISO C!
572
 */
573
#ifdef _MSC_VER
574
#pragma warning(push)
575
/* 'type cast': from data pointer to function pointer */
576
#pragma warning(disable:4054)
577
/* 'type cast': from function pointer to data pointer */
578
#pragma warning(disable:4055)
579
#else
580
#pragma GCC diagnostic push
581
#pragma GCC diagnostic ignored "-Wpedantic"
582
#endif
583
LIBSSH2_API void *
584
libssh2_session_callback_set(LIBSSH2_SESSION * session,
585
                             int cbtype, void *callback)
586
0
{
587
0
    return (void *)libssh2_session_callback_set2(session, cbtype,
588
0
                                               (libssh2_cb_generic *)callback);
589
0
}
590
#ifdef _MSC_VER
591
#pragma warning(pop)
592
#else
593
#pragma GCC diagnostic pop
594
#endif
595
596
/*
597
 * _libssh2_wait_socket
598
 *
599
 * Utility function that waits for action on the socket. Returns 0 when ready
600
 * to run again or error on timeout.
601
 */
602
int _libssh2_wait_socket(LIBSSH2_SESSION *session, time_t start_time)
603
28
{
604
28
    int rc;
605
28
    int seconds_to_next;
606
28
    int dir;
607
28
    int has_timeout;
608
28
    long ms_to_next = 0;
609
28
    long elapsed_ms;
610
611
    /* since libssh2 often sets EAGAIN internally before this function is
612
       called, we can decrease some amount of confusion in user programs by
613
       resetting the error code in this function to reduce the risk of EAGAIN
614
       being stored as error when a blocking function has returned */
615
28
    session->err_code = LIBSSH2_ERROR_NONE;
616
617
28
    rc = libssh2_keepalive_send(session, &seconds_to_next);
618
28
    if(rc)
619
0
        return rc;
620
621
28
    ms_to_next = seconds_to_next * 1000;
622
623
    /* figure out what to wait for */
624
28
    dir = libssh2_session_block_directions(session);
625
626
28
    if(!dir) {
627
0
        _libssh2_debug((session, LIBSSH2_TRACE_SOCKET,
628
0
                       "Nothing to wait for in wait_socket"));
629
        /* To avoid that we hang below just because there's nothing set to
630
           wait for, we timeout on 1 second to also avoid busy-looping
631
           during this condition */
632
0
        ms_to_next = 1000;
633
0
    }
634
635
28
    if(session->api_timeout > 0 &&
636
0
        (seconds_to_next == 0 ||
637
0
         ms_to_next > session->api_timeout)) {
638
0
        time_t now = time(NULL);
639
0
        elapsed_ms = (long)(1000*difftime(now, start_time));
640
0
        if(elapsed_ms > session->api_timeout) {
641
0
            return _libssh2_error(session, LIBSSH2_ERROR_TIMEOUT,
642
0
                                  "API timeout expired");
643
0
        }
644
0
        ms_to_next = (session->api_timeout - elapsed_ms);
645
0
        has_timeout = 1;
646
0
    }
647
28
    else if(ms_to_next > 0) {
648
0
        has_timeout = 1;
649
0
    }
650
28
    else
651
28
        has_timeout = 0;
652
653
28
#ifdef HAVE_POLL
654
28
    {
655
28
        struct pollfd sockets[1];
656
657
28
        sockets[0].fd = session->socket_fd;
658
28
        sockets[0].events = 0;
659
28
        sockets[0].revents = 0;
660
661
28
        if(dir & LIBSSH2_SESSION_BLOCK_INBOUND)
662
28
            sockets[0].events |= POLLIN;
663
664
28
        if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)
665
0
            sockets[0].events |= POLLOUT;
666
667
28
        rc = poll(sockets, 1, has_timeout ? (int)ms_to_next : -1);
668
28
    }
669
#else
670
    {
671
        fd_set rfd;
672
        fd_set wfd;
673
        fd_set *writefd = NULL;
674
        fd_set *readfd = NULL;
675
        struct timeval tv;
676
677
        tv.tv_sec = ms_to_next / 1000;
678
#ifdef libssh2_usec_t
679
        tv.tv_usec = (libssh2_usec_t)((ms_to_next - tv.tv_sec*1000) * 1000);
680
#else
681
        tv.tv_usec = (ms_to_next - tv.tv_sec*1000) * 1000;
682
#endif
683
684
        if(dir & LIBSSH2_SESSION_BLOCK_INBOUND) {
685
            FD_ZERO(&rfd);
686
#if defined(__GNUC__) || defined(__clang__)
687
#pragma GCC diagnostic push
688
#pragma GCC diagnostic ignored "-Wsign-conversion"
689
#endif
690
            FD_SET(session->socket_fd, &rfd);
691
#if defined(__GNUC__) || defined(__clang__)
692
#pragma GCC diagnostic pop
693
#endif
694
            readfd = &rfd;
695
        }
696
697
        if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND) {
698
            FD_ZERO(&wfd);
699
#if defined(__GNUC__) || defined(__clang__)
700
#pragma GCC diagnostic push
701
#pragma GCC diagnostic ignored "-Wsign-conversion"
702
#endif
703
            FD_SET(session->socket_fd, &wfd);
704
#if defined(__GNUC__) || defined(__clang__)
705
#pragma GCC diagnostic pop
706
#endif
707
            writefd = &wfd;
708
        }
709
710
        rc = select((int)(session->socket_fd + 1), readfd, writefd, NULL,
711
                    has_timeout ? &tv : NULL);
712
    }
713
#endif
714
28
    if(rc == 0) {
715
0
        return _libssh2_error(session, LIBSSH2_ERROR_TIMEOUT,
716
0
                              "Timed out waiting on socket");
717
0
    }
718
28
    if(rc < 0) {
719
0
        int err;
720
#ifdef _WIN32
721
        err = _libssh2_wsa2errno();
722
#else
723
0
        err = errno;
724
0
#endif
725
        /* Profiling tools that use SIGPROF can cause EINTR responses.
726
           poll() / select() do not set any descriptor states on EINTR,
727
           but some fds may be ready, so the caller should try again */
728
0
        if(err == EINTR)
729
0
            return 0;
730
731
0
        return _libssh2_error(session, LIBSSH2_ERROR_TIMEOUT,
732
0
                              "Error waiting on socket");
733
0
    }
734
735
28
    return 0; /* ready to try again */
736
28
}
737
738
static int
739
session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock)
740
3.45k
{
741
3.45k
    int rc;
742
743
3.45k
    if(!session) {
744
0
        fprintf(stderr, "Session is NULL, error: %i\n",
745
0
                LIBSSH2_ERROR_PROTO);
746
0
        return LIBSSH2_ERROR_PROTO;
747
0
    }
748
749
3.45k
    if(session->startup_state == libssh2_NB_state_idle) {
750
3.42k
        _libssh2_debug((session, LIBSSH2_TRACE_TRANS,
751
3.42k
                       "session_startup for socket %ld", (long)sock));
752
3.42k
        if(LIBSSH2_INVALID_SOCKET == sock) {
753
            /* Did we forget something? */
754
0
            return _libssh2_error(session, LIBSSH2_ERROR_BAD_SOCKET,
755
0
                                  "Bad socket provided");
756
0
        }
757
3.42k
        session->socket_fd = sock;
758
759
3.42k
        session->socket_prev_blockstate =
760
3.42k
            !get_socket_nonblocking(session->socket_fd);
761
762
3.42k
        if(session->socket_prev_blockstate) {
763
            /* If in blocking state change to non-blocking */
764
3.42k
            rc = session_nonblock(session->socket_fd, 1);
765
3.42k
            if(rc) {
766
0
                return _libssh2_error(session, rc,
767
0
                                      "Failed changing socket's "
768
0
                                      "blocking state to non-blocking");
769
0
            }
770
3.42k
        }
771
772
3.42k
        session->startup_state = libssh2_NB_state_created;
773
3.42k
    }
774
775
3.45k
    if(session->startup_state == libssh2_NB_state_created) {
776
3.42k
        rc = banner_send(session);
777
3.42k
        if(rc == LIBSSH2_ERROR_EAGAIN)
778
0
            return rc;
779
3.42k
        else if(rc) {
780
0
            return _libssh2_error(session, rc,
781
0
                                  "Failed sending banner");
782
0
        }
783
3.42k
        session->startup_state = libssh2_NB_state_sent;
784
3.42k
        session->banner_TxRx_state = libssh2_NB_state_idle;
785
3.42k
    }
786
787
3.45k
    if(session->startup_state == libssh2_NB_state_sent) {
788
4.29k
        do {
789
4.29k
            rc = banner_receive(session);
790
4.29k
            if(rc == LIBSSH2_ERROR_EAGAIN)
791
0
                return rc;
792
4.29k
            else if(rc)
793
170
                return _libssh2_error(session, rc,
794
170
                                      "Failed getting banner");
795
4.29k
        } while(strncmp("SSH-", (const char *)session->remote.banner, 4));
796
797
3.25k
        session->startup_state = libssh2_NB_state_sent1;
798
3.25k
    }
799
800
3.28k
    if(session->startup_state == libssh2_NB_state_sent1) {
801
3.28k
        rc = _libssh2_kex_exchange(session, 0, &session->startup_key_state);
802
3.28k
        if(rc == LIBSSH2_ERROR_EAGAIN)
803
28
            return rc;
804
3.25k
        else if(rc)
805
3.24k
            return _libssh2_error(session, rc,
806
3.24k
                                  "Unable to exchange encryption keys");
807
808
5
        session->startup_state = libssh2_NB_state_sent2;
809
5
    }
810
811
5
    if(session->startup_state == libssh2_NB_state_sent2) {
812
5
        _libssh2_debug((session, LIBSSH2_TRACE_TRANS,
813
5
                       "Requesting userauth service"));
814
815
        /* Request the userauth service */
816
5
        session->startup_service[0] = SSH_MSG_SERVICE_REQUEST;
817
5
        _libssh2_htonu32(session->startup_service + 1,
818
5
                         sizeof("ssh-userauth") - 1);
819
5
        memcpy(session->startup_service + 5, "ssh-userauth",
820
5
               sizeof("ssh-userauth") - 1);
821
822
5
        session->startup_state = libssh2_NB_state_sent3;
823
5
    }
824
825
5
    if(session->startup_state == libssh2_NB_state_sent3) {
826
5
        rc = _libssh2_transport_send(session, session->startup_service,
827
5
                                     sizeof("ssh-userauth") + 5 - 1,
828
5
                                     NULL, 0);
829
5
        if(rc == LIBSSH2_ERROR_EAGAIN)
830
0
            return rc;
831
5
        else if(rc) {
832
0
            return _libssh2_error(session, rc,
833
0
                                  "Unable to ask for ssh-userauth service");
834
0
        }
835
836
5
        session->startup_state = libssh2_NB_state_sent4;
837
5
    }
838
839
5
    if(session->startup_state == libssh2_NB_state_sent4) {
840
5
        rc = _libssh2_packet_require(session, SSH_MSG_SERVICE_ACCEPT,
841
5
                                     &session->startup_data,
842
5
                                     &session->startup_data_len, 0, NULL, 0,
843
5
                                     &session->startup_req_state);
844
5
        if(rc)
845
2
            return _libssh2_error(session, rc,
846
2
                                  "Failed to get response to "
847
2
                                  "ssh-userauth request");
848
849
3
        if(session->startup_data_len < 5) {
850
1
            return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
851
1
                                  "Unexpected packet length");
852
1
        }
853
854
2
        session->startup_service_length =
855
2
            _libssh2_ntohu32(session->startup_data + 1);
856
857
858
2
        if((session->startup_service_length != (sizeof("ssh-userauth") - 1))
859
0
            || strncmp("ssh-userauth",
860
0
                       (const char *) session->startup_data + 5,
861
2
                       session->startup_service_length)) {
862
2
            LIBSSH2_FREE(session, session->startup_data);
863
2
            session->startup_data = NULL;
864
2
            return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
865
2
                                  "Invalid response received from server");
866
2
        }
867
0
        LIBSSH2_FREE(session, session->startup_data);
868
0
        session->startup_data = NULL;
869
870
0
        session->startup_state = libssh2_NB_state_idle;
871
872
0
        return 0;
873
2
    }
874
875
    /* just for safety return some error */
876
0
    return LIBSSH2_ERROR_INVAL;
877
5
}
878
879
/*
880
 * libssh2_session_handshake
881
 *
882
 * session: LIBSSH2_SESSION struct allocated and owned by the calling program
883
 * sock:    *must* be populated with an opened and connected socket.
884
 *
885
 * Returns: 0 on success, or non-zero on failure
886
 */
887
LIBSSH2_API int
888
libssh2_session_handshake(LIBSSH2_SESSION *session, libssh2_socket_t sock)
889
3.42k
{
890
3.42k
    int rc;
891
892
3.42k
    BLOCK_ADJUST(rc, session, session_startup(session, sock));
893
894
3.42k
    return rc;
895
3.42k
}
896
897
#ifndef LIBSSH2_NO_DEPRECATED
898
/*
899
 * libssh2_session_startup
900
 *
901
 * DEPRECATED. Use libssh2_session_handshake() instead! This function is not
902
 * portable enough.
903
 *
904
 * session: LIBSSH2_SESSION struct allocated and owned by the calling program
905
 * sock:    *must* be populated with an opened and connected socket.
906
 *
907
 * Returns: 0 on success, or non-zero on failure
908
 */
909
LIBSSH2_API int
910
libssh2_session_startup(LIBSSH2_SESSION *session, int sock)
911
0
{
912
0
    return libssh2_session_handshake(session, (libssh2_socket_t) sock);
913
0
}
914
#endif
915
916
/*
917
 * session_free
918
 *
919
 * Frees the memory allocated to the session
920
 * Also closes and frees any channels attached to this session
921
 */
922
static int
923
session_free(LIBSSH2_SESSION *session)
924
3.42k
{
925
3.42k
    int rc;
926
3.42k
    LIBSSH2_PACKET *pkg;
927
3.42k
    LIBSSH2_CHANNEL *ch;
928
3.42k
    LIBSSH2_LISTENER *l;
929
3.42k
    int packets_left = 0;
930
931
3.42k
    if(session->free_state == libssh2_NB_state_idle) {
932
3.42k
        _libssh2_debug((session, LIBSSH2_TRACE_TRANS,
933
3.42k
                       "Freeing session resource %p",
934
3.42k
                       (void *)session->remote.banner));
935
936
3.42k
        session->free_state = libssh2_NB_state_created;
937
3.42k
    }
938
939
3.42k
    if(session->free_state == libssh2_NB_state_created) {
940
        /* !checksrc! disable EQUALSNULL 1 */
941
3.42k
        while((ch = _libssh2_list_first(&session->channels)) != NULL) {
942
0
            rc = _libssh2_channel_free(ch);
943
0
            if(rc == LIBSSH2_ERROR_EAGAIN)
944
0
                return rc;
945
0
        }
946
947
3.42k
        session->free_state = libssh2_NB_state_sent;
948
3.42k
    }
949
950
3.42k
    if(session->free_state == libssh2_NB_state_sent) {
951
        /* !checksrc! disable EQUALSNULL 1 */
952
3.42k
        while((l = _libssh2_list_first(&session->listeners)) != NULL) {
953
0
            rc = _libssh2_channel_forward_cancel(l);
954
0
            if(rc == LIBSSH2_ERROR_EAGAIN)
955
0
                return rc;
956
0
        }
957
958
3.42k
        session->free_state = libssh2_NB_state_sent1;
959
3.42k
    }
960
961
3.42k
    if(session->kex && session->kex->cleanup) {
962
1.27k
        session->kex->cleanup(session,
963
1.27k
                              &session->startup_key_state.key_state_low);
964
1.27k
    }
965
966
3.42k
    if(session->state & LIBSSH2_STATE_NEWKEYS) {
967
        /* hostkey */
968
0
        if(session->hostkey && session->hostkey->dtor) {
969
0
            session->hostkey->dtor(session, &session->server_hostkey_abstract);
970
0
        }
971
972
        /* Client to Server */
973
        /* crypt */
974
0
        if(session->local.crypt && session->local.crypt->dtor) {
975
0
            session->local.crypt->dtor(session,
976
0
                                       &session->local.crypt_abstract);
977
0
        }
978
        /* comp */
979
0
        if(session->local.comp && session->local.comp->dtor) {
980
0
            session->local.comp->dtor(session, 1,
981
0
                                      &session->local.comp_abstract);
982
0
        }
983
        /* mac */
984
0
        if(session->local.mac && session->local.mac->dtor) {
985
0
            session->local.mac->dtor(session, &session->local.mac_abstract);
986
0
        }
987
988
        /* Server to Client */
989
        /* crypt */
990
0
        if(session->remote.crypt && session->remote.crypt->dtor) {
991
0
            session->remote.crypt->dtor(session,
992
0
                                        &session->remote.crypt_abstract);
993
0
        }
994
        /* comp */
995
0
        if(session->remote.comp && session->remote.comp->dtor) {
996
0
            session->remote.comp->dtor(session, 0,
997
0
                                       &session->remote.comp_abstract);
998
0
        }
999
        /* mac */
1000
0
        if(session->remote.mac && session->remote.mac->dtor) {
1001
0
            session->remote.mac->dtor(session, &session->remote.mac_abstract);
1002
0
        }
1003
1004
        /* session_id */
1005
0
        if(session->session_id) {
1006
0
            LIBSSH2_FREE(session, session->session_id);
1007
0
        }
1008
0
    }
1009
1010
    /* Free banner(s) */
1011
3.42k
    if(session->remote.banner) {
1012
3.36k
        LIBSSH2_FREE(session, session->remote.banner);
1013
3.36k
    }
1014
3.42k
    if(session->local.banner) {
1015
0
        LIBSSH2_FREE(session, session->local.banner);
1016
0
    }
1017
1018
    /* Free preference(s) */
1019
3.42k
    if(session->kex_prefs) {
1020
0
        LIBSSH2_FREE(session, session->kex_prefs);
1021
0
    }
1022
3.42k
    if(session->hostkey_prefs) {
1023
0
        LIBSSH2_FREE(session, session->hostkey_prefs);
1024
0
    }
1025
1026
3.42k
    if(session->local.kexinit) {
1027
0
        LIBSSH2_FREE(session, session->local.kexinit);
1028
0
    }
1029
3.42k
    if(session->local.crypt_prefs) {
1030
0
        LIBSSH2_FREE(session, session->local.crypt_prefs);
1031
0
    }
1032
3.42k
    if(session->local.mac_prefs) {
1033
0
        LIBSSH2_FREE(session, session->local.mac_prefs);
1034
0
    }
1035
3.42k
    if(session->local.comp_prefs) {
1036
0
        LIBSSH2_FREE(session, session->local.comp_prefs);
1037
0
    }
1038
3.42k
    if(session->local.lang_prefs) {
1039
0
        LIBSSH2_FREE(session, session->local.lang_prefs);
1040
0
    }
1041
1042
3.42k
    if(session->remote.kexinit) {
1043
0
        LIBSSH2_FREE(session, session->remote.kexinit);
1044
0
    }
1045
3.42k
    if(session->remote.crypt_prefs) {
1046
0
        LIBSSH2_FREE(session, session->remote.crypt_prefs);
1047
0
    }
1048
3.42k
    if(session->remote.mac_prefs) {
1049
0
        LIBSSH2_FREE(session, session->remote.mac_prefs);
1050
0
    }
1051
3.42k
    if(session->remote.comp_prefs) {
1052
0
        LIBSSH2_FREE(session, session->remote.comp_prefs);
1053
0
    }
1054
3.42k
    if(session->remote.lang_prefs) {
1055
0
        LIBSSH2_FREE(session, session->remote.lang_prefs);
1056
0
    }
1057
3.42k
    if(session->server_sign_algorithms) {
1058
31
        LIBSSH2_FREE(session, session->server_sign_algorithms);
1059
31
    }
1060
3.42k
    if(session->sign_algo_prefs) {
1061
0
        LIBSSH2_FREE(session, session->sign_algo_prefs);
1062
0
    }
1063
1064
    /*
1065
     * Make sure all memory used in the state variables are free
1066
     */
1067
3.42k
    if(session->kexinit_data) {
1068
0
        LIBSSH2_FREE(session, session->kexinit_data);
1069
0
    }
1070
3.42k
    if(session->startup_data) {
1071
1
        LIBSSH2_FREE(session, session->startup_data);
1072
1
    }
1073
3.42k
    if(session->userauth_list_data) {
1074
0
        LIBSSH2_FREE(session, session->userauth_list_data);
1075
0
    }
1076
3.42k
    if(session->userauth_banner) {
1077
0
        LIBSSH2_FREE(session, session->userauth_banner);
1078
0
    }
1079
3.42k
    if(session->userauth_pswd_data) {
1080
0
        LIBSSH2_FREE(session, session->userauth_pswd_data);
1081
0
    }
1082
3.42k
    if(session->userauth_pswd_newpw) {
1083
0
        LIBSSH2_FREE(session, session->userauth_pswd_newpw);
1084
0
    }
1085
3.42k
    if(session->userauth_host_packet) {
1086
0
        LIBSSH2_FREE(session, session->userauth_host_packet);
1087
0
    }
1088
3.42k
    if(session->userauth_host_method) {
1089
0
        LIBSSH2_FREE(session, session->userauth_host_method);
1090
0
    }
1091
3.42k
    if(session->userauth_host_data) {
1092
0
        LIBSSH2_FREE(session, session->userauth_host_data);
1093
0
    }
1094
3.42k
    if(session->userauth_pblc_data) {
1095
0
        LIBSSH2_FREE(session, session->userauth_pblc_data);
1096
0
    }
1097
3.42k
    if(session->userauth_pblc_packet) {
1098
0
        LIBSSH2_FREE(session, session->userauth_pblc_packet);
1099
0
    }
1100
3.42k
    if(session->userauth_pblc_method) {
1101
0
        LIBSSH2_FREE(session, session->userauth_pblc_method);
1102
0
    }
1103
3.42k
    if(session->userauth_kybd_data) {
1104
0
        LIBSSH2_FREE(session, session->userauth_kybd_data);
1105
0
    }
1106
3.42k
    if(session->userauth_kybd_packet) {
1107
0
        LIBSSH2_FREE(session, session->userauth_kybd_packet);
1108
0
    }
1109
3.42k
    if(session->userauth_kybd_auth_instruction) {
1110
0
        LIBSSH2_FREE(session, session->userauth_kybd_auth_instruction);
1111
0
    }
1112
3.42k
    if(session->open_packet) {
1113
0
        LIBSSH2_FREE(session, session->open_packet);
1114
0
    }
1115
3.42k
    if(session->open_data) {
1116
0
        LIBSSH2_FREE(session, session->open_data);
1117
0
    }
1118
3.42k
    if(session->direct_message) {
1119
0
        LIBSSH2_FREE(session, session->direct_message);
1120
0
    }
1121
3.42k
    if(session->fwdLstn_packet) {
1122
0
        LIBSSH2_FREE(session, session->fwdLstn_packet);
1123
0
    }
1124
3.42k
    if(session->pkeyInit_data) {
1125
0
        LIBSSH2_FREE(session, session->pkeyInit_data);
1126
0
    }
1127
3.42k
    if(session->scpRecv_command) {
1128
0
        LIBSSH2_FREE(session, session->scpRecv_command);
1129
0
    }
1130
3.42k
    if(session->scpSend_command) {
1131
0
        LIBSSH2_FREE(session, session->scpSend_command);
1132
0
    }
1133
3.42k
    if(session->sftpInit_sftp) {
1134
0
        LIBSSH2_FREE(session, session->sftpInit_sftp);
1135
0
    }
1136
1137
    /* Free payload buffer */
1138
3.42k
    if(session->packet.total_num) {
1139
344
        LIBSSH2_FREE(session, session->packet.payload);
1140
344
    }
1141
1142
    /* Cleanup all remaining packets */
1143
    /* !checksrc! disable EQUALSNULL 1 */
1144
8.71k
    while((pkg = _libssh2_list_first(&session->packets)) != NULL) {
1145
5.28k
        packets_left++;
1146
5.28k
        _libssh2_debug((session, LIBSSH2_TRACE_TRANS,
1147
5.28k
                       "packet left with id %d", pkg->data[0]));
1148
        /* unlink the node */
1149
5.28k
        _libssh2_list_remove(&pkg->node);
1150
1151
        /* free */
1152
5.28k
        LIBSSH2_FREE(session, pkg->data);
1153
5.28k
        LIBSSH2_FREE(session, pkg);
1154
5.28k
    }
1155
3.42k
    (void)packets_left;
1156
3.42k
    _libssh2_debug((session, LIBSSH2_TRACE_TRANS,
1157
3.42k
                   "Extra packets left %d", packets_left));
1158
1159
3.42k
    if(session->socket_prev_blockstate) {
1160
        /* if the socket was previously blocking, put it back so */
1161
3.42k
        rc = session_nonblock(session->socket_fd, 0);
1162
3.42k
        if(rc) {
1163
0
            _libssh2_debug((session, LIBSSH2_TRACE_TRANS,
1164
0
                           "unable to reset socket's blocking state"));
1165
0
        }
1166
3.42k
    }
1167
1168
3.42k
    if(session->server_hostkey) {
1169
860
        LIBSSH2_FREE(session, session->server_hostkey);
1170
860
    }
1171
1172
    /* error string */
1173
3.42k
    if(session->err_msg &&
1174
3.42k
       ((session->err_flags & LIBSSH2_ERR_FLAG_DUP) != 0)) {
1175
0
        LIBSSH2_FREE(session, (char *)LIBSSH2_UNCONST(session->err_msg));
1176
0
    }
1177
1178
3.42k
    LIBSSH2_FREE(session, session);
1179
1180
3.42k
    return 0;
1181
3.42k
}
1182
1183
/*
1184
 * libssh2_session_free
1185
 *
1186
 * Frees the memory allocated to the session
1187
 * Also closes and frees any channels attached to this session
1188
 */
1189
LIBSSH2_API int
1190
libssh2_session_free(LIBSSH2_SESSION * session)
1191
3.42k
{
1192
3.42k
    int rc;
1193
1194
3.42k
    BLOCK_ADJUST(rc, session, session_free(session));
1195
1196
3.42k
    return rc;
1197
3.42k
}
1198
1199
/*
1200
 * session_disconnect
1201
 */
1202
static int
1203
session_disconnect(LIBSSH2_SESSION *session, int reason,
1204
                   const char *description,
1205
                   const char *lang)
1206
628
{
1207
628
    unsigned char *s;
1208
628
    size_t descr_len = 0, lang_len = 0;
1209
628
    int rc;
1210
1211
628
    if(session->disconnect_state == libssh2_NB_state_idle) {
1212
628
        _libssh2_debug((session, LIBSSH2_TRACE_TRANS,
1213
628
                       "Disconnecting: reason=%d, desc=%s, lang=%s", reason,
1214
628
                       description, lang));
1215
628
        if(description)
1216
628
            descr_len = strlen(description);
1217
1218
628
        if(lang)
1219
628
            lang_len = strlen(lang);
1220
1221
628
        if(descr_len > 256)
1222
0
            return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
1223
0
                                  "too long description");
1224
1225
628
        if(lang_len > 256)
1226
0
            return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
1227
0
                                  "too long language string");
1228
1229
        /* 13 = packet_type(1) + reason code(4) + descr_len(4) + lang_len(4) */
1230
628
        session->disconnect_data_len = descr_len + lang_len + 13;
1231
1232
628
        s = session->disconnect_data;
1233
1234
628
        *(s++) = SSH_MSG_DISCONNECT;
1235
628
        _libssh2_store_u32(&s, reason);
1236
628
        _libssh2_store_str(&s, description, descr_len);
1237
        /* store length only, lang is sent separately */
1238
628
        _libssh2_store_u32(&s, (uint32_t)lang_len);
1239
1240
628
        session->disconnect_state = libssh2_NB_state_created;
1241
628
    }
1242
1243
628
    rc = _libssh2_transport_send(session, session->disconnect_data,
1244
628
                                 session->disconnect_data_len,
1245
628
                                 (const unsigned char *)lang, lang_len);
1246
628
    if(rc == LIBSSH2_ERROR_EAGAIN)
1247
0
        return rc;
1248
1249
628
    session->disconnect_state = libssh2_NB_state_idle;
1250
1251
628
    return 0;
1252
628
}
1253
1254
/*
1255
 * libssh2_session_disconnect_ex
1256
 */
1257
LIBSSH2_API int
1258
libssh2_session_disconnect_ex(LIBSSH2_SESSION *session, int reason,
1259
                              const char *desc, const char *lang)
1260
628
{
1261
628
    int rc;
1262
628
    session->state &= ~LIBSSH2_STATE_INITIAL_KEX;
1263
628
    session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
1264
628
    BLOCK_ADJUST(rc, session,
1265
628
                 session_disconnect(session, reason, desc, lang));
1266
1267
628
    return rc;
1268
628
}
1269
1270
/* libssh2_session_methods
1271
 *
1272
 * Return the currently active methods for method_type
1273
 *
1274
 * NOTE: Currently lang_cs and lang_sc are ALWAYS set to empty string
1275
 * regardless of actual negotiation Strings should NOT be freed
1276
 */
1277
LIBSSH2_API const char *
1278
libssh2_session_methods(LIBSSH2_SESSION * session, int method_type)
1279
0
{
1280
    /* All methods have char *name as their first element */
1281
0
    const LIBSSH2_KEX_METHOD *method = NULL;
1282
1283
0
    switch(method_type) {
1284
0
    case LIBSSH2_METHOD_KEX:
1285
0
        method = session->kex;
1286
0
        break;
1287
1288
0
    case LIBSSH2_METHOD_HOSTKEY:
1289
0
        method = (const LIBSSH2_KEX_METHOD *) session->hostkey;
1290
0
        break;
1291
1292
0
    case LIBSSH2_METHOD_CRYPT_CS:
1293
0
        method = (const LIBSSH2_KEX_METHOD *) session->local.crypt;
1294
0
        break;
1295
1296
0
    case LIBSSH2_METHOD_CRYPT_SC:
1297
0
        method = (const LIBSSH2_KEX_METHOD *) session->remote.crypt;
1298
0
        break;
1299
1300
0
    case LIBSSH2_METHOD_MAC_CS:
1301
0
        method = (const LIBSSH2_KEX_METHOD *) session->local.mac;
1302
0
        break;
1303
1304
0
    case LIBSSH2_METHOD_MAC_SC:
1305
0
        method = (const LIBSSH2_KEX_METHOD *) session->remote.mac;
1306
0
        break;
1307
1308
0
    case LIBSSH2_METHOD_COMP_CS:
1309
0
        method = (const LIBSSH2_KEX_METHOD *) session->local.comp;
1310
0
        break;
1311
1312
0
    case LIBSSH2_METHOD_COMP_SC:
1313
0
        method = (const LIBSSH2_KEX_METHOD *) session->remote.comp;
1314
0
        break;
1315
1316
0
    case LIBSSH2_METHOD_LANG_CS:
1317
0
        return "";
1318
1319
0
    case LIBSSH2_METHOD_LANG_SC:
1320
0
        return "";
1321
1322
0
    default:
1323
0
        _libssh2_error(session, LIBSSH2_ERROR_INVAL,
1324
0
                       "Invalid parameter specified for method_type");
1325
0
        return NULL;
1326
0
    }
1327
1328
0
    if(!method) {
1329
0
        _libssh2_error(session, LIBSSH2_ERROR_METHOD_NONE,
1330
0
                       "No method negotiated");
1331
0
        return NULL;
1332
0
    }
1333
1334
0
    return method->name;
1335
0
}
1336
1337
/* libssh2_session_abstract
1338
 * Retrieve a pointer to the abstract property
1339
 */
1340
LIBSSH2_API void **
1341
libssh2_session_abstract(LIBSSH2_SESSION * session)
1342
0
{
1343
0
    return &session->abstract;
1344
0
}
1345
1346
/* libssh2_session_last_error
1347
 *
1348
 * Returns error code and populates an error string into errmsg If want_buf is
1349
 * non-zero then the string placed into errmsg must be freed by the calling
1350
 * program. Otherwise it is assumed to be owned by libssh2
1351
 */
1352
LIBSSH2_API int
1353
libssh2_session_last_error(LIBSSH2_SESSION * session, char **errmsg,
1354
                           int *errmsg_len, int want_buf)
1355
0
{
1356
0
    size_t msglen = 0;
1357
1358
    /* No error to report */
1359
0
    if(!session->err_code) {
1360
0
        if(errmsg) {
1361
0
            if(want_buf) {
1362
0
                *errmsg = LIBSSH2_ALLOC(session, 1);
1363
0
                if(*errmsg) {
1364
0
                    **errmsg = 0;
1365
0
                }
1366
0
            }
1367
0
            else {
1368
0
                *errmsg = (char *)LIBSSH2_UNCONST("");
1369
0
            }
1370
0
        }
1371
0
        if(errmsg_len) {
1372
0
            *errmsg_len = 0;
1373
0
        }
1374
0
        return 0;
1375
0
    }
1376
1377
0
    if(errmsg) {
1378
0
        const char *error = session->err_msg ? session->err_msg : "";
1379
1380
0
        msglen = strlen(error);
1381
1382
0
        if(want_buf) {
1383
            /* Make a copy so the calling program can own it */
1384
0
            *errmsg = LIBSSH2_ALLOC(session, msglen + 1);
1385
0
            if(*errmsg) {
1386
0
                memcpy(*errmsg, error, msglen);
1387
0
                (*errmsg)[msglen] = 0;
1388
0
            }
1389
0
        }
1390
0
        else
1391
0
            *errmsg = (char *)LIBSSH2_UNCONST(error);
1392
0
    }
1393
1394
0
    if(errmsg_len) {
1395
0
        *errmsg_len = (int)msglen;
1396
0
    }
1397
1398
0
    return session->err_code;
1399
0
}
1400
1401
/* libssh2_session_last_errno
1402
 *
1403
 * Returns error code
1404
 */
1405
LIBSSH2_API int
1406
libssh2_session_last_errno(LIBSSH2_SESSION * session)
1407
0
{
1408
0
    return session->err_code;
1409
0
}
1410
1411
/* libssh2_session_set_last_error
1412
 *
1413
 * Sets the internal error code for the session.
1414
 *
1415
 * This function is available specifically to be used by high level
1416
 * language wrappers (i.e. Python or Perl) that may extend the library
1417
 * features while still relying on its error reporting mechanism.
1418
 */
1419
LIBSSH2_API int
1420
libssh2_session_set_last_error(LIBSSH2_SESSION* session,
1421
                               int errcode,
1422
                               const char *errmsg)
1423
0
{
1424
0
    return _libssh2_error_flags(session, errcode, errmsg,
1425
0
                                LIBSSH2_ERR_FLAG_DUP);
1426
0
}
1427
1428
/* libssh2_session_flag
1429
 *
1430
 * Set/Get session flags
1431
 *
1432
 * Return error code.
1433
 */
1434
LIBSSH2_API int
1435
libssh2_session_flag(LIBSSH2_SESSION * session, int flag, int value)
1436
0
{
1437
0
    switch(flag) {
1438
0
    case LIBSSH2_FLAG_SIGPIPE:
1439
0
        session->flag.sigpipe = value;
1440
0
        break;
1441
0
    case LIBSSH2_FLAG_COMPRESS:
1442
0
        session->flag.compress = value;
1443
0
        break;
1444
0
    case LIBSSH2_FLAG_QUOTE_PATHS:
1445
0
        session->flag.quote_paths = value;
1446
0
        break;
1447
0
    default:
1448
        /* unknown flag */
1449
0
        return LIBSSH2_ERROR_INVAL;
1450
0
    }
1451
1452
0
    return LIBSSH2_ERROR_NONE;
1453
0
}
1454
1455
/* _libssh2_session_set_blocking
1456
 *
1457
 * Set a session's blocking mode on or off, return the previous status when
1458
 * this function is called. Note this function does not alter the state of the
1459
 * actual socket involved.
1460
 */
1461
int
1462
_libssh2_session_set_blocking(LIBSSH2_SESSION *session, int blocking)
1463
3.42k
{
1464
3.42k
    int bl = session->api_block_mode;
1465
3.42k
    _libssh2_debug((session, LIBSSH2_TRACE_CONN,
1466
3.42k
                   "Setting blocking mode %s", blocking ? "ON" : "OFF"));
1467
3.42k
    session->api_block_mode = blocking;
1468
1469
3.42k
    return bl;
1470
3.42k
}
1471
1472
/* libssh2_session_set_blocking
1473
 *
1474
 * Set a channel's blocking mode on or off, similar to a socket's
1475
 * fcntl(fd, F_SETFL, O_NONBLOCK); type command
1476
 */
1477
LIBSSH2_API void
1478
libssh2_session_set_blocking(LIBSSH2_SESSION * session, int blocking)
1479
3.42k
{
1480
3.42k
    (void)_libssh2_session_set_blocking(session, blocking);
1481
3.42k
}
1482
1483
/* libssh2_session_get_blocking
1484
 *
1485
 * Returns a session's blocking mode on or off
1486
 */
1487
LIBSSH2_API int
1488
libssh2_session_get_blocking(LIBSSH2_SESSION * session)
1489
0
{
1490
0
    return session->api_block_mode;
1491
0
}
1492
1493
1494
/* libssh2_session_set_timeout
1495
 *
1496
 * Set a session's timeout (in msec) for blocking mode,
1497
 * or 0 to disable timeouts.
1498
 */
1499
LIBSSH2_API void
1500
libssh2_session_set_timeout(LIBSSH2_SESSION * session, long timeout)
1501
0
{
1502
0
    session->api_timeout = timeout;
1503
0
}
1504
1505
/* libssh2_session_get_timeout
1506
 *
1507
 * Returns a session's timeout, or 0 if disabled
1508
 */
1509
LIBSSH2_API long
1510
libssh2_session_get_timeout(LIBSSH2_SESSION * session)
1511
0
{
1512
0
    return session->api_timeout;
1513
0
}
1514
1515
/* libssh2_session_set_read_timeout
1516
 *
1517
 * Set a session's timeout (in sec) when reading packets,
1518
 * or 0 to use default of 60 seconds.
1519
 */
1520
LIBSSH2_API void
1521
libssh2_session_set_read_timeout(LIBSSH2_SESSION * session, long timeout)
1522
0
{
1523
0
    if(timeout <= 0) {
1524
0
        timeout = LIBSSH2_DEFAULT_READ_TIMEOUT;
1525
0
    }
1526
0
    session->packet_read_timeout = timeout;
1527
0
}
1528
1529
/* libssh2_session_get_read_timeout
1530
 *
1531
 * Returns a session's timeout. Default is 60 seconds.
1532
 */
1533
LIBSSH2_API long
1534
libssh2_session_get_read_timeout(LIBSSH2_SESSION * session)
1535
0
{
1536
0
    return session->packet_read_timeout;
1537
0
}
1538
1539
/*
1540
 * libssh2_poll_channel_read
1541
 *
1542
 * Returns 0 if no data is waiting on channel,
1543
 * non-0 if data is available
1544
 */
1545
LIBSSH2_API int
1546
libssh2_poll_channel_read(LIBSSH2_CHANNEL *channel, int extended)
1547
0
{
1548
0
    LIBSSH2_SESSION *session;
1549
0
    LIBSSH2_PACKET *packet;
1550
1551
0
    if(!channel)
1552
0
        return LIBSSH2_ERROR_BAD_USE;
1553
1554
0
    session = channel->session;
1555
0
    packet = _libssh2_list_first(&session->packets);
1556
1557
0
    while(packet) {
1558
0
        if(packet->data_len < 5) {
1559
0
            return _libssh2_error(session, LIBSSH2_ERROR_BUFFER_TOO_SMALL,
1560
0
                                  "Packet too small");
1561
0
        }
1562
1563
0
        if(channel->local.id == _libssh2_ntohu32(packet->data + 1)) {
1564
0
            if(extended == 1 &&
1565
0
                (packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA
1566
0
                 || packet->data[0] == SSH_MSG_CHANNEL_DATA)) {
1567
0
                return 1;
1568
0
            }
1569
0
            else if(extended == 0 &&
1570
0
                    packet->data[0] == SSH_MSG_CHANNEL_DATA) {
1571
0
                return 1;
1572
0
            }
1573
            /* else - no data of any type is ready to be read */
1574
0
        }
1575
0
        packet = _libssh2_list_next(&packet->node);
1576
0
    }
1577
1578
0
    return 0;
1579
0
}
1580
1581
/*
1582
 * poll_channel_write
1583
 *
1584
 * Returns 0 if writing to channel would block,
1585
 * non-0 if data can be written without blocking
1586
 */
1587
static inline int
1588
poll_channel_write(LIBSSH2_CHANNEL * channel)
1589
0
{
1590
0
    return channel->local.window_size ? 1 : 0;
1591
0
}
1592
1593
/* poll_listener_queued
1594
 *
1595
 * Returns 0 if no connections are waiting to be accepted
1596
 * non-0 if one or more connections are available
1597
 */
1598
static inline int
1599
poll_listener_queued(LIBSSH2_LISTENER * listener)
1600
0
{
1601
0
    return _libssh2_list_first(&listener->queue) ? 1 : 0;
1602
0
}
1603
1604
/*
1605
 * libssh2_poll
1606
 *
1607
 * Poll sockets, channels, and listeners for activity
1608
 */
1609
LIBSSH2_API int
1610
libssh2_poll(LIBSSH2_POLLFD * fds, unsigned int nfds, long timeout)
1611
0
{
1612
0
    long timeout_remaining;
1613
0
    unsigned int i, active_fds;
1614
0
#ifdef HAVE_POLL
1615
0
    LIBSSH2_SESSION *session = NULL;
1616
0
#ifdef HAVE_ALLOCA
1617
0
    struct pollfd *sockets = alloca(sizeof(struct pollfd) * nfds);
1618
#else
1619
    struct pollfd sockets[256];
1620
1621
    if(nfds > 256)
1622
        /* systems without alloca use a fixed-size array, this can be fixed if
1623
           we really want to, at least if the compiler is a C99 capable one */
1624
        return -1;
1625
#endif
1626
    /* Setup sockets for polling */
1627
0
    for(i = 0; i < nfds; i++) {
1628
0
        fds[i].revents = 0;
1629
0
        switch(fds[i].type) {
1630
0
        case LIBSSH2_POLLFD_SOCKET:
1631
0
            sockets[i].fd = fds[i].fd.socket;
1632
0
            sockets[i].events = (short)fds[i].events;
1633
0
            sockets[i].revents = 0;
1634
0
            break;
1635
1636
0
        case LIBSSH2_POLLFD_CHANNEL:
1637
0
            sockets[i].fd = fds[i].fd.channel->session->socket_fd;
1638
0
            sockets[i].events = POLLIN;
1639
0
            sockets[i].revents = 0;
1640
0
            if(!session)
1641
0
                session = fds[i].fd.channel->session;
1642
0
            break;
1643
1644
0
        case LIBSSH2_POLLFD_LISTENER:
1645
0
            sockets[i].fd = fds[i].fd.listener->session->socket_fd;
1646
0
            sockets[i].events = POLLIN;
1647
0
            sockets[i].revents = 0;
1648
0
            if(!session)
1649
0
                session = fds[i].fd.listener->session;
1650
0
            break;
1651
1652
0
        default:
1653
0
            if(session)
1654
0
                _libssh2_error(session, LIBSSH2_ERROR_INVALID_POLL_TYPE,
1655
0
                               "Invalid descriptor passed to libssh2_poll()");
1656
0
            return -1;
1657
0
        }
1658
0
    }
1659
#elif defined(HAVE_SELECT)
1660
    LIBSSH2_SESSION *session = NULL;
1661
    libssh2_socket_t maxfd = 0;
1662
    fd_set rfds, wfds;
1663
    struct timeval tv;
1664
1665
    FD_ZERO(&rfds);
1666
    FD_ZERO(&wfds);
1667
    for(i = 0; i < nfds; i++) {
1668
        fds[i].revents = 0;
1669
        switch(fds[i].type) {
1670
        case LIBSSH2_POLLFD_SOCKET:
1671
            if(fds[i].events & LIBSSH2_POLLFD_POLLIN) {
1672
#if defined(__GNUC__) || defined(__clang__)
1673
#pragma GCC diagnostic push
1674
#pragma GCC diagnostic ignored "-Wsign-conversion"
1675
#endif
1676
                FD_SET(fds[i].fd.socket, &rfds);
1677
#if defined(__GNUC__) || defined(__clang__)
1678
#pragma GCC diagnostic pop
1679
#endif
1680
                if(fds[i].fd.socket > maxfd)
1681
                    maxfd = fds[i].fd.socket;
1682
            }
1683
            if(fds[i].events & LIBSSH2_POLLFD_POLLOUT) {
1684
#if defined(__GNUC__) || defined(__clang__)
1685
#pragma GCC diagnostic push
1686
#pragma GCC diagnostic ignored "-Wsign-conversion"
1687
#endif
1688
                FD_SET(fds[i].fd.socket, &wfds);
1689
#if defined(__GNUC__) || defined(__clang__)
1690
#pragma GCC diagnostic pop
1691
#endif
1692
                if(fds[i].fd.socket > maxfd)
1693
                    maxfd = fds[i].fd.socket;
1694
            }
1695
            break;
1696
1697
        case LIBSSH2_POLLFD_CHANNEL:
1698
#if defined(__GNUC__) || defined(__clang__)
1699
#pragma GCC diagnostic push
1700
#pragma GCC diagnostic ignored "-Wsign-conversion"
1701
#endif
1702
            FD_SET(fds[i].fd.channel->session->socket_fd, &rfds);
1703
#if defined(__GNUC__) || defined(__clang__)
1704
#pragma GCC diagnostic pop
1705
#endif
1706
            if(fds[i].fd.channel->session->socket_fd > maxfd)
1707
                maxfd = fds[i].fd.channel->session->socket_fd;
1708
            if(!session)
1709
                session = fds[i].fd.channel->session;
1710
            break;
1711
1712
        case LIBSSH2_POLLFD_LISTENER:
1713
#if defined(__GNUC__) || defined(__clang__)
1714
#pragma GCC diagnostic push
1715
#pragma GCC diagnostic ignored "-Wsign-conversion"
1716
#endif
1717
            FD_SET(fds[i].fd.listener->session->socket_fd, &rfds);
1718
#if defined(__GNUC__) || defined(__clang__)
1719
#pragma GCC diagnostic pop
1720
#endif
1721
            if(fds[i].fd.listener->session->socket_fd > maxfd)
1722
                maxfd = fds[i].fd.listener->session->socket_fd;
1723
            if(!session)
1724
                session = fds[i].fd.listener->session;
1725
            break;
1726
1727
        default:
1728
            if(session)
1729
                _libssh2_error(session, LIBSSH2_ERROR_INVALID_POLL_TYPE,
1730
                               "Invalid descriptor passed to libssh2_poll()");
1731
            return -1;
1732
        }
1733
    }
1734
#else
1735
    /* No select() or poll()
1736
     * no sockets structure to setup
1737
     */
1738
1739
    timeout = 0;
1740
#endif /* HAVE_POLL or HAVE_SELECT */
1741
1742
0
    timeout_remaining = timeout;
1743
0
    do {
1744
0
#if defined(HAVE_POLL) || defined(HAVE_SELECT)
1745
0
        int sysret;
1746
0
#endif
1747
1748
0
        active_fds = 0;
1749
1750
0
        for(i = 0; i < nfds; i++) {
1751
0
            if(fds[i].events != fds[i].revents) {
1752
0
                switch(fds[i].type) {
1753
0
                case LIBSSH2_POLLFD_CHANNEL:
1754
0
                    if((fds[i].events & LIBSSH2_POLLFD_POLLIN) &&
1755
                        /* Want to be ready for read */
1756
0
                        ((fds[i].revents & LIBSSH2_POLLFD_POLLIN) == 0)) {
1757
                        /* Not yet known to be ready for read */
1758
0
                        fds[i].revents |=
1759
0
                            libssh2_poll_channel_read(fds[i].fd.channel,
1760
0
                                                      0) ?
1761
0
                            LIBSSH2_POLLFD_POLLIN : 0;
1762
0
                    }
1763
0
                    if((fds[i].events & LIBSSH2_POLLFD_POLLEXT) &&
1764
                        /* Want to be ready for extended read */
1765
0
                        ((fds[i].revents & LIBSSH2_POLLFD_POLLEXT) == 0)) {
1766
                        /* Not yet known to be ready for extended read */
1767
0
                        fds[i].revents |=
1768
0
                            libssh2_poll_channel_read(fds[i].fd.channel,
1769
0
                                                      1) ?
1770
0
                            LIBSSH2_POLLFD_POLLEXT : 0;
1771
0
                    }
1772
0
                    if((fds[i].events & LIBSSH2_POLLFD_POLLOUT) &&
1773
                        /* Want to be ready for write */
1774
0
                        ((fds[i].revents & LIBSSH2_POLLFD_POLLOUT) == 0)) {
1775
                        /* Not yet known to be ready for write */
1776
0
                        fds[i].revents |=
1777
0
                            poll_channel_write(fds[i].fd. channel) ?
1778
0
                            LIBSSH2_POLLFD_POLLOUT : 0;
1779
0
                    }
1780
0
                    if(fds[i].fd.channel->remote.close
1781
0
                        || fds[i].fd.channel->local.close) {
1782
0
                        fds[i].revents |= LIBSSH2_POLLFD_CHANNEL_CLOSED;
1783
0
                    }
1784
0
                    if(fds[i].fd.channel->session->socket_state ==
1785
0
                        LIBSSH2_SOCKET_DISCONNECTED) {
1786
0
                        fds[i].revents |=
1787
0
                            LIBSSH2_POLLFD_CHANNEL_CLOSED |
1788
0
                            LIBSSH2_POLLFD_SESSION_CLOSED;
1789
0
                    }
1790
0
                    break;
1791
1792
0
                case LIBSSH2_POLLFD_LISTENER:
1793
0
                    if((fds[i].events & LIBSSH2_POLLFD_POLLIN) &&
1794
                        /* Want a connection */
1795
0
                        ((fds[i].revents & LIBSSH2_POLLFD_POLLIN) == 0)) {
1796
                        /* No connections known of yet */
1797
0
                        fds[i].revents |=
1798
0
                            poll_listener_queued(fds[i].fd. listener) ?
1799
0
                            LIBSSH2_POLLFD_POLLIN : 0;
1800
0
                    }
1801
0
                    if(fds[i].fd.listener->session->socket_state ==
1802
0
                        LIBSSH2_SOCKET_DISCONNECTED) {
1803
0
                        fds[i].revents |=
1804
0
                            LIBSSH2_POLLFD_LISTENER_CLOSED |
1805
0
                            LIBSSH2_POLLFD_SESSION_CLOSED;
1806
0
                    }
1807
0
                    break;
1808
0
                }
1809
0
            }
1810
0
            if(fds[i].revents) {
1811
0
                active_fds++;
1812
0
            }
1813
0
        }
1814
1815
0
        if(active_fds) {
1816
            /* Don't block on the sockets if we have channels/listeners which
1817
               are ready */
1818
0
            timeout_remaining = 0;
1819
0
        }
1820
0
#ifdef HAVE_POLL
1821
1822
0
        {
1823
0
            struct timeval tv_begin, tv_end;
1824
1825
0
            gettimeofday(&tv_begin, NULL);
1826
0
            sysret = poll(sockets, nfds, (int)timeout_remaining);
1827
0
            gettimeofday(&tv_end, NULL);
1828
0
            timeout_remaining -= (tv_end.tv_sec - tv_begin.tv_sec) * 1000;
1829
0
            timeout_remaining -= (tv_end.tv_usec - tv_begin.tv_usec) / 1000;
1830
0
        }
1831
1832
0
        if(sysret > 0) {
1833
0
            for(i = 0; i < nfds; i++) {
1834
0
                switch(fds[i].type) {
1835
0
                case LIBSSH2_POLLFD_SOCKET:
1836
0
                    fds[i].revents = sockets[i].revents;
1837
0
                    sockets[i].revents = 0; /* In case we loop again, be
1838
                                               nice */
1839
0
                    if(fds[i].revents) {
1840
0
                        active_fds++;
1841
0
                    }
1842
0
                    break;
1843
0
                case LIBSSH2_POLLFD_CHANNEL:
1844
0
                    if(sockets[i].events & POLLIN) {
1845
                        /* Spin session until no data available */
1846
0
                        while(_libssh2_transport_read(fds[i].fd.
1847
0
                                                      channel->session)
1848
0
                              > 0);
1849
0
                    }
1850
0
                    if(sockets[i].revents & POLLHUP) {
1851
0
                        fds[i].revents |=
1852
0
                            LIBSSH2_POLLFD_CHANNEL_CLOSED |
1853
0
                            LIBSSH2_POLLFD_SESSION_CLOSED;
1854
0
                    }
1855
0
                    sockets[i].revents = 0;
1856
0
                    break;
1857
0
                case LIBSSH2_POLLFD_LISTENER:
1858
0
                    if(sockets[i].events & POLLIN) {
1859
                        /* Spin session until no data available */
1860
0
                        while(_libssh2_transport_read(fds[i].fd.
1861
0
                                                      listener->session)
1862
0
                              > 0);
1863
0
                    }
1864
0
                    if(sockets[i].revents & POLLHUP) {
1865
0
                        fds[i].revents |=
1866
0
                            LIBSSH2_POLLFD_LISTENER_CLOSED |
1867
0
                            LIBSSH2_POLLFD_SESSION_CLOSED;
1868
0
                    }
1869
0
                    sockets[i].revents = 0;
1870
0
                    break;
1871
0
                }
1872
0
            }
1873
0
        }
1874
#elif defined(HAVE_SELECT)
1875
        tv.tv_sec = timeout_remaining / 1000;
1876
#ifdef libssh2_usec_t
1877
        tv.tv_usec = (libssh2_usec_t)((timeout_remaining % 1000) * 1000);
1878
#else
1879
        tv.tv_usec = (timeout_remaining % 1000) * 1000;
1880
#endif
1881
1882
        {
1883
            struct timeval tv_begin, tv_end;
1884
1885
            gettimeofday(&tv_begin, NULL);
1886
            sysret = select((int)(maxfd + 1), &rfds, &wfds, NULL, &tv);
1887
            gettimeofday(&tv_end, NULL);
1888
1889
            timeout_remaining -= (tv_end.tv_sec - tv_begin.tv_sec) * 1000;
1890
            timeout_remaining -= (tv_end.tv_usec - tv_begin.tv_usec) / 1000;
1891
        }
1892
1893
        if(sysret > 0) {
1894
            for(i = 0; i < nfds; i++) {
1895
                switch(fds[i].type) {
1896
                case LIBSSH2_POLLFD_SOCKET:
1897
#if defined(__GNUC__) || defined(__clang__)
1898
#pragma GCC diagnostic push
1899
#pragma GCC diagnostic ignored "-Wsign-conversion"
1900
#endif
1901
                    if(FD_ISSET(fds[i].fd.socket, &rfds)) {
1902
                        fds[i].revents |= LIBSSH2_POLLFD_POLLIN;
1903
                    }
1904
                    if(FD_ISSET(fds[i].fd.socket, &wfds)) {
1905
                        fds[i].revents |= LIBSSH2_POLLFD_POLLOUT;
1906
                    }
1907
                    if(fds[i].revents) {
1908
                        active_fds++;
1909
                    }
1910
#if defined(__GNUC__) || defined(__clang__)
1911
#pragma GCC diagnostic pop
1912
#endif
1913
                    break;
1914
1915
                case LIBSSH2_POLLFD_CHANNEL:
1916
                    if(FD_ISSET(fds[i].fd.channel->session->socket_fd,
1917
                                &rfds)) {
1918
                        /* Spin session until no data available */
1919
                        while(_libssh2_transport_read(fds[i].fd.
1920
                                                      channel->session)
1921
                              > 0);
1922
                    }
1923
                    break;
1924
1925
                case LIBSSH2_POLLFD_LISTENER:
1926
                    if(FD_ISSET
1927
                        (fds[i].fd.listener->session->socket_fd, &rfds)) {
1928
                        /* Spin session until no data available */
1929
                        while(_libssh2_transport_read(fds[i].fd.
1930
                                                      listener->session)
1931
                              > 0);
1932
                    }
1933
                    break;
1934
                }
1935
            }
1936
        }
1937
#endif /* else no select() or poll() -- timeout (and by extension
1938
        * timeout_remaining) will be equal to 0 */
1939
0
    } while((timeout_remaining > 0) && !active_fds);
1940
1941
0
    return active_fds;
1942
0
}
1943
1944
/*
1945
 * libssh2_session_block_directions
1946
 *
1947
 * Get blocked direction when a function returns LIBSSH2_ERROR_EAGAIN
1948
 * Returns LIBSSH2_SOCKET_BLOCK_INBOUND if recv() blocked
1949
 * or LIBSSH2_SOCKET_BLOCK_OUTBOUND if send() blocked
1950
 */
1951
LIBSSH2_API int
1952
libssh2_session_block_directions(LIBSSH2_SESSION *session)
1953
28
{
1954
28
    return session->socket_block_directions;
1955
28
}
1956
1957
/* libssh2_session_banner_get
1958
 * Get the remote banner (server ID string)
1959
 */
1960
1961
LIBSSH2_API const char *
1962
libssh2_session_banner_get(LIBSSH2_SESSION *session)
1963
0
{
1964
    /* to avoid a coredump when session is NULL */
1965
0
    if(!session)
1966
0
        return NULL;
1967
1968
0
    if(!session->remote.banner)
1969
0
        return NULL;
1970
1971
0
    return (const char *) session->remote.banner;
1972
0
}