1
/* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>
2
* Copyright (c) 2009-2010 by Daniel Stenberg
3
* Copyright (c) 2010 Simon Josefsson
6
* Redistribution and use in source and binary forms,
7
* with or without modification, are permitted provided
8
* that the following conditions are met:
10
* Redistributions of source code must retain the above
11
* copyright notice, this list of conditions and the
12
* following disclaimer.
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.
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.
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
40
#include "libssh2_priv.h"
47
#ifdef HAVE_SYS_TIME_H
54
int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char* errmsg)
56
session->err_msg = errmsg;
57
session->err_code = errcode;
59
if((errcode == LIBSSH2_ERROR_EAGAIN) && !session->api_block_mode)
60
/* if this is EAGAIN and we're in non-blocking mode, don't generate
61
a debug output for this */
63
_libssh2_debug(session, LIBSSH2_TRACE_ERROR, "%d - %s", session->err_code,
71
static int wsa2errno(void)
73
switch (WSAGetLastError()) {
84
/* It is most important to ensure errno does not stay at EAGAIN
85
* when a different error occurs so just set errno to a generic
94
* Replacement for the standard recv, return -errno on failure.
97
_libssh2_recv(libssh2_socket_t sock, void *buffer, size_t length, int flags, void **abstract)
99
ssize_t rc = recv(sock, buffer, length, flags);
105
if ( errno == EWOULDBLOCK )
112
/* Sometimes the first recv() function call sets errno to ENOENT on
114
if ( errno == ENOENT )
125
* Replacement for the standard send, return -errno on failure.
128
_libssh2_send(libssh2_socket_t sock, const void *buffer, size_t length,
129
int flags, void **abstract)
131
ssize_t rc = send(sock, buffer, length, flags);
137
if ( errno == EWOULDBLOCK )
152
_libssh2_ntohu32(const unsigned char *buf)
154
return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
161
_libssh2_ntohu64(const unsigned char *buf)
163
unsigned long msl, lsl;
165
msl = ((libssh2_uint64_t)buf[0] << 24) | ((libssh2_uint64_t)buf[1] << 16)
166
| ((libssh2_uint64_t)buf[2] << 8) | (libssh2_uint64_t)buf[3];
167
lsl = ((libssh2_uint64_t)buf[4] << 24) | ((libssh2_uint64_t)buf[5] << 16)
168
| ((libssh2_uint64_t)buf[6] << 8) | (libssh2_uint64_t)buf[7];
170
return ((libssh2_uint64_t)msl <<32) | lsl;
176
_libssh2_htonu32(unsigned char *buf, uint32_t value)
178
buf[0] = (value >> 24) & 0xFF;
179
buf[1] = (value >> 16) & 0xFF;
180
buf[2] = (value >> 8) & 0xFF;
181
buf[3] = value & 0xFF;
184
/* _libssh2_store_u32
186
void _libssh2_store_u32(unsigned char **buf, uint32_t value)
188
_libssh2_htonu32(*buf, value);
189
*buf += sizeof(uint32_t);
192
/* _libssh2_store_str
194
void _libssh2_store_str(unsigned char **buf, const char *str, size_t len)
196
_libssh2_store_u32(buf, (uint32_t)len);
198
memcpy(*buf, str, len);
203
/* Base64 Conversion */
205
static const char base64_table[] =
207
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
208
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
209
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
210
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
211
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0'
214
static const char base64_pad = '=';
216
static const short base64_reverse_table[256] = {
217
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
218
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
219
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
220
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
221
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
222
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
223
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
224
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
225
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
226
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
227
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
228
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
229
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
230
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
231
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
232
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
235
/* libssh2_base64_decode
237
* Decode a base64 chunk and store it into a newly alloc'd buffer
240
libssh2_base64_decode(LIBSSH2_SESSION *session, char **data,
241
unsigned int *datalen, const char *src,
242
unsigned int src_len)
244
unsigned char *s, *d;
248
*data = LIBSSH2_ALLOC(session, (3 * src_len / 4) + 1);
249
d = (unsigned char *) *data;
251
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
252
"Unable to allocate memory for base64 decoding");
255
for(s = (unsigned char *) src; ((char *) s) < (src + src_len); s++) {
256
if ((v = base64_reverse_table[*s]) < 0)
277
/* Invalid -- We have a byte which belongs exclusively to a partial
279
LIBSSH2_FREE(session, *data);
280
return _libssh2_error(session, LIBSSH2_ERROR_INVAL, "Invalid base64");
287
/* ---- Base64 Encoding/Decoding Table --- */
288
static const char table64[]=
289
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
292
* _libssh2_base64_encode()
294
* Returns the length of the newly created base64 string. The third argument
295
* is a pointer to an allocated area holding the base64 data. If something
296
* went wrong, 0 is returned.
299
size_t _libssh2_base64_encode(LIBSSH2_SESSION *session,
300
const char *inp, size_t insize, char **outptr)
302
unsigned char ibuf[3];
303
unsigned char obuf[4];
308
const char *indata = inp;
310
*outptr = NULL; /* set to NULL in case of failure before we reach the end */
313
insize = strlen(indata);
315
base64data = output = LIBSSH2_ALLOC(session, insize*4/3+4);
320
for (i = inputparts = 0; i < 3; i++) {
331
obuf[0] = (unsigned char) ((ibuf[0] & 0xFC) >> 2);
332
obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \
333
((ibuf[1] & 0xF0) >> 4));
334
obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \
335
((ibuf[2] & 0xC0) >> 6));
336
obuf[3] = (unsigned char) (ibuf[2] & 0x3F);
339
case 1: /* only one byte read */
340
snprintf(output, 5, "%c%c==",
344
case 2: /* two bytes read */
345
snprintf(output, 5, "%c%c%c=",
351
snprintf(output, 5, "%c%c%c%c",
361
*outptr = base64data; /* make it return the actual data memory */
363
return strlen(base64data); /* return the length of the new data */
365
/* ---- End of Base64 Encoding ---- */
368
libssh2_free(LIBSSH2_SESSION *session, void *ptr)
370
LIBSSH2_FREE(session, ptr);
375
libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
377
session->showmask = bitmask;
382
libssh2_trace_sethandler(LIBSSH2_SESSION *session, void* handler_context,
383
libssh2_trace_handler_func callback)
385
session->tracehandler = callback;
386
session->tracehandler_context = handler_context;
391
_libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
394
int len, msglen, buflen = sizeof(buffer);
398
static const char *const contexts[] = {
410
const char* contexttext = contexts[0];
411
unsigned int contextindex;
413
if (!(session->showmask & context)) {
414
/* no such output asked for */
418
/* Find the first matching context string for this message */
419
for (contextindex = 0; contextindex < ARRAY_SIZE(contexts);
421
if ((context & (1 << contextindex)) != 0) {
422
contexttext = contexts[contextindex];
427
_libssh2_gettimeofday(&now, NULL);
429
firstsec = now.tv_sec;
431
now.tv_sec -= firstsec;
433
len = snprintf(buffer, buflen, "[libssh2] %d.%06d %s: ",
434
(int)now.tv_sec, (int)now.tv_usec, contexttext);
441
va_start(vargs, format);
442
len = vsnprintf(buffer + msglen, buflen, format, vargs);
444
msglen += len < buflen ? len : buflen - 1;
447
if (session->tracehandler)
448
(session->tracehandler)(session, session->tracehandler_context, buffer,
451
fprintf(stderr, "%s\n", buffer);
456
libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
464
libssh2_trace_sethandler(LIBSSH2_SESSION *session, void* handler_context,
465
libssh2_trace_handler_func callback)
468
(void) handler_context;
474
/* init the list head */
475
void _libssh2_list_init(struct list_head *head)
477
head->first = head->last = NULL;
480
/* add a node to the list */
481
void _libssh2_list_add(struct list_head *head,
482
struct list_node *entry)
484
/* store a pointer to the head */
487
/* we add this entry at the "top" so it has no next */
490
/* make our prev point to what the head thinks is last */
491
entry->prev = head->last;
493
/* and make head's last be us now */
496
/* make sure our 'prev' node points to us next */
498
entry->prev->next = entry;
503
/* return the "first" node in the list this head points to */
504
void *_libssh2_list_first(struct list_head *head)
509
/* return the next node in the list */
510
void *_libssh2_list_next(struct list_node *node)
515
/* return the prev node in the list */
516
void *_libssh2_list_prev(struct list_node *node)
521
/* remove this node from the list */
522
void _libssh2_list_remove(struct list_node *entry)
525
entry->prev->next = entry->next;
527
entry->head->first = entry->next;
530
entry->next->prev = entry->prev;
532
entry->head->last = entry->prev;
536
/* insert a node before the given 'after' entry */
537
void _libssh2_list_insert(struct list_node *after, /* insert before this */
538
struct list_node *entry)
540
/* 'after' is next to 'entry' */
541
bentry->next = after;
543
/* entry's prev is then made to be the prev after current has */
544
entry->prev = after->prev;
546
/* the node that is now before 'entry' was previously before 'after'
547
and must be made to point to 'entry' correctly */
549
entry->prev->next = entry;
551
/* there was no node before this, so we make sure we point the head
552
pointer to this node */
553
after->head->first = entry;
555
/* after's prev entry points back to entry */
558
/* after's next entry is still the same as before */
560
/* entry's head is the same as after's */
561
entry->head = after->head;
566
/* this define is defined in misc.h for the correct platforms */
567
#ifdef LIBSSH2_GETTIMEOFDAY_WIN32
570
* Implementation according to:
571
* The Open Group Base Specifications Issue 6
572
* IEEE Std 1003.1, 2004 Edition
576
* THIS SOFTWARE IS NOT COPYRIGHTED
578
* This source code is offered for use in the public domain. You may
579
* use, modify or distribute it freely.
581
* This code is distributed in the hope that it will be useful but
582
* WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
583
* DISCLAIMED. This includes but is not limited to warranties of
584
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
587
* Danny Smith <dannysmith@users.sourceforge.net>
590
/* Offset between 1/1/1601 and 1/1/1970 in 100 nanosec units */
591
#define _W32_FT_OFFSET (116444736000000000)
593
int __cdecl _libssh2_gettimeofday(struct timeval *tp, void *tzp)
596
unsigned __int64 ns100; /*time since 1 Jan 1601 in 100ns units */
602
GetSystemTimeAsFileTime (&_now.ft);
603
tp->tv_usec=(long)((_now.ns100 / 10) % 1000000 );
604
tp->tv_sec= (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000);
606
/* Always return 0 as per Open Group Base Specifications Issue 6.
607
Do not set errno on error. */