libssh2

Форк
0
/
misc.c 
971 строка · 25.0 Кб
1
/* Copyright (C) Sara Golemon <sarag@libssh2.org>
2
 * Copyright (C) Daniel Stenberg
3
 * Copyright (C) Simon Josefsson
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 HAVE_UNISTD_H
45
#include <unistd.h>
46
#endif
47

48
#include <errno.h>
49
#include <assert.h>
50

51
#ifdef _WIN32
52
/* Force parameter type. */
53
#define recv(s, b, l, f)  recv((s), (b), (int)(l), (f))
54
#define send(s, b, l, f)  send((s), (b), (int)(l), (f))
55
#endif
56

57
/* snprintf not in Visual Studio CRT and _snprintf dangerously incompatible.
58
   We provide a safe wrapper if snprintf not found */
59
#ifdef LIBSSH2_SNPRINTF
60
#include <stdarg.h>
61

62
/* Want safe, 'n += snprintf(b + n ...)' like function. If cp_max_len is 1
63
* then assume cp is pointing to a null char and do nothing. Returns number
64
* number of chars placed in cp excluding the trailing null char. So for
65
* cp_max_len > 0 the return value is always < cp_max_len; for cp_max_len
66
* <= 0 the return value is 0 (and no chars are written to cp). */
67
int _libssh2_snprintf(char *cp, size_t cp_max_len, const char *fmt, ...)
68
{
69
    va_list args;
70
    int n;
71

72
    if(cp_max_len < 2)
73
        return 0;
74
    va_start(args, fmt);
75
    n = vsnprintf(cp, cp_max_len, fmt, args);
76
    va_end(args);
77
    return (n < (int)cp_max_len) ? n : (int)(cp_max_len - 1);
78
}
79
#endif
80

81
int _libssh2_error_flags(LIBSSH2_SESSION* session, int errcode,
82
                         const char *errmsg, int errflags)
83
{
84
    if(!session) {
85
        if(errmsg)
86
            fprintf(stderr, "Session is NULL, error: %s\n", errmsg);
87
        return errcode;
88
    }
89

90
    if(session->err_flags & LIBSSH2_ERR_FLAG_DUP)
91
        LIBSSH2_FREE(session, (char *)session->err_msg);
92

93
    session->err_code = errcode;
94
    session->err_flags = 0;
95

96
    if(errmsg && ((errflags & LIBSSH2_ERR_FLAG_DUP) != 0)) {
97
        size_t len = strlen(errmsg);
98
        char *copy = LIBSSH2_ALLOC(session, len + 1);
99
        if(copy) {
100
            memcpy(copy, errmsg, len + 1);
101
            session->err_flags = LIBSSH2_ERR_FLAG_DUP;
102
            session->err_msg = copy;
103
        }
104
        else
105
            /* Out of memory: this code path is very unlikely */
106
            session->err_msg = "former error forgotten (OOM)";
107
    }
108
    else
109
        session->err_msg = errmsg;
110

111
#ifdef LIBSSH2DEBUG
112
    if((errcode == LIBSSH2_ERROR_EAGAIN) && !session->api_block_mode)
113
        /* if this is EAGAIN and we're in non-blocking mode, don't generate
114
           a debug output for this */
115
        return errcode;
116
    _libssh2_debug((session, LIBSSH2_TRACE_ERROR, "%d - %s", session->err_code,
117
                   session->err_msg));
118
#endif
119

120
    return errcode;
121
}
122

123
int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char *errmsg)
124
{
125
    return _libssh2_error_flags(session, errcode, errmsg, 0);
126
}
127

128
#ifdef _WIN32
129
int _libssh2_wsa2errno(void)
130
{
131
    switch(WSAGetLastError()) {
132
    case WSAEWOULDBLOCK:
133
        return EAGAIN;
134

135
    case WSAENOTSOCK:
136
        return EBADF;
137

138
    case WSAEINTR:
139
        return EINTR;
140

141
    default:
142
        /* It is most important to ensure errno does not stay at EAGAIN
143
         * when a different error occurs so just set errno to a generic
144
         * error */
145
        return EIO;
146
    }
147
}
148
#endif
149

150
/* _libssh2_recv
151
 *
152
 * Replacement for the standard recv, return -errno on failure.
153
 */
154
ssize_t
155
_libssh2_recv(libssh2_socket_t sock, void *buffer, size_t length,
156
              int flags, void **abstract)
157
{
158
    ssize_t rc;
159

160
    (void)abstract;
161

162
    rc = recv(sock, buffer, length, flags);
163
    if(rc < 0) {
164
        int err;
165
#ifdef _WIN32
166
        err = _libssh2_wsa2errno();
167
#else
168
        err = errno;
169
#endif
170
        /* Profiling tools that use SIGPROF can cause EINTR responses.
171
           recv() does not modify its arguments when it returns EINTR,
172
           but there may be data waiting, so the caller should try again */
173
        if(err == EINTR)
174
            return -EAGAIN;
175
        /* Sometimes the first recv() function call sets errno to ENOENT on
176
           Solaris and HP-UX */
177
        if(err == ENOENT)
178
            return -EAGAIN;
179
#ifdef EWOULDBLOCK /* For VMS and other special unixes */
180
        else if(err == EWOULDBLOCK)
181
            return -EAGAIN;
182
#endif
183
        else
184
            return -err;
185
    }
186
    return rc;
187
}
188

189
/* _libssh2_send
190
 *
191
 * Replacement for the standard send, return -errno on failure.
192
 */
193
ssize_t
194
_libssh2_send(libssh2_socket_t sock, const void *buffer, size_t length,
195
              int flags, void **abstract)
196
{
197
    ssize_t rc;
198

199
    (void)abstract;
200

201
    rc = send(sock, buffer, length, flags);
202
    if(rc < 0) {
203
        int err;
204
#ifdef _WIN32
205
        err = _libssh2_wsa2errno();
206
#else
207
        err = errno;
208
#endif
209
        /* Profiling tools that use SIGPROF can cause EINTR responses.
210
           send() is defined as not yet sending any data when it returns EINTR,
211
           so the caller should try again */
212
        if(err == EINTR)
213
            return -EAGAIN;
214
#ifdef EWOULDBLOCK /* For VMS and other special unixes */
215
        if(err == EWOULDBLOCK)
216
            return -EAGAIN;
217
#endif
218
        return -err;
219
    }
220
    return rc;
221
}
222

223
/* libssh2_ntohu32
224
 */
225
uint32_t
226
_libssh2_ntohu32(const unsigned char *buf)
227
{
228
    return ((uint32_t)buf[0] << 24)
229
         | ((uint32_t)buf[1] << 16)
230
         | ((uint32_t)buf[2] << 8)
231
         | ((uint32_t)buf[3]);
232
}
233

234

235
/* _libssh2_ntohu64
236
 */
237
libssh2_uint64_t
238
_libssh2_ntohu64(const unsigned char *buf)
239
{
240
    return ((libssh2_uint64_t)buf[0] << 56)
241
         | ((libssh2_uint64_t)buf[1] << 48)
242
         | ((libssh2_uint64_t)buf[2] << 40)
243
         | ((libssh2_uint64_t)buf[3] << 32)
244
         | ((libssh2_uint64_t)buf[4] << 24)
245
         | ((libssh2_uint64_t)buf[5] << 16)
246
         | ((libssh2_uint64_t)buf[6] <<  8)
247
         | ((libssh2_uint64_t)buf[7]);
248
}
249

250
/* _libssh2_htonu32
251
 */
252
void
253
_libssh2_htonu32(unsigned char *buf, uint32_t value)
254
{
255
    buf[0] = (unsigned char)((value >> 24) & 0xFF);
256
    buf[1] = (value >> 16) & 0xFF;
257
    buf[2] = (value >> 8) & 0xFF;
258
    buf[3] = value & 0xFF;
259
}
260

261
/* _libssh2_store_u32
262
 */
263
void _libssh2_store_u32(unsigned char **buf, uint32_t value)
264
{
265
    _libssh2_htonu32(*buf, value);
266
    *buf += sizeof(uint32_t);
267
}
268

269
/* _libssh2_store_str
270
 */
271
int _libssh2_store_str(unsigned char **buf, const char *str, size_t len)
272
{
273
    uint32_t len_stored = (uint32_t)len;
274

275
    _libssh2_store_u32(buf, len_stored);
276
    if(len_stored) {
277
        memcpy(*buf, str, len_stored);
278
        *buf += len_stored;
279
    }
280

281
    assert(len_stored == len);
282
    return len_stored == len;
283
}
284

285
/* _libssh2_store_bignum2_bytes
286
 */
287
int _libssh2_store_bignum2_bytes(unsigned char **buf,
288
                                 const unsigned char *bytes,
289
                                 size_t len)
290
{
291
    uint32_t len_stored;
292
    uint32_t extraByte;
293
    const unsigned char *p;
294

295
    for(p = bytes; len > 0 && *p == 0; --len, ++p) {}
296

297
    extraByte = (len > 0 && (p[0] & 0x80) != 0);
298
    len_stored = (uint32_t)len;
299
    if(extraByte && len_stored == 0xffffffff)
300
        len_stored--;
301
    _libssh2_store_u32(buf, len_stored + extraByte);
302

303
    if(extraByte) {
304
        *buf[0] = 0;
305
        *buf += 1;
306
    }
307

308
    if(len_stored) {
309
        memcpy(*buf, p, len_stored);
310
        *buf += len_stored;
311
    }
312

313
    assert(len_stored == len);
314
    return len_stored == len;
315
}
316

317
/* Base64 Conversion */
318

319
static const short base64_reverse_table[256] = {
320
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
321
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
322
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
323
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
324
    -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
325
    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
326
    -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
327
    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
328
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
329
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
330
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
331
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
332
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
333
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
334
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
335
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
336
};
337

338
/* libssh2_base64_decode
339
 *
340
 * Legacy public function. DEPRECATED.
341
 */
342
LIBSSH2_API int
343
libssh2_base64_decode(LIBSSH2_SESSION *session, char **data,
344
                      unsigned int *datalen, const char *src,
345
                      unsigned int src_len)
346
{
347
    int rc;
348
    size_t dlen;
349

350
    rc = _libssh2_base64_decode(session, data, &dlen, src, src_len);
351

352
    if(datalen)
353
        *datalen = (unsigned int)dlen;
354

355
    return rc;
356
}
357

358
/* _libssh2_base64_decode
359
 *
360
 * Decode a base64 chunk and store it into a newly alloc'd buffer
361
 */
362
int _libssh2_base64_decode(LIBSSH2_SESSION *session,
363
                           char **data, size_t *datalen,
364
                           const char *src, size_t src_len)
365
{
366
    unsigned char *d;
367
    const char *s;
368
    short v;
369
    ssize_t i = 0, len = 0;
370

371
    *data = LIBSSH2_ALLOC(session, ((src_len / 4) * 3) + 1);
372
    d = (unsigned char *) *data;
373
    if(!d) {
374
        return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
375
                              "Unable to allocate memory for base64 decoding");
376
    }
377

378
    for(s = src; s < (src + src_len); s++) {
379
        v = base64_reverse_table[(unsigned char)*s];
380
        if(v < 0)
381
            continue;
382
        switch(i % 4) {
383
        case 0:
384
            d[len] = (unsigned char)(v << 2);
385
            break;
386
        case 1:
387
            d[len++] |= (unsigned char)(v >> 4);
388
            d[len] = (unsigned char)(v << 4);
389
            break;
390
        case 2:
391
            d[len++] |= (unsigned char)(v >> 2);
392
            d[len] = (unsigned char)(v << 6);
393
            break;
394
        case 3:
395
            d[len++] |= (unsigned char)v;
396
            break;
397
        }
398
        i++;
399
    }
400
    if((i % 4) == 1) {
401
        /* Invalid -- We have a byte which belongs exclusively to a partial
402
           octet */
403
        LIBSSH2_FREE(session, *data);
404
        *data = NULL;
405
        return _libssh2_error(session, LIBSSH2_ERROR_INVAL, "Invalid base64");
406
    }
407

408
    *datalen = len;
409
    return 0;
410
}
411

412
/* ---- Base64 Encoding/Decoding Table --- */
413
static const char table64[]=
414
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
415

416
/*
417
 * _libssh2_base64_encode
418
 *
419
 * Returns the length of the newly created base64 string. The third argument
420
 * is a pointer to an allocated area holding the base64 data. If something
421
 * went wrong, 0 is returned.
422
 *
423
 */
424
size_t _libssh2_base64_encode(LIBSSH2_SESSION *session,
425
                              const char *inp, size_t insize, char **outptr)
426
{
427
    unsigned char ibuf[3];
428
    unsigned char obuf[4];
429
    int i;
430
    int inputparts;
431
    char *output;
432
    char *base64data;
433
    const char *indata = inp;
434

435
    *outptr = NULL; /* set to NULL in case of failure before we reach the
436
                       end */
437

438
    if(insize == 0)
439
        insize = strlen(indata);
440

441
    base64data = output = LIBSSH2_ALLOC(session, insize * 4 / 3 + 4);
442
    if(!output)
443
        return 0;
444

445
    while(insize > 0) {
446
        for(i = inputparts = 0; i < 3; i++) {
447
            if(insize > 0) {
448
                inputparts++;
449
                ibuf[i] = *indata;
450
                indata++;
451
                insize--;
452
            }
453
            else
454
                ibuf[i] = 0;
455
        }
456

457
        obuf[0] = (unsigned char)  ((ibuf[0] & 0xFC) >> 2);
458
        obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \
459
                                   ((ibuf[1] & 0xF0) >> 4));
460
        obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \
461
                                   ((ibuf[2] & 0xC0) >> 6));
462
        obuf[3] = (unsigned char)   (ibuf[2] & 0x3F);
463

464
        switch(inputparts) {
465
        case 1: /* only one byte read */
466
            output[0] = table64[obuf[0]];
467
            output[1] = table64[obuf[1]];
468
            output[2] = '=';
469
            output[3] = '=';
470
            break;
471
        case 2: /* two bytes read */
472
            output[0] = table64[obuf[0]];
473
            output[1] = table64[obuf[1]];
474
            output[2] = table64[obuf[2]];
475
            output[3] = '=';
476
            break;
477
        default:
478
            output[0] = table64[obuf[0]];
479
            output[1] = table64[obuf[1]];
480
            output[2] = table64[obuf[2]];
481
            output[3] = table64[obuf[3]];
482
            break;
483
        }
484
        output += 4;
485
    }
486
    *output = 0;
487
    *outptr = base64data; /* make it return the actual data memory */
488

489
    return strlen(base64data); /* return the length of the new data */
490
}
491
/* ---- End of Base64 Encoding ---- */
492

493
LIBSSH2_API void
494
libssh2_free(LIBSSH2_SESSION *session, void *ptr)
495
{
496
    LIBSSH2_FREE(session, ptr);
497
}
498

499
#ifdef LIBSSH2DEBUG
500
#include <stdarg.h>
501

502
LIBSSH2_API int
503
libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
504
{
505
    session->showmask = bitmask;
506
    return 0;
507
}
508

509
LIBSSH2_API int
510
libssh2_trace_sethandler(LIBSSH2_SESSION *session, void *handler_context,
511
                         libssh2_trace_handler_func callback)
512
{
513
    session->tracehandler = callback;
514
    session->tracehandler_context = handler_context;
515
    return 0;
516
}
517

518
void
519
_libssh2_debug_low(LIBSSH2_SESSION * session, int context, const char *format,
520
                   ...)
521
{
522
    char buffer[1536];
523
    int len, msglen, buflen = sizeof(buffer);
524
    va_list vargs;
525
    struct timeval now;
526
    static long firstsec;
527
    static const char *const contexts[] = {
528
        "Unknown",
529
        "Transport",
530
        "Key Ex",
531
        "Userauth",
532
        "Conn",
533
        "SCP",
534
        "SFTP",
535
        "Failure Event",
536
        "Publickey",
537
        "Socket",
538
    };
539
    const char *contexttext = contexts[0];
540
    unsigned int contextindex;
541

542
    if(!(session->showmask & context)) {
543
        /* no such output asked for */
544
        return;
545
    }
546

547
    /* Find the first matching context string for this message */
548
    for(contextindex = 0; contextindex < ARRAY_SIZE(contexts);
549
         contextindex++) {
550
        if((context & (1 << contextindex)) != 0) {
551
            contexttext = contexts[contextindex];
552
            break;
553
        }
554
    }
555

556
    gettimeofday(&now, NULL);
557
    if(!firstsec) {
558
        firstsec = now.tv_sec;
559
    }
560
    now.tv_sec -= firstsec;
561

562
    len = snprintf(buffer, buflen, "[libssh2] %d.%06d %s: ",
563
                   (int)now.tv_sec, (int)now.tv_usec, contexttext);
564

565
    if(len >= buflen)
566
        msglen = buflen - 1;
567
    else {
568
        buflen -= len;
569
        msglen = len;
570
        va_start(vargs, format);
571
        len = vsnprintf(buffer + msglen, buflen, format, vargs);
572
        va_end(vargs);
573
        msglen += len < buflen ? len : buflen - 1;
574
    }
575

576
    if(session->tracehandler)
577
        (session->tracehandler)(session, session->tracehandler_context, buffer,
578
                                msglen);
579
    else
580
        fprintf(stderr, "%s\n", buffer);
581
}
582

583
#else
584
LIBSSH2_API int
585
libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
586
{
587
    (void)session;
588
    (void)bitmask;
589
    return 0;
590
}
591

592
LIBSSH2_API int
593
libssh2_trace_sethandler(LIBSSH2_SESSION *session, void *handler_context,
594
                         libssh2_trace_handler_func callback)
595
{
596
    (void)session;
597
    (void)handler_context;
598
    (void)callback;
599
    return 0;
600
}
601
#endif
602

603
/* init the list head */
604
void _libssh2_list_init(struct list_head *head)
605
{
606
    head->first = head->last = NULL;
607
}
608

609
/* add a node to the list */
610
void _libssh2_list_add(struct list_head *head,
611
                       struct list_node *entry)
612
{
613
    /* store a pointer to the head */
614
    entry->head = head;
615

616
    /* we add this entry at the "top" so it has no next */
617
    entry->next = NULL;
618

619
    /* make our prev point to what the head thinks is last */
620
    entry->prev = head->last;
621

622
    /* and make head's last be us now */
623
    head->last = entry;
624

625
    /* make sure our 'prev' node points to us next */
626
    if(entry->prev)
627
        entry->prev->next = entry;
628
    else
629
        head->first = entry;
630
}
631

632
/* return the "first" node in the list this head points to */
633
void *_libssh2_list_first(struct list_head *head)
634
{
635
    return head->first;
636
}
637

638
/* return the next node in the list */
639
void *_libssh2_list_next(struct list_node *node)
640
{
641
    return node->next;
642
}
643

644
/* return the prev node in the list */
645
void *_libssh2_list_prev(struct list_node *node)
646
{
647
    return node->prev;
648
}
649

650
/* remove this node from the list */
651
void _libssh2_list_remove(struct list_node *entry)
652
{
653
    if(entry->prev)
654
        entry->prev->next = entry->next;
655
    else
656
        entry->head->first = entry->next;
657

658
    if(entry->next)
659
        entry->next->prev = entry->prev;
660
    else
661
        entry->head->last = entry->prev;
662
}
663

664
#if 0
665
/* insert a node before the given 'after' entry */
666
void _libssh2_list_insert(struct list_node *after, /* insert before this */
667
                          struct list_node *entry)
668
{
669
    /* 'after' is next to 'entry' */
670
    bentry->next = after;
671

672
    /* entry's prev is then made to be the prev after current has */
673
    entry->prev = after->prev;
674

675
    /* the node that is now before 'entry' was previously before 'after'
676
       and must be made to point to 'entry' correctly */
677
    if(entry->prev)
678
        entry->prev->next = entry;
679
    else
680
      /* there was no node before this, so we make sure we point the head
681
         pointer to this node */
682
      after->head->first = entry;
683

684
    /* after's prev entry points back to entry */
685
    after->prev = entry;
686

687
    /* after's next entry is still the same as before */
688

689
    /* entry's head is the same as after's */
690
    entry->head = after->head;
691
}
692

693
#endif
694

695
/* Defined in libssh2_priv.h for the correct platforms */
696
#ifdef LIBSSH2_GETTIMEOFDAY
697
/*
698
 * _libssh2_gettimeofday
699
 * Implementation according to:
700
 * The Open Group Base Specifications Issue 6
701
 * IEEE Std 1003.1, 2004 Edition
702
 */
703

704
/*
705
 *  THIS SOFTWARE IS NOT COPYRIGHTED
706
 *
707
 *  This source code is offered for use in the public domain. You may
708
 *  use, modify or distribute it freely.
709
 *
710
 *  This code is distributed in the hope that it will be useful but
711
 *  WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
712
 *  DISCLAIMED. This includes but is not limited to warranties of
713
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
714
 *
715
 *  Contributed by:
716
 *  Danny Smith <dannysmith@users.sourceforge.net>
717
 */
718

719
int _libssh2_gettimeofday(struct timeval *tp, void *tzp)
720
{
721
    (void)tzp;
722
    if(tp) {
723
#ifdef _WIN32
724
        /* Offset between 1601-01-01 and 1970-01-01 in 100 nanosec units */
725
        #define _WIN32_FT_OFFSET (116444736000000000)
726

727
        union {
728
            libssh2_uint64_t ns100; /* time since 1 Jan 1601 in 100ns units */
729
            FILETIME ft;
730
        } _now;
731
        GetSystemTimeAsFileTime(&_now.ft);
732
        tp->tv_usec = (long)((_now.ns100 / 10) % 1000000);
733
        tp->tv_sec = (long)((_now.ns100 - _WIN32_FT_OFFSET) / 10000000);
734
#else
735
        /* Platforms without a native implementation or local replacement */
736
        tp->tv_usec = 0;
737
        tp->tv_sec = 0;
738
#endif
739
    }
740
    /* Always return 0 as per Open Group Base Specifications Issue 6.
741
       Do not set errno on error.  */
742
    return 0;
743
}
744
#endif
745

746
void *_libssh2_calloc(LIBSSH2_SESSION* session, size_t size)
747
{
748
    void *p = LIBSSH2_ALLOC(session, size);
749
    if(p) {
750
        memset(p, 0, size);
751
    }
752
    return p;
753
}
754

755
/* XOR operation on buffers input1 and input2, result in output.
756
   It is safe to use an input buffer as the output buffer. */
757
void _libssh2_xor_data(unsigned char *output,
758
                       const unsigned char *input1,
759
                       const unsigned char *input2,
760
                       size_t length)
761
{
762
    size_t i;
763

764
    for(i = 0; i < length; i++)
765
        *output++ = *input1++ ^ *input2++;
766
}
767

768
/* Increments an AES CTR buffer to prepare it for use with the
769
   next AES block. */
770
void _libssh2_aes_ctr_increment(unsigned char *ctr,
771
                                size_t length)
772
{
773
    unsigned char *pc;
774
    unsigned int val, carry;
775

776
    pc = ctr + length - 1;
777
    carry = 1;
778

779
    while(pc >= ctr) {
780
        val = (unsigned int)*pc + carry;
781
        *pc-- = val & 0xFF;
782
        carry = val >> 8;
783
    }
784
}
785

786
#ifdef LIBSSH2_MEMZERO
787
static void * (* const volatile memset_libssh)(void *, int, size_t) = memset;
788

789
void _libssh2_memzero(void *buf, size_t size)
790
{
791
    memset_libssh(buf, 0, size);
792
}
793
#endif
794

795
/* String buffer */
796

797
struct string_buf *_libssh2_string_buf_new(LIBSSH2_SESSION *session)
798
{
799
    struct string_buf *ret;
800

801
    ret = _libssh2_calloc(session, sizeof(*ret));
802
    if(!ret)
803
        return NULL;
804

805
    return ret;
806
}
807

808
void _libssh2_string_buf_free(LIBSSH2_SESSION *session, struct string_buf *buf)
809
{
810
    if(!buf)
811
        return;
812

813
    if(buf->data)
814
        LIBSSH2_FREE(session, buf->data);
815

816
    LIBSSH2_FREE(session, buf);
817
    buf = NULL;
818
}
819

820
int _libssh2_get_byte(struct string_buf *buf, unsigned char *out)
821
{
822
    if(!_libssh2_check_length(buf, 1)) {
823
        return -1;
824
    }
825

826
    *out = buf->dataptr[0];
827
    buf->dataptr += 1;
828
    return 0;
829
}
830

831
int _libssh2_get_boolean(struct string_buf *buf, unsigned char *out)
832
{
833
    if(!_libssh2_check_length(buf, 1)) {
834
        return -1;
835
    }
836

837

838
    *out = buf->dataptr[0] == 0 ? 0 : 1;
839
    buf->dataptr += 1;
840
    return 0;
841
}
842

843
int _libssh2_get_u32(struct string_buf *buf, uint32_t *out)
844
{
845
    if(!_libssh2_check_length(buf, 4)) {
846
        return -1;
847
    }
848

849
    *out = _libssh2_ntohu32(buf->dataptr);
850
    buf->dataptr += 4;
851
    return 0;
852
}
853

854
int _libssh2_get_u64(struct string_buf *buf, libssh2_uint64_t *out)
855
{
856
    if(!_libssh2_check_length(buf, 8)) {
857
        return -1;
858
    }
859

860
    *out = _libssh2_ntohu64(buf->dataptr);
861
    buf->dataptr += 8;
862
    return 0;
863
}
864

865
int _libssh2_match_string(struct string_buf *buf, const char *match)
866
{
867
    unsigned char *out;
868
    size_t len = 0;
869
    if(_libssh2_get_string(buf, &out, &len) || len != strlen(match) ||
870
        strncmp((char *)out, match, strlen(match)) != 0) {
871
        return -1;
872
    }
873
    return 0;
874
}
875

876
int _libssh2_get_string(struct string_buf *buf, unsigned char **outbuf,
877
                        size_t *outlen)
878
{
879
    uint32_t data_len;
880
    if(!buf || _libssh2_get_u32(buf, &data_len) != 0) {
881
        return -1;
882
    }
883
    if(!_libssh2_check_length(buf, data_len)) {
884
        return -1;
885
    }
886
    *outbuf = buf->dataptr;
887
    buf->dataptr += data_len;
888

889
    if(outlen)
890
        *outlen = (size_t)data_len;
891

892
    return 0;
893
}
894

895
int _libssh2_copy_string(LIBSSH2_SESSION *session, struct string_buf *buf,
896
                         unsigned char **outbuf, size_t *outlen)
897
{
898
    size_t str_len;
899
    unsigned char *str;
900

901
    if(_libssh2_get_string(buf, &str, &str_len)) {
902
        return -1;
903
    }
904

905
    if(str_len) {
906
        *outbuf = LIBSSH2_ALLOC(session, str_len);
907
        if(*outbuf) {
908
            memcpy(*outbuf, str, str_len);
909
        }
910
        else {
911
            return -1;
912
        }
913
    }
914
    else {
915
        *outbuf = NULL;
916
    }
917

918
    if(outlen)
919
        *outlen = str_len;
920

921
    return 0;
922
}
923

924
int _libssh2_get_bignum_bytes(struct string_buf *buf, unsigned char **outbuf,
925
                              size_t *outlen)
926
{
927
    uint32_t data_len;
928
    uint32_t bn_len;
929
    unsigned char *bnptr;
930

931
    if(_libssh2_get_u32(buf, &data_len)) {
932
        return -1;
933
    }
934
    if(!_libssh2_check_length(buf, data_len)) {
935
        return -1;
936
    }
937

938
    bn_len = data_len;
939
    bnptr = buf->dataptr;
940

941
    /* trim leading zeros */
942
    while(bn_len > 0 && *bnptr == 0x00) {
943
        bn_len--;
944
        bnptr++;
945
    }
946

947
    *outbuf = bnptr;
948
    buf->dataptr += data_len;
949

950
    if(outlen)
951
        *outlen = (size_t)bn_len;
952

953
    return 0;
954
}
955

956
/* Given the current location in buf, _libssh2_check_length ensures
957
   callers can read the next len number of bytes out of the buffer
958
   before reading the buffer content */
959

960
int _libssh2_check_length(struct string_buf *buf, size_t len)
961
{
962
    unsigned char *endp = &buf->data[buf->len];
963
    size_t left = endp - buf->dataptr;
964
    return (len <= left) && (left <= buf->len);
965
}
966

967
int _libssh2_eob(struct string_buf *buf)
968
{
969
    unsigned char *endp = &buf->data[buf->len];
970
    return buf->dataptr >= endp;
971
}
972

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.