mirror of https://github.com/wolfSSL/wolfssh.git
Run threaded api-test SFTP/SCP tests on Windows
parent
53047bd8c7
commit
5acbeaeaee
|
|
@ -139,12 +139,13 @@ jobs:
|
|||
run: nuget restore ${{env.WOLFSSL_SOLUTION_FILE_PATH}}
|
||||
|
||||
# These env paths already include the wolfssh/ and wolfssl/ checkout
|
||||
# prefixes, so they must run from the workspace root (as the build job does).
|
||||
- name: updated user_settings.h for sshd and x509
|
||||
run: cp ${{env.USER_SETTINGS_H_NEW}} ${{env.USER_SETTINGS_H}}
|
||||
|
||||
- name: replace wolfSSL user_settings.h with wolfSSH user_settings.h
|
||||
run: get-content ${{env.USER_SETTINGS_H_NEW}} | %{$_ -replace "if 0","if 1"}
|
||||
# prefixes, so this runs from the default working directory, the workspace
|
||||
# root.
|
||||
- name: Enable wolfSSH options (sshd, sftp, x509) in user_settings.h
|
||||
shell: bash
|
||||
run: |
|
||||
sed -i 's/#if 0/#if 1/g' ${{env.USER_SETTINGS_H_NEW}}
|
||||
cp ${{env.USER_SETTINGS_H_NEW}} ${{env.USER_SETTINGS_H}}
|
||||
|
||||
# WholeProgramOptimization=false disables /GL so the v142-independent objects
|
||||
# link without a cross-version code-generation requirement (C1047).
|
||||
|
|
|
|||
|
|
@ -2249,6 +2249,11 @@ static int LoadPasswdList(StrList* strList, PwMapList* mapList)
|
|||
int count = 0;
|
||||
|
||||
while (strList) {
|
||||
if (WSTRLEN(strList->str) >= sizeof names - 1) {
|
||||
fprintf(stderr, "Ignoring over-long entry: %.32s\n", strList->str);
|
||||
strList = strList->next;
|
||||
continue;
|
||||
}
|
||||
WSTRNCPY(names, strList->str, sizeof names - 1);
|
||||
passwd = WSTRCHR(names, ':');
|
||||
if (passwd != NULL) {
|
||||
|
|
@ -2278,6 +2283,11 @@ static int LoadKeyboardList(StrList* strList, PwMapList* mapList,
|
|||
int count = 0;
|
||||
|
||||
while (strList) {
|
||||
if (WSTRLEN(strList->str) >= sizeof names - 1) {
|
||||
fprintf(stderr, "Ignoring over-long entry: %.32s\n", strList->str);
|
||||
strList = strList->next;
|
||||
continue;
|
||||
}
|
||||
WSTRNCPY(names, strList->str, sizeof names - 1);
|
||||
passwd = WSTRCHR(names, ':');
|
||||
if (passwd != NULL) {
|
||||
|
|
@ -2314,6 +2324,11 @@ static int LoadPubKeyList(StrList* strList, int format, PwMapList* mapList)
|
|||
buf = NULL;
|
||||
bufSz = 0;
|
||||
|
||||
if (WSTRLEN(strList->str) >= sizeof names - 1) {
|
||||
fprintf(stderr, "Ignoring over-long entry: %.32s\n", strList->str);
|
||||
strList = strList->next;
|
||||
continue;
|
||||
}
|
||||
WSTRNCPY(names, strList->str, sizeof names - 1);
|
||||
fileName = WSTRCHR(names, ':');
|
||||
if (fileName != NULL) {
|
||||
|
|
@ -2834,6 +2849,12 @@ static INLINE void SignalTcpReady(tcp_ready* ready, word16 port)
|
|||
ready->port = port;
|
||||
pthread_cond_signal(&ready->cond);
|
||||
pthread_mutex_unlock(&ready->mutex);
|
||||
#elif defined(USE_WINDOWS_API) && defined(NO_MAIN_DRIVER) && \
|
||||
!defined(SINGLE_THREADED)
|
||||
ready->ready = 1;
|
||||
ready->port = port;
|
||||
/* SetEvent is a full barrier; this one-shot signal needs no lock */
|
||||
SetEvent(ready->readyEvent);
|
||||
#else
|
||||
WOLFSSH_UNUSED(ready);
|
||||
WOLFSSH_UNUSED(port);
|
||||
|
|
@ -2979,7 +3000,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
|
|||
}
|
||||
else {
|
||||
port = (word16)atoi(myoptarg);
|
||||
#if !defined(NO_MAIN_DRIVER) || defined(USE_WINDOWS_API)
|
||||
#if !defined(NO_MAIN_DRIVER)
|
||||
if (port == 0) {
|
||||
ES_ERROR("port number cannot be 0");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,6 +156,7 @@ static void myStatusCb(WOLFSSH* sshIn, word32* bytes, char* name)
|
|||
static word32 lastOutputTime = 0;
|
||||
static word32 lastPrintedBytes[2] = {0, 0};
|
||||
word32 elapsedTime;
|
||||
word32 nameSz;
|
||||
#endif
|
||||
char buf[80];
|
||||
word64 longBytes = ((word64)bytes[1] << 32) | bytes[0];
|
||||
|
|
@ -176,13 +177,19 @@ static void myStatusCb(WOLFSSH* sshIn, word32* bytes, char* name)
|
|||
}
|
||||
lastPrintedBytes[0] = bytes[0];
|
||||
lastPrintedBytes[1] = bytes[1];
|
||||
if (WSTRNCMP(currentFile, name, WSTRLEN(name)) != 0) {
|
||||
/* clamp over-long names: currentFile holds the truncated prefix, so the
|
||||
* comparison must use the same bound or every call looks like a new file */
|
||||
nameSz = (word32)WSTRLEN(name);
|
||||
if (nameSz >= sizeof(currentFile))
|
||||
nameSz = (word32)sizeof(currentFile) - 1;
|
||||
if (WSTRNCMP(currentFile, name, nameSz) != 0 ||
|
||||
currentFile[nameSz] != '\0') {
|
||||
startTime = current_time(1);
|
||||
lastOutputTime = 0; /* Reset timer for new file transfer */
|
||||
lastPrintedBytes[0] = 0;
|
||||
lastPrintedBytes[1] = 0;
|
||||
WMEMSET(currentFile, 0, WOLFSSH_MAX_FILENAME);
|
||||
WSTRNCPY(currentFile, name, WOLFSSH_MAX_FILENAME);
|
||||
WMEMSET(currentFile, 0, sizeof(currentFile));
|
||||
WMEMCPY(currentFile, name, nameSz);
|
||||
}
|
||||
elapsedTime = currentTime - startTime;
|
||||
WSNPRINTF(buf, sizeof(buf), "Processed %8llu\t bytes in %d seconds\r",
|
||||
|
|
@ -191,7 +198,7 @@ static void myStatusCb(WOLFSSH* sshIn, word32* bytes, char* name)
|
|||
if (elapsedTime > TIMEOUT_VALUE) {
|
||||
WSNPRINTF(buf, sizeof(buf), "\nProcess timed out at %d seconds, "
|
||||
"stopping\r", elapsedTime);
|
||||
WMEMSET(currentFile, 0, WOLFSSH_MAX_FILENAME);
|
||||
WMEMSET(currentFile, 0, sizeof(currentFile));
|
||||
wolfSSH_SFTP_Interrupt(ssh);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -667,7 +674,7 @@ static int doCmds(func_args* args)
|
|||
ret == WS_CHAN_RXD || ret == WS_REKEYING);
|
||||
|
||||
#ifndef WOLFSSH_NO_TIMESTAMP
|
||||
WMEMSET(currentFile, 0, WOLFSSH_MAX_FILENAME);
|
||||
WMEMSET(currentFile, 0, sizeof(currentFile));
|
||||
#endif
|
||||
|
||||
if (ret != WS_SUCCESS) {
|
||||
|
|
@ -778,7 +785,7 @@ static int doCmds(func_args* args)
|
|||
ret == WS_CHAN_RXD || ret == WS_REKEYING);
|
||||
|
||||
#ifndef WOLFSSH_NO_TIMESTAMP
|
||||
WMEMSET(currentFile, 0, WOLFSSH_MAX_FILENAME);
|
||||
WMEMSET(currentFile, 0, sizeof(currentFile));
|
||||
#endif
|
||||
|
||||
if (ret != WS_SUCCESS) {
|
||||
|
|
@ -1445,6 +1452,7 @@ static int doAutopilot(int cmd, char* local, char* remote)
|
|||
int ret = WS_SUCCESS;
|
||||
char fullpath[128] = ".";
|
||||
WS_SFTPNAME* name = NULL;
|
||||
word32 remoteSz;
|
||||
byte remoteAbsPath = 0;
|
||||
|
||||
/* check if is absolute path before making it one */
|
||||
|
|
@ -1462,8 +1470,11 @@ static int doAutopilot(int cmd, char* local, char* remote)
|
|||
|
||||
if (remoteAbsPath) {
|
||||
/* use remote absolute path if provided */
|
||||
remoteSz = (word32)WSTRLEN(remote);
|
||||
if (remoteSz >= sizeof(fullpath))
|
||||
return WS_BUFFER_E;
|
||||
WMEMSET(fullpath, 0, sizeof(fullpath));
|
||||
WSTRNCPY(fullpath, remote, sizeof(fullpath) - 1);
|
||||
WMEMCPY(fullpath, remote, remoteSz + 1);
|
||||
}
|
||||
else {
|
||||
err = doBuildRemotePath(remote, fullpath, sizeof(fullpath), &name);
|
||||
|
|
|
|||
|
|
@ -1952,12 +1952,19 @@ int wolfSSH_SCP_connect(WOLFSSH* ssh, byte* cmd)
|
|||
}
|
||||
|
||||
|
||||
/* Shared format so the size probe and the write cannot drift. */
|
||||
#define SCP_CMD_FMT "scp -%c %s"
|
||||
|
||||
static char* MakeScpCmd(const char* name, char dir, void* heap)
|
||||
{
|
||||
char* cmd;
|
||||
int sz;
|
||||
|
||||
sz = WSNPRINTF(NULL, 0, "scp -%c %s", dir, name) + 1;
|
||||
#ifdef USE_WINDOWS_API
|
||||
sz = WSCPRINTF(SCP_CMD_FMT, dir, name) + 1;
|
||||
#else
|
||||
sz = WSNPRINTF(NULL, 0, SCP_CMD_FMT, dir, name) + 1;
|
||||
#endif
|
||||
if (sz <= 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -1965,7 +1972,7 @@ static char* MakeScpCmd(const char* name, char dir, void* heap)
|
|||
if (cmd == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
sz = WSNPRINTF(cmd, sz, "scp -%c %s", dir, name);
|
||||
sz = WSNPRINTF(cmd, sz, SCP_CMD_FMT, dir, name);
|
||||
if (sz <= 0) {
|
||||
WFREE(cmd, heap, DYNTYPE_STRING);
|
||||
return NULL;
|
||||
|
|
@ -2717,10 +2724,15 @@ static ScpDir* ScpNewDir(void *fs, const char* path, void* heap)
|
|||
int ScpPushDir(void *fs, ScpSendCtx* ctx, const char* path, void* heap)
|
||||
{
|
||||
ScpDir* entry;
|
||||
word32 pathSz;
|
||||
|
||||
if (ctx == NULL || path == NULL)
|
||||
return WS_BAD_ARGUMENT;
|
||||
|
||||
pathSz = (word32)WSTRLEN(path);
|
||||
if (pathSz >= sizeof(ctx->dirName))
|
||||
return WS_BUFFER_E;
|
||||
|
||||
entry = ScpNewDir(fs, path, heap);
|
||||
if (entry == NULL) {
|
||||
return WS_FATAL_ERROR;
|
||||
|
|
@ -2734,13 +2746,28 @@ int ScpPushDir(void *fs, ScpSendCtx* ctx, const char* path, void* heap)
|
|||
ctx->currentDir = entry;
|
||||
}
|
||||
|
||||
/* append directory name to ctx->dirName */
|
||||
WSTRNCPY(ctx->dirName, path, DEFAULT_SCP_FILE_NAME_SZ-1);
|
||||
ctx->dirName[DEFAULT_SCP_FILE_NAME_SZ-1] = '\0';
|
||||
/* append directory name to ctx->dirName, terminator included; the guard
|
||||
* above bounds pathSz so the copy always fits */
|
||||
WMEMCPY(ctx->dirName, path, pathSz + 1);
|
||||
|
||||
return WS_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef WOLFSSH_TEST_INTERNAL
|
||||
int wolfSSH_TestScpPushDir(const char* path)
|
||||
{
|
||||
ScpSendCtx ctx;
|
||||
int ret;
|
||||
|
||||
WMEMSET(&ctx, 0, sizeof(ctx));
|
||||
ret = ScpPushDir(NULL, &ctx, path, NULL);
|
||||
if (ret == WS_SUCCESS)
|
||||
ScpSendCtxFreeDirs(NULL, &ctx, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* WOLFSSH_TEST_INTERNAL */
|
||||
|
||||
/* Remove top ScpDir from directory stack, remove dir from ctx->dirName */
|
||||
int ScpPopDir(void *fs, ScpSendCtx* ctx, void* heap)
|
||||
{
|
||||
|
|
|
|||
60
tests/api.c
60
tests/api.c
|
|
@ -1687,6 +1687,20 @@ static void test_wolfSSH_agent_signrequest_success(void)
|
|||
#if defined(WOLFSSH_SFTP) && !defined(NO_WOLFSSH_CLIENT) && \
|
||||
!defined(SINGLE_THREADED)
|
||||
|
||||
/* A peer gone at shutdown is not a failure: the send path returns the reset,
|
||||
* the recv path returns generic WS_ERROR with the code in wolfSSH_get_error.
|
||||
* WS_SOCKET_ERROR_E is generic, so a real shutdown failure is tolerated too. */
|
||||
static int AbsorbBenignReset(WOLFSSH* ssh, int ret)
|
||||
{
|
||||
if (ret == WS_SOCKET_ERROR_E ||
|
||||
(ret == WS_ERROR &&
|
||||
wolfSSH_get_error(ssh) == WS_SOCKET_ERROR_E)) {
|
||||
ret = WS_SUCCESS;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
byte userPassword[256];
|
||||
|
||||
static int sftpUserAuth(byte authType, WS_UserAuthData* authData, void* ctx)
|
||||
|
|
@ -1820,10 +1834,8 @@ static void test_wolfSSH_SFTP_SendReadPacket(void)
|
|||
argsCount = 0;
|
||||
args[argsCount++] = ".";
|
||||
args[argsCount++] = "-1";
|
||||
#ifndef USE_WINDOWS_API
|
||||
args[argsCount++] = "-p";
|
||||
args[argsCount++] = "0";
|
||||
#endif
|
||||
ser.argv = (char**)args;
|
||||
ser.argc = argsCount;
|
||||
ser.signal = &ready;
|
||||
|
|
@ -2004,11 +2016,7 @@ static void test_wolfSSH_SFTP_SendReadPacket(void)
|
|||
wolfSSH_worker(ssh, NULL);
|
||||
}
|
||||
|
||||
argsCount = wolfSSH_shutdown(ssh);
|
||||
if (argsCount == WS_SOCKET_ERROR_E) {
|
||||
/* If the socket is closed on shutdown, peer is gone, this is OK. */
|
||||
argsCount = WS_SUCCESS;
|
||||
}
|
||||
argsCount = AbsorbBenignReset(ssh, wolfSSH_shutdown(ssh));
|
||||
|
||||
#if DEFAULT_HIGHWATER_MARK < 8000
|
||||
if (argsCount == WS_REKEYING) {
|
||||
|
|
@ -2030,6 +2038,7 @@ static void test_wolfSSH_SFTP_SendReadPacket(void)
|
|||
k_sleep(Z_TIMEOUT_TICKS(100));
|
||||
#endif
|
||||
ThreadJoin(serThread);
|
||||
FreeTcpReady(&ready);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2090,10 +2099,8 @@ static void test_wolfSSH_SFTP_PartialSend(void)
|
|||
argsCount = 0;
|
||||
args[argsCount++] = ".";
|
||||
args[argsCount++] = "-1";
|
||||
#ifndef USE_WINDOWS_API
|
||||
args[argsCount++] = "-p";
|
||||
args[argsCount++] = "0";
|
||||
#endif
|
||||
ser.argv = (char**)args;
|
||||
ser.argc = argsCount;
|
||||
ser.signal = &ready;
|
||||
|
|
@ -2279,10 +2286,7 @@ static void test_wolfSSH_SFTP_PartialSend(void)
|
|||
wolfSSH_worker(ssh, NULL);
|
||||
}
|
||||
|
||||
argsCount = wolfSSH_shutdown(ssh);
|
||||
if (argsCount == WS_SOCKET_ERROR_E) {
|
||||
argsCount = WS_SUCCESS;
|
||||
}
|
||||
argsCount = AbsorbBenignReset(ssh, wolfSSH_shutdown(ssh));
|
||||
#if DEFAULT_HIGHWATER_MARK < 8000
|
||||
if (argsCount == WS_REKEYING) {
|
||||
argsCount = WS_SUCCESS;
|
||||
|
|
@ -2299,6 +2303,7 @@ static void test_wolfSSH_SFTP_PartialSend(void)
|
|||
k_sleep(Z_TIMEOUT_TICKS(100));
|
||||
#endif
|
||||
ThreadJoin(serThread);
|
||||
FreeTcpReady(&ready);
|
||||
#endif /* WOLFSSH_TEST_INTERNAL */
|
||||
}
|
||||
|
||||
|
|
@ -2330,10 +2335,8 @@ static void sftp_rekey_test(int nonBlock)
|
|||
argsCount = 0;
|
||||
args[argsCount++] = ".";
|
||||
args[argsCount++] = "-1";
|
||||
#ifndef USE_WINDOWS_API
|
||||
args[argsCount++] = "-p";
|
||||
args[argsCount++] = "0";
|
||||
#endif
|
||||
ser.argv = (char**)args;
|
||||
ser.argc = argsCount;
|
||||
ser.signal = &ready;
|
||||
|
|
@ -2417,9 +2420,7 @@ static void sftp_rekey_test(int nonBlock)
|
|||
* before the WS_REKEYING fixup below could otherwise mask it. The loop cap
|
||||
* is one above the assert threshold to leave last-iteration headroom. */
|
||||
AssertIntLE(tries, SFTP_REKEY_MAX_TRIES);
|
||||
if (argsCount == WS_SOCKET_ERROR_E) {
|
||||
argsCount = WS_SUCCESS;
|
||||
}
|
||||
argsCount = AbsorbBenignReset(ssh, argsCount);
|
||||
#if DEFAULT_HIGHWATER_MARK < 8000
|
||||
if (argsCount == WS_REKEYING) {
|
||||
/* in cases where highwater mark is really small a re-key could happen */
|
||||
|
|
@ -2437,6 +2438,7 @@ static void sftp_rekey_test(int nonBlock)
|
|||
k_sleep(Z_TIMEOUT_TICKS(100));
|
||||
#endif
|
||||
ThreadJoin(serThread);
|
||||
FreeTcpReady(&ready);
|
||||
}
|
||||
|
||||
static void test_wolfSSH_SFTP_ReKey(void)
|
||||
|
|
@ -2615,10 +2617,8 @@ static void test_wolfSSH_SFTP_Confinement(void)
|
|||
argsCount = 0;
|
||||
args[argsCount++] = ".";
|
||||
args[argsCount++] = "-1";
|
||||
#ifndef USE_WINDOWS_API
|
||||
args[argsCount++] = "-p";
|
||||
args[argsCount++] = "0";
|
||||
#endif
|
||||
ser.argv = (char**)args;
|
||||
ser.argc = argsCount;
|
||||
ser.signal = &ready;
|
||||
|
|
@ -2791,10 +2791,7 @@ static void test_wolfSSH_SFTP_Confinement(void)
|
|||
while (wolfSSH_get_error(ssh) == WS_REKEYING)
|
||||
wolfSSH_worker(ssh, NULL);
|
||||
|
||||
ret = wolfSSH_shutdown(ssh);
|
||||
if (ret == WS_SOCKET_ERROR_E) {
|
||||
ret = WS_SUCCESS;
|
||||
}
|
||||
ret = AbsorbBenignReset(ssh, wolfSSH_shutdown(ssh));
|
||||
#if DEFAULT_HIGHWATER_MARK < 8000
|
||||
if (ret == WS_REKEYING) {
|
||||
ret = WS_SUCCESS;
|
||||
|
|
@ -2809,6 +2806,7 @@ static void test_wolfSSH_SFTP_Confinement(void)
|
|||
k_sleep(Z_TIMEOUT_TICKS(100));
|
||||
#endif
|
||||
ThreadJoin(serThread);
|
||||
FreeTcpReady(&ready);
|
||||
|
||||
/* remove staged targets; escMkdir/escDest only exist if confinement
|
||||
* leaked, and inJailDir only if the positive-case RMDIR did not run, so
|
||||
|
|
@ -3184,10 +3182,8 @@ static void scp_rekey_test(int nonBlock, int toServer)
|
|||
argsCount = 0;
|
||||
args[argsCount++] = ".";
|
||||
args[argsCount++] = "-1";
|
||||
#ifndef USE_WINDOWS_API
|
||||
args[argsCount++] = "-p";
|
||||
args[argsCount++] = "0";
|
||||
#endif
|
||||
ser.argv = (char**)args;
|
||||
ser.argc = argsCount;
|
||||
ser.signal = &ready;
|
||||
|
|
@ -3282,6 +3278,7 @@ static void scp_rekey_test(int nonBlock, int toServer)
|
|||
wolfSSH_free(ssh);
|
||||
wolfSSH_CTX_free(ctx);
|
||||
ThreadJoin(serThread);
|
||||
FreeTcpReady(&ready);
|
||||
|
||||
/* verify the transferred file matches the source once the server is done */
|
||||
AssertIntEQ(scpFilesMatch(verifyName, fileData, SCP_REKEY_FILE_SZ), 0);
|
||||
|
|
@ -4035,10 +4032,8 @@ static void test_wolfSSH_KeyboardInteractive(void)
|
|||
args[argsCount++] = "-1";
|
||||
args[argsCount++] = "-i";
|
||||
args[argsCount++] = "test:test";
|
||||
#ifndef USE_WINDOWS_API
|
||||
args[argsCount++] = "-p";
|
||||
args[argsCount++] = "0";
|
||||
#endif
|
||||
ser.argv = (char**)args;
|
||||
ser.argc = argsCount;
|
||||
ser.signal = &ready;
|
||||
|
|
@ -4051,11 +4046,7 @@ static void test_wolfSSH_KeyboardInteractive(void)
|
|||
AssertNotNull(ssh);
|
||||
|
||||
|
||||
argsCount = wolfSSH_shutdown(ssh);
|
||||
if (argsCount == WS_SOCKET_ERROR_E) {
|
||||
/* If the socket is closed on shutdown, peer is gone, this is OK. */
|
||||
argsCount = WS_SUCCESS;
|
||||
}
|
||||
argsCount = AbsorbBenignReset(ssh, wolfSSH_shutdown(ssh));
|
||||
|
||||
#if DEFAULT_HIGHWATER_MARK < 8000
|
||||
if (argsCount == WS_REKEYING) {
|
||||
|
|
@ -4077,6 +4068,7 @@ static void test_wolfSSH_KeyboardInteractive(void)
|
|||
k_sleep(Z_TIMEOUT_TICKS(100));
|
||||
#endif
|
||||
ThreadJoin(serThread);
|
||||
FreeTcpReady(&ready);
|
||||
}
|
||||
|
||||
#else /* WOLFSSH_SFTP && !NO_WOLFSSH_CLIENT && !SINGLE_THREADED */
|
||||
|
|
@ -4095,6 +4087,8 @@ int wolfSSH_ApiTest(int argc, char** argv)
|
|||
#ifdef WOLFSSH_TEST_BLOCK
|
||||
return 77;
|
||||
#else
|
||||
WSTARTTCP();
|
||||
|
||||
AssertIntEQ(wolfSSH_Init(), WS_SUCCESS);
|
||||
|
||||
#if defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,2)
|
||||
|
|
|
|||
|
|
@ -1836,6 +1836,7 @@ static void test_client(void)
|
|||
if (!unbalanced) {
|
||||
AssertIntEQ(serverArgs.return_code, WS_SUCCESS);
|
||||
}
|
||||
FreeTcpReady(&ready);
|
||||
}
|
||||
|
||||
static void test_basic_KeyboardInteractive(void)
|
||||
|
|
|
|||
41
tests/unit.c
41
tests/unit.c
|
|
@ -8875,6 +8875,39 @@ static int test_ScpExtractFileName(void)
|
|||
}
|
||||
#endif /* WOLFSSH_TEST_INTERNAL && WOLFSSH_SCP && !WOLFSSH_SCP_USER_CALLBACKS */
|
||||
|
||||
#if defined(WOLFSSH_TEST_INTERNAL) && defined(WOLFSSH_SCP) && \
|
||||
!defined(WOLFSSH_SCP_USER_CALLBACKS) && !defined(NO_FILESYSTEM)
|
||||
/* ScpPushDir bounds the request path against ctx->dirName before copying it.
|
||||
* The accept side stops short of WS_SUCCESS because no directory that long
|
||||
* exists to open, so it asserts the guard did not fire rather than success. */
|
||||
static int test_ScpPushDir(void)
|
||||
{
|
||||
char path[DEFAULT_SCP_FILE_NAME_SZ + 1];
|
||||
int ret;
|
||||
|
||||
/* one byte too long for ctx->dirName: rejected before anything is opened */
|
||||
WMEMSET(path, 'a', DEFAULT_SCP_FILE_NAME_SZ);
|
||||
path[DEFAULT_SCP_FILE_NAME_SZ] = '\0';
|
||||
ret = wolfSSH_TestScpPushDir(path);
|
||||
if (ret != WS_BUFFER_E)
|
||||
return -913;
|
||||
|
||||
/* exact fit clears the length guard and fails at the open instead */
|
||||
path[DEFAULT_SCP_FILE_NAME_SZ - 1] = '\0';
|
||||
ret = wolfSSH_TestScpPushDir(path);
|
||||
if (ret == WS_BUFFER_E)
|
||||
return -914;
|
||||
|
||||
/* NULL path is rejected */
|
||||
ret = wolfSSH_TestScpPushDir(NULL);
|
||||
if (ret != WS_BAD_ARGUMENT)
|
||||
return -915;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* WOLFSSH_TEST_INTERNAL && WOLFSSH_SCP &&
|
||||
* !WOLFSSH_SCP_USER_CALLBACKS && !NO_FILESYSTEM */
|
||||
|
||||
#endif /* WOLFSSH_TEST_INTERNAL */
|
||||
|
||||
/* Error Code And Message Test */
|
||||
|
|
@ -9497,6 +9530,14 @@ int wolfSSH_UnitTest(int argc, char** argv)
|
|||
testResult = testResult || unitResult;
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSH_TEST_INTERNAL) && defined(WOLFSSH_SCP) && \
|
||||
!defined(WOLFSSH_SCP_USER_CALLBACKS) && !defined(NO_FILESYSTEM)
|
||||
unitResult = test_ScpPushDir();
|
||||
printf("ScpPushDir: %s\n",
|
||||
(unitResult == 0 ? "SUCCESS" : "FAILED"));
|
||||
testResult = testResult || unitResult;
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSH_TEST_CAPTURING_ALLOCATOR
|
||||
unitResult = test_SshResourceFree_zeroesSecrets();
|
||||
printf("SshResourceFree_zeroesSecrets: %s\n",
|
||||
|
|
|
|||
|
|
@ -1533,6 +1533,9 @@ enum WS_MessageIdLimits {
|
|||
word32 bufSz, word32* inOutIdx);
|
||||
WOLFSSH_API int wolfSSH_TestScpGetTimestamp(WOLFSSH* ssh, byte* buf,
|
||||
word32 bufSz, word32* inOutIdx);
|
||||
#if !defined(WOLFSSH_SCP_USER_CALLBACKS) && !defined(NO_FILESYSTEM)
|
||||
WOLFSSH_API int wolfSSH_TestScpPushDir(const char* path);
|
||||
#endif
|
||||
#endif /* WOLFSSH_SCP */
|
||||
#ifndef WOLFSSH_NO_DH
|
||||
WOLFSSH_API int wolfSSH_TestKeyAgreeDh_client(WOLFSSH* ssh, byte hashId,
|
||||
|
|
|
|||
|
|
@ -642,6 +642,14 @@ extern "C" {
|
|||
#endif
|
||||
#endif /* WSTRING_USER */
|
||||
|
||||
/* Measures a formatted string's length; _snprintf_s rejects the NULL/0 probe
|
||||
* form that WSNPRINTF maps to on Windows. Defined outside WSTRING_USER so
|
||||
* custom string ports need not supply it, and left overridable. */
|
||||
#if defined(USE_WINDOWS_API) && !defined(WSCPRINTF)
|
||||
#include <stdio.h>
|
||||
#define WSCPRINTF(f,...) _scprintf((f),##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
/* get local time for debug print out */
|
||||
#if defined(USE_WINDOWS_API) || defined(__MINGW32__)
|
||||
#define WTIME time
|
||||
|
|
|
|||
|
|
@ -687,7 +687,7 @@ static INLINE void tcp_listen(WS_SOCKET_T* sockfd, word16* port, int useAnyAddr)
|
|||
err_sys("tcp listen failed");
|
||||
#endif
|
||||
|
||||
#if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_TIRTOS) && !defined(WOLFSSL_NUCLEUS)
|
||||
#if !defined(WOLFSSL_TIRTOS) && !defined(WOLFSSL_NUCLEUS)
|
||||
if (*port == 0) {
|
||||
socklen_t len = sizeof(addr);
|
||||
if (getsockname(*sockfd, (struct sockaddr*)&addr, &len) == 0) {
|
||||
|
|
@ -837,6 +837,8 @@ typedef struct tcp_ready {
|
|||
#if defined(_POSIX_THREADS) && !defined(__MINGW32__)
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
#elif defined(USE_WINDOWS_API)
|
||||
HANDLE readyEvent; /* manual-reset event, set when ready */
|
||||
#endif
|
||||
} tcp_ready;
|
||||
|
||||
|
|
@ -860,6 +862,14 @@ typedef struct func_args {
|
|||
|
||||
#ifdef WOLFSSH_TEST_LOCKING
|
||||
|
||||
#if defined(USE_WINDOWS_API) && defined(NO_MAIN_DRIVER) && \
|
||||
!defined(SINGLE_THREADED)
|
||||
/* Upper bound on the wait for the server to become ready. The signal fires
|
||||
* right after the listen() so the real wait is sub-second; this generous
|
||||
* bound only keeps a dead server from hanging the run. */
|
||||
#define TCP_READY_TIMEOUT_MS 30000
|
||||
#endif
|
||||
|
||||
static INLINE void InitTcpReady(tcp_ready* ready)
|
||||
{
|
||||
ready->ready = 0;
|
||||
|
|
@ -869,6 +879,12 @@ static INLINE void InitTcpReady(tcp_ready* ready)
|
|||
!defined(__MINGW32__) && !defined(SINGLE_THREADED)
|
||||
pthread_mutex_init(&ready->mutex, NULL);
|
||||
pthread_cond_init(&ready->cond, NULL);
|
||||
#elif defined(USE_WINDOWS_API) && defined(NO_MAIN_DRIVER) && \
|
||||
!defined(SINGLE_THREADED)
|
||||
ready->readyEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if (ready->readyEvent == NULL) {
|
||||
err_sys("Create tcp ready event failed");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -879,6 +895,12 @@ static INLINE void FreeTcpReady(tcp_ready* ready)
|
|||
!defined(__MINGW32__) && !defined(SINGLE_THREADED)
|
||||
pthread_mutex_destroy(&ready->mutex);
|
||||
pthread_cond_destroy(&ready->cond);
|
||||
#elif defined(USE_WINDOWS_API) && defined(NO_MAIN_DRIVER) && \
|
||||
!defined(SINGLE_THREADED)
|
||||
if (ready->readyEvent != NULL) {
|
||||
CloseHandle(ready->readyEvent);
|
||||
ready->readyEvent = NULL;
|
||||
}
|
||||
#else
|
||||
WOLFSSH_UNUSED(ready);
|
||||
#endif
|
||||
|
|
@ -902,6 +924,14 @@ static INLINE void WaitTcpReady(tcp_ready* ready)
|
|||
* seems to help. This is not ideal. (XXX) */
|
||||
k_sleep(Z_TIMEOUT_TICKS(300));
|
||||
#endif /* WOLFSSH_ZEPHYR */
|
||||
#elif defined(USE_WINDOWS_API) && defined(NO_MAIN_DRIVER) && \
|
||||
!defined(SINGLE_THREADED)
|
||||
/* timeout or unset predicate means the server never signalled; abort
|
||||
* so the failure points at startup, not a later bogus connect */
|
||||
if (WaitForSingleObject(ready->readyEvent, TCP_READY_TIMEOUT_MS)
|
||||
!= WAIT_OBJECT_0 || !ready->ready) {
|
||||
err_sys("wait for tcp ready failed");
|
||||
}
|
||||
#else
|
||||
WOLFSSH_UNUSED(ready);
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue