summaryrefslogtreecommitdiff
path: root/libs/libssh2/src/misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libssh2/src/misc.c')
-rw-r--r--libs/libssh2/src/misc.c431
1 files changed, 330 insertions, 101 deletions
diff --git a/libs/libssh2/src/misc.c b/libs/libssh2/src/misc.c
index f7faae7b6a..bd084c854f 100644
--- a/libs/libssh2/src/misc.c
+++ b/libs/libssh2/src/misc.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>
- * Copyright (c) 2009-2014 by Daniel Stenberg
+ * Copyright (c) 2009-2019 by Daniel Stenberg
* Copyright (c) 2010 Simon Josefsson
* All rights reserved.
*
@@ -39,6 +39,11 @@
#include "libssh2_priv.h"
#include "misc.h"
+#include "blf.h"
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
@@ -48,21 +53,28 @@
#include <sys/time.h>
#endif
+#if defined(HAVE_DECL_SECUREZEROMEMORY) && HAVE_DECL_SECUREZEROMEMORY
+#ifdef HAVE_WINDOWS_H
+#include <windows.h>
+#endif
+#endif
+
#include <stdio.h>
#include <errno.h>
-int _libssh2_error_flags(LIBSSH2_SESSION* session, int errcode, const char* errmsg, int errflags)
+int _libssh2_error_flags(LIBSSH2_SESSION* session, int errcode,
+ const char *errmsg, int errflags)
{
- if (session->err_flags & LIBSSH2_ERR_FLAG_DUP)
+ if(session->err_flags & LIBSSH2_ERR_FLAG_DUP)
LIBSSH2_FREE(session, (char *)session->err_msg);
session->err_code = errcode;
session->err_flags = 0;
- if ((errmsg != NULL) && ((errflags & LIBSSH2_ERR_FLAG_DUP) != 0)) {
+ if((errmsg != NULL) && ((errflags & LIBSSH2_ERR_FLAG_DUP) != 0)) {
size_t len = strlen(errmsg);
char *copy = LIBSSH2_ALLOC(session, len + 1);
- if (copy) {
+ if(copy) {
memcpy(copy, errmsg, len + 1);
session->err_flags = LIBSSH2_ERR_FLAG_DUP;
session->err_msg = copy;
@@ -86,7 +98,7 @@ int _libssh2_error_flags(LIBSSH2_SESSION* session, int errcode, const char* errm
return errcode;
}
-int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char* errmsg)
+int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char *errmsg)
{
return _libssh2_error_flags(session, errcode, errmsg, 0);
}
@@ -94,7 +106,7 @@ int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char* errmsg)
#ifdef WIN32
static int wsa2errno(void)
{
- switch (WSAGetLastError()) {
+ switch(WSAGetLastError()) {
case WSAEWOULDBLOCK:
return EAGAIN;
@@ -127,20 +139,20 @@ _libssh2_recv(libssh2_socket_t sock, void *buffer, size_t length,
rc = recv(sock, buffer, length, flags);
#ifdef WIN32
- if (rc < 0 )
+ if(rc < 0)
return -wsa2errno();
#elif defined(__VMS)
- if (rc < 0 ){
- if ( errno == EWOULDBLOCK )
+ if(rc < 0) {
+ if(errno == EWOULDBLOCK)
return -EAGAIN;
else
return -errno;
}
#else
- if (rc < 0 ){
+ if(rc < 0) {
/* Sometimes the first recv() function call sets errno to ENOENT on
Solaris and HP-UX */
- if ( errno == ENOENT )
+ if(errno == ENOENT)
return -EAGAIN;
else
return -errno;
@@ -163,17 +175,17 @@ _libssh2_send(libssh2_socket_t sock, const void *buffer, size_t length,
rc = send(sock, buffer, length, flags);
#ifdef WIN32
- if (rc < 0 )
+ if(rc < 0)
return -wsa2errno();
#elif defined(__VMS)
- if (rc < 0 ) {
- if ( errno == EWOULDBLOCK )
+ if(rc < 0) {
+ if(errno == EWOULDBLOCK)
return -EAGAIN;
else
return -errno;
}
#else
- if (rc < 0 )
+ if(rc < 0)
return -errno;
#endif
return rc;
@@ -269,15 +281,16 @@ libssh2_base64_decode(LIBSSH2_SESSION *session, char **data,
*data = LIBSSH2_ALLOC(session, (3 * src_len / 4) + 1);
d = (unsigned char *) *data;
- if (!d) {
+ if(!d) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for base64 decoding");
}
for(s = (unsigned char *) src; ((char *) s) < (src + src_len); s++) {
- if ((v = base64_reverse_table[*s]) < 0)
+ v = base64_reverse_table[*s];
+ if(v < 0)
continue;
- switch (i % 4) {
+ switch(i % 4) {
case 0:
d[len] = (unsigned char)(v << 2);
break;
@@ -295,10 +308,11 @@ libssh2_base64_decode(LIBSSH2_SESSION *session, char **data,
}
i++;
}
- if ((i % 4) == 1) {
+ if((i % 4) == 1) {
/* Invalid -- We have a byte which belongs exclusively to a partial
octet */
LIBSSH2_FREE(session, *data);
+ *data = NULL;
return _libssh2_error(session, LIBSSH2_ERROR_INVAL, "Invalid base64");
}
@@ -321,68 +335,69 @@ static const char table64[]=
size_t _libssh2_base64_encode(LIBSSH2_SESSION *session,
const char *inp, size_t insize, char **outptr)
{
- unsigned char ibuf[3];
- unsigned char obuf[4];
- int i;
- int inputparts;
- char *output;
- char *base64data;
- const char *indata = inp;
-
- *outptr = NULL; /* set to NULL in case of failure before we reach the end */
-
- if(0 == insize)
- insize = strlen(indata);
-
- base64data = output = LIBSSH2_ALLOC(session, insize*4/3+4);
- if(NULL == output)
- return 0;
-
- while(insize > 0) {
- for (i = inputparts = 0; i < 3; i++) {
- if(insize > 0) {
- inputparts++;
- ibuf[i] = *indata;
- indata++;
- insize--;
- }
- else
- ibuf[i] = 0;
- }
+ unsigned char ibuf[3];
+ unsigned char obuf[4];
+ int i;
+ int inputparts;
+ char *output;
+ char *base64data;
+ const char *indata = inp;
+
+ *outptr = NULL; /* set to NULL in case of failure before we reach the
+ end */
+
+ if(0 == insize)
+ insize = strlen(indata);
+
+ base64data = output = LIBSSH2_ALLOC(session, insize * 4 / 3 + 4);
+ if(NULL == output)
+ return 0;
+
+ while(insize > 0) {
+ for(i = inputparts = 0; i < 3; i++) {
+ if(insize > 0) {
+ inputparts++;
+ ibuf[i] = *indata;
+ indata++;
+ insize--;
+ }
+ else
+ ibuf[i] = 0;
+ }
- obuf[0] = (unsigned char) ((ibuf[0] & 0xFC) >> 2);
- obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \
- ((ibuf[1] & 0xF0) >> 4));
- obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \
- ((ibuf[2] & 0xC0) >> 6));
- obuf[3] = (unsigned char) (ibuf[2] & 0x3F);
-
- switch(inputparts) {
- case 1: /* only one byte read */
- snprintf(output, 5, "%c%c==",
- table64[obuf[0]],
- table64[obuf[1]]);
- break;
- case 2: /* two bytes read */
- snprintf(output, 5, "%c%c%c=",
- table64[obuf[0]],
- table64[obuf[1]],
- table64[obuf[2]]);
- break;
- default:
- snprintf(output, 5, "%c%c%c%c",
- table64[obuf[0]],
- table64[obuf[1]],
- table64[obuf[2]],
- table64[obuf[3]] );
- break;
+ obuf[0] = (unsigned char) ((ibuf[0] & 0xFC) >> 2);
+ obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \
+ ((ibuf[1] & 0xF0) >> 4));
+ obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \
+ ((ibuf[2] & 0xC0) >> 6));
+ obuf[3] = (unsigned char) (ibuf[2] & 0x3F);
+
+ switch(inputparts) {
+ case 1: /* only one byte read */
+ snprintf(output, 5, "%c%c==",
+ table64[obuf[0]],
+ table64[obuf[1]]);
+ break;
+ case 2: /* two bytes read */
+ snprintf(output, 5, "%c%c%c=",
+ table64[obuf[0]],
+ table64[obuf[1]],
+ table64[obuf[2]]);
+ break;
+ default:
+ snprintf(output, 5, "%c%c%c%c",
+ table64[obuf[0]],
+ table64[obuf[1]],
+ table64[obuf[2]],
+ table64[obuf[3]]);
+ break;
+ }
+ output += 4;
}
- output += 4;
- }
- *output=0;
- *outptr = base64data; /* make it return the actual data memory */
+ *output = 0;
+ *outptr = base64data; /* make it return the actual data memory */
- return strlen(base64data); /* return the length of the new data */
+ return strlen(base64data); /* return the length of the new data */
}
/* ---- End of Base64 Encoding ---- */
@@ -403,7 +418,7 @@ libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
}
LIBSSH2_API int
-libssh2_trace_sethandler(LIBSSH2_SESSION *session, void* handler_context,
+libssh2_trace_sethandler(LIBSSH2_SESSION *session, void *handler_context,
libssh2_trace_handler_func callback)
{
session->tracehandler = callback;
@@ -431,18 +446,18 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
"Publickey",
"Socket",
};
- const char* contexttext = contexts[0];
+ const char *contexttext = contexts[0];
unsigned int contextindex;
- if (!(session->showmask & context)) {
+ if(!(session->showmask & context)) {
/* no such output asked for */
return;
}
/* Find the first matching context string for this message */
- for (contextindex = 0; contextindex < ARRAY_SIZE(contexts);
+ for(contextindex = 0; contextindex < ARRAY_SIZE(contexts);
contextindex++) {
- if ((context & (1 << contextindex)) != 0) {
+ if((context & (1 << contextindex)) != 0) {
contexttext = contexts[contextindex];
break;
}
@@ -457,7 +472,7 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
len = snprintf(buffer, buflen, "[libssh2] %d.%06d %s: ",
(int)now.tv_sec, (int)now.tv_usec, contexttext);
- if (len >= buflen)
+ if(len >= buflen)
msglen = buflen - 1;
else {
buflen -= len;
@@ -468,7 +483,7 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
msglen += len < buflen ? len : buflen - 1;
}
- if (session->tracehandler)
+ if(session->tracehandler)
(session->tracehandler)(session, session->tracehandler_context, buffer,
msglen);
else
@@ -485,7 +500,7 @@ libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
}
LIBSSH2_API int
-libssh2_trace_sethandler(LIBSSH2_SESSION *session, void* handler_context,
+libssh2_trace_sethandler(LIBSSH2_SESSION *session, void *handler_context,
libssh2_trace_handler_func callback)
{
(void) session;
@@ -615,21 +630,20 @@ void _libssh2_list_insert(struct list_node *after, /* insert before this */
#define _W32_FT_OFFSET (116444736000000000)
int __cdecl _libssh2_gettimeofday(struct timeval *tp, void *tzp)
- {
- union {
- unsigned __int64 ns100; /*time since 1 Jan 1601 in 100ns units */
- FILETIME ft;
- } _now;
- (void)tzp;
- if(tp)
- {
- GetSystemTimeAsFileTime (&_now.ft);
- tp->tv_usec=(long)((_now.ns100 / 10) % 1000000 );
- tp->tv_sec= (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000);
+{
+ union {
+ unsigned __int64 ns100; /*time since 1 Jan 1601 in 100ns units */
+ FILETIME ft;
+ } _now;
+ (void)tzp;
+ if(tp) {
+ GetSystemTimeAsFileTime(&_now.ft);
+ tp->tv_usec = (long)((_now.ns100 / 10) % 1000000);
+ tp->tv_sec = (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000);
}
- /* Always return 0 as per Open Group Base Specifications Issue 6.
- Do not set errno on error. */
- return 0;
+ /* Always return 0 as per Open Group Base Specifications Issue 6.
+ Do not set errno on error. */
+ return 0;
}
@@ -643,3 +657,218 @@ void *_libssh2_calloc(LIBSSH2_SESSION* session, size_t size)
}
return p;
}
+
+/* XOR operation on buffers input1 and input2, result in output.
+ It is safe to use an input buffer as the output buffer. */
+void _libssh2_xor_data(unsigned char *output,
+ const unsigned char *input1,
+ const unsigned char *input2,
+ size_t length)
+{
+ size_t i;
+
+ for(i = 0; i < length; i++)
+ *output++ = *input1++ ^ *input2++;
+}
+
+/* Increments an AES CTR buffer to prepare it for use with the
+ next AES block. */
+void _libssh2_aes_ctr_increment(unsigned char *ctr,
+ size_t length)
+{
+ unsigned char *pc;
+ unsigned int val, carry;
+
+ pc = ctr + length - 1;
+ carry = 1;
+
+ while(pc >= ctr) {
+ val = (unsigned int)*pc + carry;
+ *pc-- = val & 0xFF;
+ carry = val >> 8;
+ }
+}
+
+#ifdef WIN32
+static void * (__cdecl * const volatile memset_libssh)(void *, int, size_t) =
+ memset;
+#else
+static void * (* const volatile memset_libssh)(void *, int, size_t) = memset;
+#endif
+
+void _libssh2_explicit_zero(void *buf, size_t size)
+{
+#if defined(HAVE_DECL_SECUREZEROMEMORY) && HAVE_DECL_SECUREZEROMEMORY
+ SecureZeroMemory(buf, size);
+ (void)memset_libssh; /* Silence unused variable warning */
+#elif defined(HAVE_MEMSET_S)
+ (void)memset_s(buf, size, 0, size);
+ (void)memset_libssh; /* Silence unused variable warning */
+#else
+ memset_libssh(buf, 0, size);
+#endif
+}
+
+/* String buffer */
+
+struct string_buf* _libssh2_string_buf_new(LIBSSH2_SESSION *session)
+{
+ struct string_buf *ret;
+
+ ret = _libssh2_calloc(session, sizeof(*ret));
+ if(ret == NULL)
+ return NULL;
+
+ return ret;
+}
+
+void _libssh2_string_buf_free(LIBSSH2_SESSION *session, struct string_buf *buf)
+{
+ if(buf == NULL)
+ return;
+
+ if(buf->data != NULL)
+ LIBSSH2_FREE(session, buf->data);
+
+ LIBSSH2_FREE(session, buf);
+ buf = NULL;
+}
+
+int _libssh2_get_u32(struct string_buf *buf, uint32_t *out)
+{
+ if(!_libssh2_check_length(buf, 4)) {
+ return -1;
+ }
+
+ *out = _libssh2_ntohu32(buf->dataptr);
+ buf->dataptr += 4;
+ return 0;
+}
+
+int _libssh2_get_u64(struct string_buf *buf, libssh2_uint64_t *out)
+{
+ if(!_libssh2_check_length(buf, 8)) {
+ return -1;
+ }
+
+ *out = _libssh2_ntohu64(buf->dataptr);
+ buf->dataptr += 8;
+ return 0;
+}
+
+int _libssh2_match_string(struct string_buf *buf, const char *match)
+{
+ unsigned char *out;
+ size_t len = 0;
+ if(_libssh2_get_string(buf, &out, &len) || len != strlen(match) ||
+ strncmp((char *)out, match, strlen(match)) != 0) {
+ return -1;
+ }
+ return 0;
+}
+
+int _libssh2_get_string(struct string_buf *buf, unsigned char **outbuf,
+ size_t *outlen)
+{
+ uint32_t data_len;
+ if(_libssh2_get_u32(buf, &data_len) != 0) {
+ return -1;
+ }
+ if(!_libssh2_check_length(buf, data_len)) {
+ return -1;
+ }
+ *outbuf = buf->dataptr;
+ buf->dataptr += data_len;
+
+ if(outlen)
+ *outlen = (size_t)data_len;
+
+ return 0;
+}
+
+int _libssh2_copy_string(LIBSSH2_SESSION *session, struct string_buf *buf,
+ unsigned char **outbuf, size_t *outlen)
+{
+ size_t str_len;
+ unsigned char *str;
+
+ if(_libssh2_get_string(buf, &str, &str_len)) {
+ return -1;
+ }
+
+ *outbuf = LIBSSH2_ALLOC(session, str_len);
+ if(*outbuf) {
+ memcpy(*outbuf, str, str_len);
+ }
+ else {
+ return -1;
+ }
+
+ if(outlen)
+ *outlen = str_len;
+
+ return 0;
+}
+
+int _libssh2_get_bignum_bytes(struct string_buf *buf, unsigned char **outbuf,
+ size_t *outlen)
+{
+ uint32_t data_len;
+ uint32_t bn_len;
+ unsigned char *bnptr;
+
+ if(_libssh2_get_u32(buf, &data_len)) {
+ return -1;
+ }
+ if(!_libssh2_check_length(buf, data_len)) {
+ return -1;
+ }
+
+ bn_len = data_len;
+ bnptr = buf->dataptr;
+
+ /* trim leading zeros */
+ while(bn_len > 0 && *bnptr == 0x00) {
+ bn_len--;
+ bnptr++;
+ }
+
+ *outbuf = bnptr;
+ buf->dataptr += data_len;
+
+ if(outlen)
+ *outlen = (size_t)bn_len;
+
+ return 0;
+}
+
+/* Given the current location in buf, _libssh2_check_length ensures
+ callers can read the next len number of bytes out of the buffer
+ before reading the buffer content */
+
+int _libssh2_check_length(struct string_buf *buf, size_t len)
+{
+ unsigned char *endp = &buf->data[buf->len];
+ size_t left = endp - buf->dataptr;
+ return ((len <= left) && (left <= buf->len));
+}
+
+/* Wrappers */
+
+int _libssh2_bcrypt_pbkdf(const char *pass,
+ size_t passlen,
+ const uint8_t *salt,
+ size_t saltlen,
+ uint8_t *key,
+ size_t keylen,
+ unsigned int rounds)
+{
+ /* defined in bcrypt_pbkdf.c */
+ return bcrypt_pbkdf(pass,
+ passlen,
+ salt,
+ saltlen,
+ key,
+ keylen,
+ rounds);
+}