Skip to content

Commit 932fa4a

Browse files
Run threaded api-test SFTP/SCP tests on Windows
1 parent 974f4fd commit 932fa4a

7 files changed

Lines changed: 120 additions & 47 deletions

File tree

.github/workflows/windows-check.yml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -139,12 +139,13 @@ jobs:
139139
run: nuget restore ${{env.WOLFSSL_SOLUTION_FILE_PATH}}
140140

141141
# These env paths already include the wolfssh/ and wolfssl/ checkout
142-
# prefixes, so they must run from the workspace root (as the build job does).
143-
- name: updated user_settings.h for sshd and x509
144-
run: cp ${{env.USER_SETTINGS_H_NEW}} ${{env.USER_SETTINGS_H}}
145-
146-
- name: replace wolfSSL user_settings.h with wolfSSH user_settings.h
147-
run: get-content ${{env.USER_SETTINGS_H_NEW}} | %{$_ -replace "if 0","if 1"}
142+
# prefixes, so this runs from the default working directory, the workspace
143+
# root.
144+
- name: Enable wolfSSH options (sshd, sftp, x509) in user_settings.h
145+
shell: bash
146+
run: |
147+
sed -i 's/#if 0/#if 1/g' ${{env.USER_SETTINGS_H_NEW}}
148+
cp ${{env.USER_SETTINGS_H_NEW}} ${{env.USER_SETTINGS_H}}
148149
149150
# WholeProgramOptimization=false disables /GL so the v142-independent objects
150151
# link without a cross-version code-generation requirement (C1047).

examples/echoserver/echoserver.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2260,6 +2260,11 @@ static int LoadPasswdList(StrList* strList, PwMapList* mapList)
22602260
int count = 0;
22612261

22622262
while (strList) {
2263+
if (WSTRLEN(strList->str) >= sizeof names - 1) {
2264+
fprintf(stderr, "Ignoring over-long entry\n");
2265+
strList = strList->next;
2266+
continue;
2267+
}
22632268
WSTRNCPY(names, strList->str, sizeof names - 1);
22642269
passwd = WSTRCHR(names, ':');
22652270
if (passwd != NULL) {
@@ -2289,6 +2294,11 @@ static int LoadKeyboardList(StrList* strList, PwMapList* mapList,
22892294
int count = 0;
22902295

22912296
while (strList) {
2297+
if (WSTRLEN(strList->str) >= sizeof names - 1) {
2298+
fprintf(stderr, "Ignoring over-long entry\n");
2299+
strList = strList->next;
2300+
continue;
2301+
}
22922302
WSTRNCPY(names, strList->str, sizeof names - 1);
22932303
passwd = WSTRCHR(names, ':');
22942304
if (passwd != NULL) {
@@ -2325,6 +2335,11 @@ static int LoadPubKeyList(StrList* strList, int format, PwMapList* mapList)
23252335
buf = NULL;
23262336
bufSz = 0;
23272337

2338+
if (WSTRLEN(strList->str) >= sizeof names - 1) {
2339+
fprintf(stderr, "Ignoring over-long entry\n");
2340+
strList = strList->next;
2341+
continue;
2342+
}
23282343
WSTRNCPY(names, strList->str, sizeof names - 1);
23292344
fileName = WSTRCHR(names, ':');
23302345
if (fileName != NULL) {
@@ -2841,6 +2856,13 @@ static INLINE void SignalTcpReady(tcp_ready* ready, word16 port)
28412856
ready->port = port;
28422857
pthread_cond_signal(&ready->cond);
28432858
pthread_mutex_unlock(&ready->mutex);
2859+
#elif defined(USE_WINDOWS_API) && defined(NO_MAIN_DRIVER) && \
2860+
!defined(SINGLE_THREADED)
2861+
EnterCriticalSection(&ready->cs);
2862+
ready->ready = 1;
2863+
ready->port = port;
2864+
LeaveCriticalSection(&ready->cs);
2865+
SetEvent(ready->readyEvent);
28442866
#else
28452867
WOLFSSH_UNUSED(ready);
28462868
WOLFSSH_UNUSED(port);
@@ -2986,7 +3008,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
29863008
}
29873009
else {
29883010
port = (word16)atoi(myoptarg);
2989-
#if !defined(NO_MAIN_DRIVER) || defined(USE_WINDOWS_API)
3011+
#if !defined(NO_MAIN_DRIVER)
29903012
if (port == 0) {
29913013
ES_ERROR("port number cannot be 0");
29923014
}

examples/sftpclient/sftpclient.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ static void myStatusCb(WOLFSSH* sshIn, word32* bytes, char* name)
156156
static word32 lastOutputTime = 0;
157157
static word32 lastPrintedBytes[2] = {0, 0};
158158
word32 elapsedTime;
159+
word32 nameSz;
159160
#endif
160161
char buf[80];
161162
word64 longBytes = ((word64)bytes[1] << 32) | bytes[0];
@@ -181,8 +182,11 @@ static void myStatusCb(WOLFSSH* sshIn, word32* bytes, char* name)
181182
lastOutputTime = 0; /* Reset timer for new file transfer */
182183
lastPrintedBytes[0] = 0;
183184
lastPrintedBytes[1] = 0;
184-
WMEMSET(currentFile, 0, WOLFSSH_MAX_FILENAME);
185-
WSTRNCPY(currentFile, name, WOLFSSH_MAX_FILENAME);
185+
WMEMSET(currentFile, 0, sizeof(currentFile));
186+
nameSz = (word32)WSTRLEN(name);
187+
if (nameSz >= sizeof(currentFile))
188+
return;
189+
WMEMCPY(currentFile, name, nameSz + 1);
186190
}
187191
elapsedTime = currentTime - startTime;
188192
WSNPRINTF(buf, sizeof(buf), "Processed %8llu\t bytes in %d seconds\r",
@@ -1445,6 +1449,7 @@ static int doAutopilot(int cmd, char* local, char* remote)
14451449
int ret = WS_SUCCESS;
14461450
char fullpath[128] = ".";
14471451
WS_SFTPNAME* name = NULL;
1452+
word32 remoteSz;
14481453
byte remoteAbsPath = 0;
14491454

14501455
/* check if is absolute path before making it one */
@@ -1462,8 +1467,11 @@ static int doAutopilot(int cmd, char* local, char* remote)
14621467

14631468
if (remoteAbsPath) {
14641469
/* use remote absolute path if provided */
1470+
remoteSz = (word32)WSTRLEN(remote);
1471+
if (remoteSz >= sizeof(fullpath))
1472+
return WS_BUFFER_E;
14651473
WMEMSET(fullpath, 0, sizeof(fullpath));
1466-
WSTRNCPY(fullpath, remote, sizeof(fullpath) - 1);
1474+
WMEMCPY(fullpath, remote, remoteSz + 1);
14671475
}
14681476
else {
14691477
err = doBuildRemotePath(remote, fullpath, sizeof(fullpath), &name);

src/wolfscp.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1908,7 +1908,11 @@ static char* MakeScpCmd(const char* name, char dir, void* heap)
19081908
char* cmd;
19091909
int sz;
19101910

1911+
#ifdef USE_WINDOWS_API
1912+
sz = WSCPRINTF("scp -%c %s", dir, name) + 1;
1913+
#else
19111914
sz = WSNPRINTF(NULL, 0, "scp -%c %s", dir, name) + 1;
1915+
#endif
19121916
if (sz <= 0) {
19131917
return NULL;
19141918
}
@@ -2663,10 +2667,15 @@ static ScpDir* ScpNewDir(void *fs, const char* path, void* heap)
26632667
int ScpPushDir(void *fs, ScpSendCtx* ctx, const char* path, void* heap)
26642668
{
26652669
ScpDir* entry;
2670+
word32 pathSz;
26662671

26672672
if (ctx == NULL || path == NULL)
26682673
return WS_BAD_ARGUMENT;
26692674

2675+
pathSz = (word32)WSTRLEN(path);
2676+
if (pathSz >= sizeof(ctx->dirName))
2677+
return WS_BUFFER_E;
2678+
26702679
entry = ScpNewDir(fs, path, heap);
26712680
if (entry == NULL) {
26722681
return WS_FATAL_ERROR;
@@ -2680,9 +2689,9 @@ int ScpPushDir(void *fs, ScpSendCtx* ctx, const char* path, void* heap)
26802689
ctx->currentDir = entry;
26812690
}
26822691

2683-
/* append directory name to ctx->dirName */
2684-
WSTRNCPY(ctx->dirName, path, DEFAULT_SCP_FILE_NAME_SZ-1);
2685-
ctx->dirName[DEFAULT_SCP_FILE_NAME_SZ-1] = '\0';
2692+
/* append directory name to ctx->dirName, terminator included; the guard
2693+
* above bounds pathSz so the copy always fits */
2694+
WMEMCPY(ctx->dirName, path, pathSz + 1);
26862695

26872696
return WS_SUCCESS;
26882697
}

tests/api.c

Lines changed: 27 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1502,6 +1502,20 @@ static void test_wolfSSH_agent_signrequest_success(void)
15021502
#if defined(WOLFSSH_SFTP) && !defined(NO_WOLFSSH_CLIENT) && \
15031503
!defined(SINGLE_THREADED)
15041504

1505+
/* A peer that is already gone at shutdown is not a test failure. The send path
1506+
* reports the reset as the return value; the recv path returns the generic
1507+
* WS_ERROR and stashes the specific code in wolfSSH_get_error. */
1508+
static int AbsorbBenignReset(WOLFSSH* ssh, int ret)
1509+
{
1510+
if (ret == WS_SOCKET_ERROR_E ||
1511+
(ret == WS_ERROR &&
1512+
wolfSSH_get_error(ssh) == WS_SOCKET_ERROR_E)) {
1513+
ret = WS_SUCCESS;
1514+
}
1515+
1516+
return ret;
1517+
}
1518+
15051519
byte userPassword[256];
15061520

15071521
static int sftpUserAuth(byte authType, WS_UserAuthData* authData, void* ctx)
@@ -1635,10 +1649,8 @@ static void test_wolfSSH_SFTP_SendReadPacket(void)
16351649
argsCount = 0;
16361650
args[argsCount++] = ".";
16371651
args[argsCount++] = "-1";
1638-
#ifndef USE_WINDOWS_API
16391652
args[argsCount++] = "-p";
16401653
args[argsCount++] = "0";
1641-
#endif
16421654
ser.argv = (char**)args;
16431655
ser.argc = argsCount;
16441656
ser.signal = &ready;
@@ -1819,11 +1831,7 @@ static void test_wolfSSH_SFTP_SendReadPacket(void)
18191831
wolfSSH_worker(ssh, NULL);
18201832
}
18211833

1822-
argsCount = wolfSSH_shutdown(ssh);
1823-
if (argsCount == WS_SOCKET_ERROR_E) {
1824-
/* If the socket is closed on shutdown, peer is gone, this is OK. */
1825-
argsCount = WS_SUCCESS;
1826-
}
1834+
argsCount = AbsorbBenignReset(ssh, wolfSSH_shutdown(ssh));
18271835

18281836
#if DEFAULT_HIGHWATER_MARK < 8000
18291837
if (argsCount == WS_REKEYING) {
@@ -1845,6 +1853,7 @@ static void test_wolfSSH_SFTP_SendReadPacket(void)
18451853
k_sleep(Z_TIMEOUT_TICKS(100));
18461854
#endif
18471855
ThreadJoin(serThread);
1856+
FreeTcpReady(&ready);
18481857
}
18491858

18501859

@@ -1905,10 +1914,8 @@ static void test_wolfSSH_SFTP_PartialSend(void)
19051914
argsCount = 0;
19061915
args[argsCount++] = ".";
19071916
args[argsCount++] = "-1";
1908-
#ifndef USE_WINDOWS_API
19091917
args[argsCount++] = "-p";
19101918
args[argsCount++] = "0";
1911-
#endif
19121919
ser.argv = (char**)args;
19131920
ser.argc = argsCount;
19141921
ser.signal = &ready;
@@ -2094,10 +2101,7 @@ static void test_wolfSSH_SFTP_PartialSend(void)
20942101
wolfSSH_worker(ssh, NULL);
20952102
}
20962103

2097-
argsCount = wolfSSH_shutdown(ssh);
2098-
if (argsCount == WS_SOCKET_ERROR_E) {
2099-
argsCount = WS_SUCCESS;
2100-
}
2104+
argsCount = AbsorbBenignReset(ssh, wolfSSH_shutdown(ssh));
21012105
#if DEFAULT_HIGHWATER_MARK < 8000
21022106
if (argsCount == WS_REKEYING) {
21032107
argsCount = WS_SUCCESS;
@@ -2114,6 +2118,7 @@ static void test_wolfSSH_SFTP_PartialSend(void)
21142118
k_sleep(Z_TIMEOUT_TICKS(100));
21152119
#endif
21162120
ThreadJoin(serThread);
2121+
FreeTcpReady(&ready);
21172122
#endif /* WOLFSSH_TEST_INTERNAL */
21182123
}
21192124

@@ -2145,10 +2150,8 @@ static void sftp_rekey_test(int nonBlock)
21452150
argsCount = 0;
21462151
args[argsCount++] = ".";
21472152
args[argsCount++] = "-1";
2148-
#ifndef USE_WINDOWS_API
21492153
args[argsCount++] = "-p";
21502154
args[argsCount++] = "0";
2151-
#endif
21522155
ser.argv = (char**)args;
21532156
ser.argc = argsCount;
21542157
ser.signal = &ready;
@@ -2232,9 +2235,7 @@ static void sftp_rekey_test(int nonBlock)
22322235
* before the WS_REKEYING fixup below could otherwise mask it. The loop cap
22332236
* is one above the assert threshold to leave last-iteration headroom. */
22342237
AssertIntLE(tries, SFTP_REKEY_MAX_TRIES);
2235-
if (argsCount == WS_SOCKET_ERROR_E) {
2236-
argsCount = WS_SUCCESS;
2237-
}
2238+
argsCount = AbsorbBenignReset(ssh, argsCount);
22382239
#if DEFAULT_HIGHWATER_MARK < 8000
22392240
if (argsCount == WS_REKEYING) {
22402241
/* in cases where highwater mark is really small a re-key could happen */
@@ -2252,6 +2253,7 @@ static void sftp_rekey_test(int nonBlock)
22522253
k_sleep(Z_TIMEOUT_TICKS(100));
22532254
#endif
22542255
ThreadJoin(serThread);
2256+
FreeTcpReady(&ready);
22552257
}
22562258

22572259
static void test_wolfSSH_SFTP_ReKey(void)
@@ -2430,10 +2432,8 @@ static void test_wolfSSH_SFTP_Confinement(void)
24302432
argsCount = 0;
24312433
args[argsCount++] = ".";
24322434
args[argsCount++] = "-1";
2433-
#ifndef USE_WINDOWS_API
24342435
args[argsCount++] = "-p";
24352436
args[argsCount++] = "0";
2436-
#endif
24372437
ser.argv = (char**)args;
24382438
ser.argc = argsCount;
24392439
ser.signal = &ready;
@@ -2606,10 +2606,7 @@ static void test_wolfSSH_SFTP_Confinement(void)
26062606
while (wolfSSH_get_error(ssh) == WS_REKEYING)
26072607
wolfSSH_worker(ssh, NULL);
26082608

2609-
ret = wolfSSH_shutdown(ssh);
2610-
if (ret == WS_SOCKET_ERROR_E) {
2611-
ret = WS_SUCCESS;
2612-
}
2609+
ret = AbsorbBenignReset(ssh, wolfSSH_shutdown(ssh));
26132610
#if DEFAULT_HIGHWATER_MARK < 8000
26142611
if (ret == WS_REKEYING) {
26152612
ret = WS_SUCCESS;
@@ -2624,6 +2621,7 @@ static void test_wolfSSH_SFTP_Confinement(void)
26242621
k_sleep(Z_TIMEOUT_TICKS(100));
26252622
#endif
26262623
ThreadJoin(serThread);
2624+
FreeTcpReady(&ready);
26272625

26282626
/* remove staged targets; escMkdir/escDest only exist if confinement
26292627
* leaked, and inJailDir only if the positive-case RMDIR did not run, so
@@ -2945,10 +2943,8 @@ static void scp_rekey_test(int nonBlock, int toServer)
29452943
argsCount = 0;
29462944
args[argsCount++] = ".";
29472945
args[argsCount++] = "-1";
2948-
#ifndef USE_WINDOWS_API
29492946
args[argsCount++] = "-p";
29502947
args[argsCount++] = "0";
2951-
#endif
29522948
ser.argv = (char**)args;
29532949
ser.argc = argsCount;
29542950
ser.signal = &ready;
@@ -3043,6 +3039,7 @@ static void scp_rekey_test(int nonBlock, int toServer)
30433039
wolfSSH_free(ssh);
30443040
wolfSSH_CTX_free(ctx);
30453041
ThreadJoin(serThread);
3042+
FreeTcpReady(&ready);
30463043

30473044
/* verify the transferred file matches the source once the server is done */
30483045
AssertIntEQ(scpFilesMatch(verifyName, fileData, SCP_REKEY_FILE_SZ), 0);
@@ -3759,10 +3756,8 @@ static void test_wolfSSH_KeyboardInteractive(void)
37593756
args[argsCount++] = "-1";
37603757
args[argsCount++] = "-i";
37613758
args[argsCount++] = "test:test";
3762-
#ifndef USE_WINDOWS_API
37633759
args[argsCount++] = "-p";
37643760
args[argsCount++] = "0";
3765-
#endif
37663761
ser.argv = (char**)args;
37673762
ser.argc = argsCount;
37683763
ser.signal = &ready;
@@ -3775,11 +3770,7 @@ static void test_wolfSSH_KeyboardInteractive(void)
37753770
AssertNotNull(ssh);
37763771

37773772

3778-
argsCount = wolfSSH_shutdown(ssh);
3779-
if (argsCount == WS_SOCKET_ERROR_E) {
3780-
/* If the socket is closed on shutdown, peer is gone, this is OK. */
3781-
argsCount = WS_SUCCESS;
3782-
}
3773+
argsCount = AbsorbBenignReset(ssh, wolfSSH_shutdown(ssh));
37833774

37843775
#if DEFAULT_HIGHWATER_MARK < 8000
37853776
if (argsCount == WS_REKEYING) {
@@ -3801,6 +3792,7 @@ static void test_wolfSSH_KeyboardInteractive(void)
38013792
k_sleep(Z_TIMEOUT_TICKS(100));
38023793
#endif
38033794
ThreadJoin(serThread);
3795+
FreeTcpReady(&ready);
38043796
}
38053797

38063798
#else /* WOLFSSH_SFTP && !NO_WOLFSSH_CLIENT && !SINGLE_THREADED */
@@ -3819,6 +3811,8 @@ int wolfSSH_ApiTest(int argc, char** argv)
38193811
#ifdef WOLFSSH_TEST_BLOCK
38203812
return 77;
38213813
#else
3814+
WSTARTTCP();
3815+
38223816
AssertIntEQ(wolfSSH_Init(), WS_SUCCESS);
38233817

38243818
#if defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,2)

wolfssh/port.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,14 @@ extern "C" {
635635
#endif
636636
#endif /* WSTRING_USER */
637637

638+
/* Measures a formatted string's length; _snprintf_s rejects the NULL/0 probe
639+
* form that WSNPRINTF maps to on Windows. Defined outside WSTRING_USER so
640+
* custom string ports need not supply it, and left overridable. */
641+
#if defined(USE_WINDOWS_API) && !defined(WSCPRINTF)
642+
#include <stdio.h>
643+
#define WSCPRINTF(f,...) _scprintf((f),##__VA_ARGS__)
644+
#endif
645+
638646
/* get local time for debug print out */
639647
#if defined(USE_WINDOWS_API) || defined(__MINGW32__)
640648
#define WTIME time

0 commit comments

Comments
 (0)