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.c371
1 files changed, 229 insertions, 142 deletions
diff --git a/libs/libssh2/src/misc.c b/libs/libssh2/src/misc.c
index bd084c854f..b386e3d667 100644
--- a/libs/libssh2/src/misc.c
+++ b/libs/libssh2/src/misc.c
@@ -1,6 +1,6 @@
-/* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>
- * Copyright (c) 2009-2019 by Daniel Stenberg
- * Copyright (c) 2010 Simon Josefsson
+/* Copyright (C) Sara Golemon <sarag@libssh2.org>
+ * Copyright (C) Daniel Stenberg
+ * Copyright (C) Simon Josefsson
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@@ -35,43 +35,66 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
*/
#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>
#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
+#include <errno.h>
+#include <assert.h>
-#if defined(HAVE_DECL_SECUREZEROMEMORY) && HAVE_DECL_SECUREZEROMEMORY
-#ifdef HAVE_WINDOWS_H
-#include <windows.h>
-#endif
+#ifdef WIN32
+/* Force parameter type. */
+#define recv(s, b, l, f) recv((s), (b), (int)(l), (f))
+#define send(s, b, l, f) send((s), (b), (int)(l), (f))
#endif
-#include <stdio.h>
-#include <errno.h>
+/* snprintf not in Visual Studio CRT and _snprintf dangerously incompatible.
+ We provide a safe wrapper if snprintf not found */
+#ifdef LIBSSH2_SNPRINTF
+#include <stdarg.h>
+
+/* Want safe, 'n += snprintf(b + n ...)' like function. If cp_max_len is 1
+* then assume cp is pointing to a null char and do nothing. Returns number
+* number of chars placed in cp excluding the trailing null char. So for
+* cp_max_len > 0 the return value is always < cp_max_len; for cp_max_len
+* <= 0 the return value is 0 (and no chars are written to cp). */
+int _libssh2_snprintf(char *cp, size_t cp_max_len, const char *fmt, ...)
+{
+ va_list args;
+ int n;
+
+ if(cp_max_len < 2)
+ return 0;
+ va_start(args, fmt);
+ n = vsnprintf(cp, cp_max_len, fmt, args);
+ va_end(args);
+ return (n < (int)cp_max_len) ? n : (int)(cp_max_len - 1);
+}
+#endif
int _libssh2_error_flags(LIBSSH2_SESSION* session, int errcode,
const char *errmsg, int errflags)
{
+ if(!session) {
+ if(errmsg)
+ fprintf(stderr, "Session is NULL, error: %s\n", errmsg);
+ return errcode;
+ }
+
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 && ((errflags & LIBSSH2_ERR_FLAG_DUP) != 0)) {
size_t len = strlen(errmsg);
char *copy = LIBSSH2_ALLOC(session, len + 1);
if(copy) {
@@ -91,8 +114,8 @@ int _libssh2_error_flags(LIBSSH2_SESSION* session, int errcode,
/* if this is EAGAIN and we're in non-blocking mode, don't generate
a debug output for this */
return errcode;
- _libssh2_debug(session, LIBSSH2_TRACE_ERROR, "%d - %s", session->err_code,
- session->err_msg);
+ _libssh2_debug((session, LIBSSH2_TRACE_ERROR, "%d - %s", session->err_code,
+ session->err_msg));
#endif
return errcode;
@@ -135,25 +158,22 @@ _libssh2_recv(libssh2_socket_t sock, void *buffer, size_t length,
{
ssize_t rc;
- (void) abstract;
+ (void)abstract;
rc = recv(sock, buffer, length, flags);
#ifdef WIN32
if(rc < 0)
return -wsa2errno();
-#elif defined(__VMS)
- if(rc < 0) {
- if(errno == EWOULDBLOCK)
- return -EAGAIN;
- else
- return -errno;
- }
#else
if(rc < 0) {
/* Sometimes the first recv() function call sets errno to ENOENT on
Solaris and HP-UX */
if(errno == ENOENT)
return -EAGAIN;
+#ifdef EWOULDBLOCK /* For VMS and other special unixes */
+ else if(errno == EWOULDBLOCK)
+ return -EAGAIN;
+#endif
else
return -errno;
}
@@ -171,32 +191,33 @@ _libssh2_send(libssh2_socket_t sock, const void *buffer, size_t length,
{
ssize_t rc;
- (void) abstract;
+ (void)abstract;
rc = send(sock, buffer, length, flags);
#ifdef WIN32
if(rc < 0)
return -wsa2errno();
-#elif defined(__VMS)
+#else
if(rc < 0) {
+#ifdef EWOULDBLOCK /* For VMS and other special unixes */
if(errno == EWOULDBLOCK)
return -EAGAIN;
- else
- return -errno;
- }
-#else
- if(rc < 0)
+#endif
return -errno;
+ }
#endif
return rc;
}
/* libssh2_ntohu32
*/
-unsigned int
+uint32_t
_libssh2_ntohu32(const unsigned char *buf)
{
- return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+ return ((uint32_t)buf[0] << 24)
+ | ((uint32_t)buf[1] << 16)
+ | ((uint32_t)buf[2] << 8)
+ | ((uint32_t)buf[3]);
}
@@ -205,14 +226,14 @@ _libssh2_ntohu32(const unsigned char *buf)
libssh2_uint64_t
_libssh2_ntohu64(const unsigned char *buf)
{
- unsigned long msl, lsl;
-
- msl = ((libssh2_uint64_t)buf[0] << 24) | ((libssh2_uint64_t)buf[1] << 16)
- | ((libssh2_uint64_t)buf[2] << 8) | (libssh2_uint64_t)buf[3];
- lsl = ((libssh2_uint64_t)buf[4] << 24) | ((libssh2_uint64_t)buf[5] << 16)
- | ((libssh2_uint64_t)buf[6] << 8) | (libssh2_uint64_t)buf[7];
-
- return ((libssh2_uint64_t)msl <<32) | lsl;
+ return ((libssh2_uint64_t)buf[0] << 56)
+ | ((libssh2_uint64_t)buf[1] << 48)
+ | ((libssh2_uint64_t)buf[2] << 40)
+ | ((libssh2_uint64_t)buf[3] << 32)
+ | ((libssh2_uint64_t)buf[4] << 24)
+ | ((libssh2_uint64_t)buf[5] << 16)
+ | ((libssh2_uint64_t)buf[6] << 8)
+ | ((libssh2_uint64_t)buf[7]);
}
/* _libssh2_htonu32
@@ -220,7 +241,7 @@ _libssh2_ntohu64(const unsigned char *buf)
void
_libssh2_htonu32(unsigned char *buf, uint32_t value)
{
- buf[0] = (value >> 24) & 0xFF;
+ buf[0] = (unsigned char)((value >> 24) & 0xFF);
buf[1] = (value >> 16) & 0xFF;
buf[2] = (value >> 8) & 0xFF;
buf[3] = value & 0xFF;
@@ -236,13 +257,50 @@ void _libssh2_store_u32(unsigned char **buf, uint32_t value)
/* _libssh2_store_str
*/
-void _libssh2_store_str(unsigned char **buf, const char *str, size_t len)
+int _libssh2_store_str(unsigned char **buf, const char *str, size_t len)
{
- _libssh2_store_u32(buf, (uint32_t)len);
- if(len) {
- memcpy(*buf, str, len);
- *buf += len;
+ uint32_t len_stored = (uint32_t)len;
+
+ _libssh2_store_u32(buf, len_stored);
+ if(len_stored) {
+ memcpy(*buf, str, len_stored);
+ *buf += len_stored;
+ }
+
+ assert(len_stored == len);
+ return len_stored == len;
+}
+
+/* _libssh2_store_bignum2_bytes
+ */
+int _libssh2_store_bignum2_bytes(unsigned char **buf,
+ const unsigned char *bytes,
+ size_t len)
+{
+ uint32_t len_stored;
+ uint32_t extraByte;
+ const unsigned char *p;
+
+ for(p = bytes; len > 0 && *p == 0; --len, ++p) {}
+
+ extraByte = (len > 0 && (p[0] & 0x80) != 0);
+ len_stored = (uint32_t)len;
+ if(extraByte && len_stored == 0xffffffff)
+ len_stored--;
+ _libssh2_store_u32(buf, len_stored + extraByte);
+
+ if(extraByte) {
+ *buf[0] = 0;
+ *buf += 1;
+ }
+
+ if(len_stored) {
+ memcpy(*buf, p, len_stored);
+ *buf += len_stored;
}
+
+ assert(len_stored == len);
+ return len_stored == len;
}
/* Base64 Conversion */
@@ -268,26 +326,46 @@ static const short base64_reverse_table[256] = {
/* libssh2_base64_decode
*
- * Decode a base64 chunk and store it into a newly alloc'd buffer
+ * Legacy public function. DEPRECATED.
*/
LIBSSH2_API int
libssh2_base64_decode(LIBSSH2_SESSION *session, char **data,
unsigned int *datalen, const char *src,
unsigned int src_len)
{
- unsigned char *s, *d;
+ int rc;
+ size_t dlen;
+
+ rc = _libssh2_base64_decode(session, data, &dlen, src, src_len);
+
+ if(datalen)
+ *datalen = (unsigned int)dlen;
+
+ return rc;
+}
+
+/* _libssh2_base64_decode
+ *
+ * Decode a base64 chunk and store it into a newly alloc'd buffer
+ */
+int _libssh2_base64_decode(LIBSSH2_SESSION *session,
+ char **data, size_t *datalen,
+ const char *src, size_t src_len)
+{
+ unsigned char *d;
+ const char *s;
short v;
- int i = 0, len = 0;
+ ssize_t i = 0, len = 0;
- *data = LIBSSH2_ALLOC(session, (3 * src_len / 4) + 1);
+ *data = LIBSSH2_ALLOC(session, ((src_len / 4) * 3) + 1);
d = (unsigned char *) *data;
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++) {
- v = base64_reverse_table[*s];
+ for(s = src; s < (src + src_len); s++) {
+ v = base64_reverse_table[(unsigned char)*s];
if(v < 0)
continue;
switch(i % 4) {
@@ -295,15 +373,15 @@ libssh2_base64_decode(LIBSSH2_SESSION *session, char **data,
d[len] = (unsigned char)(v << 2);
break;
case 1:
- d[len++] |= v >> 4;
+ d[len++] |= (unsigned char)(v >> 4);
d[len] = (unsigned char)(v << 4);
break;
case 2:
- d[len++] |= v >> 2;
+ d[len++] |= (unsigned char)(v >> 2);
d[len] = (unsigned char)(v << 6);
break;
case 3:
- d[len++] |= v;
+ d[len++] |= (unsigned char)v;
break;
}
i++;
@@ -322,10 +400,10 @@ libssh2_base64_decode(LIBSSH2_SESSION *session, char **data,
/* ---- Base64 Encoding/Decoding Table --- */
static const char table64[]=
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/*
- * _libssh2_base64_encode()
+ * _libssh2_base64_encode
*
* Returns the length of the newly created base64 string. The third argument
* is a pointer to an allocated area holding the base64 data. If something
@@ -346,11 +424,11 @@ size_t _libssh2_base64_encode(LIBSSH2_SESSION *session,
*outptr = NULL; /* set to NULL in case of failure before we reach the
end */
- if(0 == insize)
+ if(insize == 0)
insize = strlen(indata);
base64data = output = LIBSSH2_ALLOC(session, insize * 4 / 3 + 4);
- if(NULL == output)
+ if(!output)
return 0;
while(insize > 0) {
@@ -374,22 +452,22 @@ size_t _libssh2_base64_encode(LIBSSH2_SESSION *session,
switch(inputparts) {
case 1: /* only one byte read */
- snprintf(output, 5, "%c%c==",
- table64[obuf[0]],
- table64[obuf[1]]);
+ output[0] = table64[obuf[0]];
+ output[1] = table64[obuf[1]];
+ output[2] = '=';
+ output[3] = '=';
break;
case 2: /* two bytes read */
- snprintf(output, 5, "%c%c%c=",
- table64[obuf[0]],
- table64[obuf[1]],
- table64[obuf[2]]);
+ output[0] = table64[obuf[0]];
+ output[1] = table64[obuf[1]];
+ output[2] = table64[obuf[2]];
+ output[3] = '=';
break;
default:
- snprintf(output, 5, "%c%c%c%c",
- table64[obuf[0]],
- table64[obuf[1]],
- table64[obuf[2]],
- table64[obuf[3]]);
+ output[0] = table64[obuf[0]];
+ output[1] = table64[obuf[1]];
+ output[2] = table64[obuf[2]];
+ output[3] = table64[obuf[3]];
break;
}
output += 4;
@@ -427,13 +505,14 @@ libssh2_trace_sethandler(LIBSSH2_SESSION *session, void *handler_context,
}
void
-_libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
+_libssh2_debug_low(LIBSSH2_SESSION * session, int context, const char *format,
+ ...)
{
char buffer[1536];
int len, msglen, buflen = sizeof(buffer);
va_list vargs;
struct timeval now;
- static int firstsec;
+ static long firstsec;
static const char *const contexts[] = {
"Unknown",
"Transport",
@@ -463,7 +542,7 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
}
}
- _libssh2_gettimeofday(&now, NULL);
+ gettimeofday(&now, NULL);
if(!firstsec) {
firstsec = now.tv_sec;
}
@@ -494,8 +573,8 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...)
LIBSSH2_API int
libssh2_trace(LIBSSH2_SESSION * session, int bitmask)
{
- (void) session;
- (void) bitmask;
+ (void)session;
+ (void)bitmask;
return 0;
}
@@ -503,9 +582,9 @@ LIBSSH2_API int
libssh2_trace_sethandler(LIBSSH2_SESSION *session, void *handler_context,
libssh2_trace_handler_func callback)
{
- (void) session;
- (void) handler_context;
- (void) callback;
+ (void)session;
+ (void)handler_context;
+ (void)callback;
return 0;
}
#endif
@@ -602,10 +681,10 @@ void _libssh2_list_insert(struct list_node *after, /* insert before this */
#endif
-/* this define is defined in misc.h for the correct platforms */
-#ifdef LIBSSH2_GETTIMEOFDAY_WIN32
+/* Defined in libssh2_priv.h for the correct platforms */
+#ifdef LIBSSH2_GETTIMEOFDAY
/*
- * gettimeofday
+ * _libssh2_gettimeofday
* Implementation according to:
* The Open Group Base Specifications Issue 6
* IEEE Std 1003.1, 2004 Edition
@@ -626,27 +705,31 @@ void _libssh2_list_insert(struct list_node *after, /* insert before this */
* Danny Smith <dannysmith@users.sourceforge.net>
*/
-/* Offset between 1/1/1601 and 1/1/1970 in 100 nanosec units */
-#define _W32_FT_OFFSET (116444736000000000)
-
-int __cdecl _libssh2_gettimeofday(struct timeval *tp, void *tzp)
+int _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) {
+#ifdef WIN32
+ /* Offset between 1601-01-01 and 1970-01-01 in 100 nanosec units */
+ #define _WIN32_FT_OFFSET (116444736000000000)
+
+ union {
+ libssh2_uint64_t ns100; /* time since 1 Jan 1601 in 100ns units */
+ FILETIME ft;
+ } _now;
GetSystemTimeAsFileTime(&_now.ft);
tp->tv_usec = (long)((_now.ns100 / 10) % 1000000);
- tp->tv_sec = (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000);
+ tp->tv_sec = (long)((_now.ns100 - _WIN32_FT_OFFSET) / 10000000);
+#else
+ /* Platforms without a native implementation or local replacement */
+ tp->tv_usec = 0;
+ tp->tv_sec = 0;
+#endif
}
/* Always return 0 as per Open Group Base Specifications Issue 6.
Do not set errno on error. */
return 0;
}
-
-
#endif
void *_libssh2_calloc(LIBSSH2_SESSION* session, size_t size)
@@ -689,34 +772,23 @@ void _libssh2_aes_ctr_increment(unsigned char *ctr,
}
}
-#ifdef WIN32
-static void * (__cdecl * const volatile memset_libssh)(void *, int, size_t) =
- memset;
-#else
+#ifdef LIBSSH2_MEMZERO
static void * (* const volatile memset_libssh)(void *, int, size_t) = memset;
-#endif
-void _libssh2_explicit_zero(void *buf, size_t size)
+void _libssh2_memzero(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
}
+#endif
/* String buffer */
-struct string_buf* _libssh2_string_buf_new(LIBSSH2_SESSION *session)
+struct string_buf *_libssh2_string_buf_new(LIBSSH2_SESSION *session)
{
struct string_buf *ret;
ret = _libssh2_calloc(session, sizeof(*ret));
- if(ret == NULL)
+ if(!ret)
return NULL;
return ret;
@@ -724,16 +796,39 @@ struct string_buf* _libssh2_string_buf_new(LIBSSH2_SESSION *session)
void _libssh2_string_buf_free(LIBSSH2_SESSION *session, struct string_buf *buf)
{
- if(buf == NULL)
+ if(!buf)
return;
- if(buf->data != NULL)
+ if(buf->data)
LIBSSH2_FREE(session, buf->data);
LIBSSH2_FREE(session, buf);
buf = NULL;
}
+int _libssh2_get_byte(struct string_buf *buf, unsigned char *out)
+{
+ if(!_libssh2_check_length(buf, 1)) {
+ return -1;
+ }
+
+ *out = buf->dataptr[0];
+ buf->dataptr += 1;
+ return 0;
+}
+
+int _libssh2_get_boolean(struct string_buf *buf, unsigned char *out)
+{
+ if(!_libssh2_check_length(buf, 1)) {
+ return -1;
+ }
+
+
+ *out = buf->dataptr[0] == 0 ? 0 : 1;
+ buf->dataptr += 1;
+ return 0;
+}
+
int _libssh2_get_u32(struct string_buf *buf, uint32_t *out)
{
if(!_libssh2_check_length(buf, 4)) {
@@ -771,7 +866,7 @@ 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) {
+ if(!buf || _libssh2_get_u32(buf, &data_len) != 0) {
return -1;
}
if(!_libssh2_check_length(buf, data_len)) {
@@ -796,12 +891,18 @@ int _libssh2_copy_string(LIBSSH2_SESSION *session, struct string_buf *buf,
return -1;
}
- *outbuf = LIBSSH2_ALLOC(session, str_len);
- if(*outbuf) {
- memcpy(*outbuf, str, str_len);
+ if(str_len) {
+ *outbuf = LIBSSH2_ALLOC(session, str_len);
+ if(*outbuf) {
+ memcpy(*outbuf, str, str_len);
+ }
+ else {
+ return -1;
+ }
}
else {
- return -1;
+ *outlen = 0;
+ *outbuf = NULL;
}
if(outlen)
@@ -850,25 +951,11 @@ 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);
+ return (len <= left) && (left <= buf->len);
+}
+
+int _libssh2_eob(struct string_buf *buf)
+{
+ unsigned char *endp = &buf->data[buf->len];
+ return buf->dataptr >= endp;
}