diff --git a/ChangeLog.md b/ChangeLog.md index 9a9b99749..20a691263 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,33 @@ +### wolfSSH v1.4.0 (04/30/2019) + +- SFTP support for time attributes +- TCP port forwarding feature added (--enable-fwd) +- Example tcp port forwarding added to /examples/portfwd/portfwd +- Fixes to SCP, including default direction set +- Fix to match ID during KEX init +- Add check for window adjustment packets when sending large transfers +- Fixes and maintenance to Nucleus port for file closing +- Add enable all option (--enable-all) +- Fix for --disable-inline build +- Fixes for GCC-7 warnings when falling through switch statements +- Additional sanity checks added from fuzz testing +- Refactor and fixes for use with non blocking +- Add extended data read for piping stderr +- Add client side pseudo terminal connection with ./examples/client/client -t +- Add some basic Windows terminal conversions with wolfSSH_ConvertConsole +- Add wolfSSH_stream_peek function to peek at incoming SSH data +- Change name of internal function SendBuffered() to avoid clash with wolfSSL +- Add support for SFTP on Windows +- Use int types for arguments in examples to fix Raspberry Pi build +- Fix for fail case with leading 0’s on MPINT +- Default window size (DEFAULT_WINDOW_SZ) lowered from ~ 1 MB to ~ 16 KB +- Disable examples option added to configure (--disable-examples) +- Callback function and example use added for checking public key sent +- AES CTR cipher support added +- Fix for free’ing ECC caches with examples +- Renamed example SFTP to be examples/sftpclient/wolfsftp + + ### wolfSSH v1.3.0 (08/15/2018) - Accepted code submission from Stephen Casner for SCP support. Thanks Stephen! diff --git a/configure.ac b/configure.ac index 337cf99bd..8e1753ea7 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ # All right reserved. AC_COPYRIGHT([Copyright (C) 2014-2019 wolfSSL Inc.]) -AC_INIT([wolfssh],[1.3.1],[support@wolfssl.com],[wolfssh],[https://www.wolfssl.com]) +AC_INIT([wolfssh],[1.4.0],[support@wolfssl.com],[wolfssh],[https://www.wolfssl.com]) AC_PREREQ([2.63]) AC_CONFIG_AUX_DIR([build-aux]) @@ -20,7 +20,7 @@ AC_ARG_PROGRAM AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_HEADERS([src/config.h]) -WOLFSSH_LIBRARY_VERSION=7:0:2 +WOLFSSH_LIBRARY_VERSION=8:0:3 # | | | # +------+ | +---+ # | | | diff --git a/examples/echoserver/echoserver.c b/examples/echoserver/echoserver.c index a7a6e1876..9acad9f62 100644 --- a/examples/echoserver/echoserver.c +++ b/examples/echoserver/echoserver.c @@ -525,10 +525,16 @@ static int LoadPasswordBuffer(byte* buf, word32 bufSz, PwMapList* list) while (*str != 0) { delimiter = strchr(str, ':'); + if (delimiter == NULL) { + return -1; + } username = str; *delimiter = 0; password = delimiter + 1; str = strchr(password, '\n'); + if (str == NULL) { + return -1; + } *str = 0; str++; if (PwMapNew(list, WOLFSSH_USERAUTH_PASSWORD, @@ -566,13 +572,22 @@ static int LoadPublicKeyBuffer(byte* buf, word32 bufSz, PwMapList* list) while (*str != 0) { /* Skip the public key type. This example will always be ssh-rsa. */ delimiter = strchr(str, ' '); + if (delimiter == NULL) { + return -1; + } str = delimiter + 1; delimiter = strchr(str, ' '); + if (delimiter == NULL) { + return -1; + } publicKey64 = (byte*)str; *delimiter = 0; publicKey64Sz = (word32)(delimiter - str); str = delimiter + 1; delimiter = strchr(str, '\n'); + if (delimiter == NULL) { + return -1; + } username = (byte*)str; *delimiter = 0; usernameSz = (word32)(delimiter - str); diff --git a/examples/server/server.c b/examples/server/server.c index b5c1bcf81..84b609574 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -413,10 +413,16 @@ static int LoadPasswordBuffer(byte* buf, word32 bufSz, PwMapList* list) while (*str != 0) { delimiter = strchr(str, ':'); + if (delimiter == NULL) { + return -1; + } username = str; *delimiter = 0; password = delimiter + 1; str = strchr(password, '\n'); + if (str == NULL) { + return -1; + } *str = 0; str++; if (PwMapNew(list, WOLFSSH_USERAUTH_PASSWORD, @@ -454,13 +460,22 @@ static int LoadPublicKeyBuffer(byte* buf, word32 bufSz, PwMapList* list) while (*str != 0) { /* Skip the public key type. This example will always be ssh-rsa. */ delimiter = strchr(str, ' '); + if (delimiter == NULL) { + return -1; + } str = delimiter + 1; delimiter = strchr(str, ' '); + if (delimiter == NULL) { + return -1; + } publicKey64 = (byte*)str; *delimiter = 0; publicKey64Sz = (word32)(delimiter - str); str = delimiter + 1; delimiter = strchr(str, '\n'); + if (delimiter == NULL) { + return -1; + } username = (byte*)str; *delimiter = 0; usernameSz = (word32)(delimiter - str); diff --git a/examples/sftpclient/sftpclient.c b/examples/sftpclient/sftpclient.c index ae4a15691..98a7cdde7 100644 --- a/examples/sftpclient/sftpclient.c +++ b/examples/sftpclient/sftpclient.c @@ -1127,7 +1127,7 @@ THREAD_RETURN WOLFSSH_THREAD sftpclient_test(void* args) n = NULL; } - ret = doCmds(args); + ret = doCmds((func_args*)args); XFREE(workingDir, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (ret == WS_SUCCESS) { if (wolfSSH_shutdown(ssh) != WS_SUCCESS) { diff --git a/src/io.c b/src/io.c index 24ef4f5a2..a53d1b85a 100644 --- a/src/io.c +++ b/src/io.c @@ -113,8 +113,8 @@ void* wolfSSH_GetIOWriteCtx(WOLFSSH* ssh) /* lwIP needs to be configured to use sockets API in this mode */ /* LWIP_SOCKET 1 in lwip/opt.h or in build */ #include "lwip/sockets.h" - #include #ifndef LWIP_PROVIDE_ERRNO + #include #define LWIP_PROVIDE_ERRNO 1 #endif #elif defined(FREESCALE_MQX) diff --git a/src/wolfscp.c b/src/wolfscp.c index 97428bf5b..3b8ccd07b 100644 --- a/src/wolfscp.c +++ b/src/wolfscp.c @@ -2178,6 +2178,11 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest, } ret = FindNextDirEntry(sendCtx); + + /* help out static analysis tool */ + if (ret != WS_BAD_ARGUMENT && sendCtx == NULL) + ret = WS_BAD_ARGUMENT; + if (ret == WS_SUCCESS || ret == WS_NEXT_ERROR) { #ifdef WOLFSSL_NUCLEUS diff --git a/src/wolfsftp.c b/src/wolfsftp.c index 576341853..6589f8b14 100644 --- a/src/wolfsftp.c +++ b/src/wolfsftp.c @@ -940,6 +940,7 @@ static int wolfSSH_SFTP_RecvRealPath(WOLFSSH* ssh, int reqId, byte* data, WFREE(out, ssh->ctx->heap, DYNTYPE_BUFFER); return WS_FATAL_ERROR; } + /* take over control of buffer */ wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); return WS_BAD_FILE_E; } @@ -1164,6 +1165,7 @@ int wolfSSH_SFTP_read(WOLFSSH* ssh) "Unknown/Unsupported packet type", "English", state->data, (word32*)&state->sz); if (ret == WS_SUCCESS) { + /* set send out buffer, "state->data" is taken by ssh */ wolfSSH_SFTP_RecvSetSend(ssh, state->data, state->sz); } } @@ -1371,6 +1373,8 @@ int wolfSSH_SFTP_RecvRMDIR(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) WFREE(out, ssh->ctx->heap, DYNTYPE_BUFFER); return WS_FATAL_ERROR; } + + /* set send out buffer, "out" is taken by ssh */ wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); return ret; } @@ -1416,11 +1420,13 @@ int wolfSSH_SFTP_RecvMKDIR(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) dir[sz] = '\0'; idx += sz; if (idx + UINT32_SZ > maxSz) { + WFREE(dir, ssh->ctx->heap, DYNTYPE_BUFFER); return WS_BUFFER_E; } ato32(data + idx, &sz); idx += UINT32_SZ; if (idx + sz > maxSz) { + WFREE(dir, ssh->ctx->heap, DYNTYPE_BUFFER); return WS_BUFFER_E; } if (sz != UINT32_SZ) { @@ -1463,6 +1469,8 @@ int wolfSSH_SFTP_RecvMKDIR(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) WFREE(out, ssh->ctx->heap, DYNTYPE_BUFFER); return WS_FATAL_ERROR; } + + /* set send out buffer, "out" is taken by ssh */ wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); return ret; } @@ -1598,6 +1606,8 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) return WS_FATAL_ERROR; } } + + /* set send out buffer, "out" is taken by ssh */ wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); (void)ier; @@ -1725,6 +1735,8 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) return WS_FATAL_ERROR; } } + + /* set send out buffer, "out" is taken by ssh */ wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); (void)ier; @@ -1848,6 +1860,8 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) return WS_FATAL_ERROR; } } + + /* set send out buffer, "out" is taken by ssh */ wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); return ret; @@ -1951,6 +1965,8 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) return WS_FATAL_ERROR; } } + + /* set send out buffer, "out" is taken by ssh */ wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); return ret; @@ -2397,6 +2413,8 @@ int wolfSSH_SFTP_RecvReadDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) WFREE(out, ssh->ctx->heap, DYNTYPE_BUFFER); return WS_FATAL_ERROR; } + + /* set send out buffer, "out" is taken by ssh */ wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); return WS_SUCCESS; } @@ -2415,6 +2433,8 @@ int wolfSSH_SFTP_RecvReadDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) return WS_FATAL_ERROR; } wolfSSH_SFTPNAME_list_free(list); + + /* set send out buffer, "out" is taken by ssh */ wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); return WS_SUCCESS; } @@ -2562,6 +2582,8 @@ int wolfSSH_SFTP_RecvWrite(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) WFREE(out, ssh->ctx->heap, DYNTYPE_BUFFER); return WS_FATAL_ERROR; } + + /* set send out buffer, "out" is taken by ssh */ wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); return ret; } @@ -2640,6 +2662,8 @@ int wolfSSH_SFTP_RecvWrite(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) WFREE(out, ssh->ctx->heap, DYNTYPE_BUFFER); return WS_FATAL_ERROR; } + + /* set send out buffer, "out" is taken by ssh */ wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); return ret; } @@ -2718,6 +2742,7 @@ int wolfSSH_SFTP_RecvRead(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) if (res != NULL) { if (wolfSSH_SFTP_CreateStatus(ssh, type, reqId, res, "English", NULL, &outSz) != WS_SIZE_ONLY) { + WFREE(out, ssh->ctx->heap, DYNTYPE_BUFFER); return WS_FATAL_ERROR; } if (outSz > sz) { @@ -2738,6 +2763,7 @@ int wolfSSH_SFTP_RecvRead(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) SFTP_CreatePacket(ssh, WOLFSSH_FTP_DATA, out, outSz, NULL, 0); } + /* set send out buffer, "out" is taken by ssh */ wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); return ret; } @@ -2844,6 +2870,7 @@ int wolfSSH_SFTP_RecvRead(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) SFTP_CreatePacket(ssh, WOLFSSH_FTP_DATA, out, outSz, NULL, 0); } + /* set send out buffer, "out" is taken by ssh */ wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); return ret; } @@ -2932,6 +2959,8 @@ int wolfSSH_SFTP_RecvClose(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) WFREE(out, ssh->ctx->heap, DYNTYPE_BUFFER); return WS_FATAL_ERROR; } + + /* set send out buffer, "out" is taken by ssh */ wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); return ret; } @@ -3012,6 +3041,8 @@ int wolfSSH_SFTP_RecvClose(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) WFREE(out, ssh->ctx->heap, DYNTYPE_BUFFER); return WS_FATAL_ERROR; } + + /* set send out buffer, "out" is taken by ssh */ wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); return ret; } @@ -3100,6 +3131,8 @@ int wolfSSH_SFTP_RecvRemove(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) WFREE(out, ssh->ctx->heap, DYNTYPE_BUFFER); return WS_FATAL_ERROR; } + + /* set send out buffer, "out" is taken by ssh */ wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); return ret; } @@ -3194,6 +3227,8 @@ int wolfSSH_SFTP_RecvRename(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) WFREE(out, ssh->ctx->heap, DYNTYPE_BUFFER); return WS_FATAL_ERROR; } + + /* set send out buffer, "out" is taken by ssh */ wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); return ret; } @@ -3675,6 +3710,8 @@ int wolfSSH_SFTP_RecvFSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) return WS_FATAL_ERROR; } } + + /* set send out buffer, "out" is taken by ssh */ wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); return ret; } @@ -3722,6 +3759,7 @@ int wolfSSH_SFTP_RecvSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) WLOG(WS_LOG_SFTP, "Unable to get stat of file/directory"); if (wolfSSH_SFTP_CreateStatus(ssh, WOLFSSH_FTP_FAILURE, reqId, "STAT error", "English", NULL, &outSz) != WS_SIZE_ONLY) { + WFREE(name, ssh->ctx->heap, DYNTYPE_BUFFER); return WS_FATAL_ERROR; } ret = WS_BAD_FILE_E; @@ -3752,6 +3790,7 @@ int wolfSSH_SFTP_RecvSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) SFTP_SetAttributes(ssh, out + WOLFSSH_SFTP_HEADER, sz, &atr); } + /* set send out buffer, "out" is taken by ssh */ wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); return ret; } @@ -3800,6 +3839,7 @@ int wolfSSH_SFTP_RecvLSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) WLOG(WS_LOG_SFTP, "Unable to get lstat of file/directory"); if (wolfSSH_SFTP_CreateStatus(ssh, WOLFSSH_FTP_FAILURE, reqId, "LSTAT error", "English", NULL, &outSz) != WS_SIZE_ONLY) { + WFREE(name, ssh->ctx->heap, DYNTYPE_BUFFER); return WS_FATAL_ERROR; } ret = WS_BAD_FILE_E; @@ -3830,6 +3870,7 @@ int wolfSSH_SFTP_RecvLSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) SFTP_SetAttributes(ssh, out + WOLFSSH_SFTP_HEADER, sz, &atr); } + /* set send out buffer, "out" is taken by ssh */ wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); return ret; } @@ -3960,6 +4001,8 @@ int wolfSSH_SFTP_RecvSetSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) WFREE(out, ssh->ctx->heap, DYNTYPE_BUFFER); return WS_FATAL_ERROR; } + + /* set send out buffer, "out" is taken by ssh */ wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); return ret; } diff --git a/wolfssh/version.h b/wolfssh/version.h index 7ed1aff68..3f9ee40fb 100644 --- a/wolfssh/version.h +++ b/wolfssh/version.h @@ -33,8 +33,8 @@ extern "C" { #endif -#define LIBWOLFSSH_VERSION_STRING "1.3.1" -#define LIBWOLFSSH_VERSION_HEX 0x01003001 +#define LIBWOLFSSH_VERSION_STRING "1.4.0" +#define LIBWOLFSSH_VERSION_HEX 0x01004000 #ifdef __cplusplus }