Skip to content

Commit a9c7ebc

Browse files
committed
Fix SCP server side
SCP on the server side would get an EAGAIN around the 128KB mark, which would trigger an error. That error in-turn would cause two attempts to close the file, which would segfault. Also fix inverted error return status on scpclient.
1 parent 697f54a commit a9c7ebc

File tree

4 files changed

+65
-3
lines changed

4 files changed

+65
-3
lines changed

apps/wolfsshd/test/run_all_sshd_tests.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ test_cases=(
88
"sshd_term_size_test.sh"
99
"sshd_large_sftp_test.sh"
1010
"sshd_bad_sftp_test.sh"
11+
"sshd_scp_fail.sh"
1112
"sshd_term_close_test.sh"
1213
"ssh_kex_algos.sh"
1314
)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/bin/sh
2+
3+
# sshd local test
4+
5+
PWD=`pwd`
6+
cd ../../..
7+
8+
TEST_SCP_CLIENT="./examples/scpclient/wolfscp"
9+
USER=`whoami`
10+
PRIVATE_KEY="./keys/hansel-key-ecc.der"
11+
PUBLIC_KEY="./keys/hansel-key-ecc.pub"
12+
13+
if [ -z "$1" ] || [ -z "$2" ]; then
14+
echo "expecting host and port as arguments"
15+
echo "./sshd_exec_test.sh 127.0.0.1 22222"
16+
exit 1
17+
fi
18+
19+
mkdir test-$$
20+
21+
OUTDIR="`pwd`/test-$$"
22+
23+
dd if=/dev/random of=$OUTDIR/test.dat bs=1024 count=512
24+
25+
echo "$TEST_SCP_CLIENT -u $USER -i $PRIVATE_KEY -j $PUBLIC_KEY -S$OUTDIR/test.dat:. -H $1 -p $2"
26+
$TEST_SCP_CLIENT -u $USER -i $PRIVATE_KEY -j $PUBLIC_KEY -S$OUTDIR/test.dat:. -H $1 -p $2
27+
28+
RESULT=$?
29+
if [ "$RESULT" != "0" ]; then
30+
echo "Expecting to pass transfer"
31+
exit 1
32+
fi
33+
34+
MD5SOURCE=`md5sum $OUTDIR/test.dat | awk '{ print $1 }'`
35+
MD5DEST=`md5sum test.dat | awk '{ print $1 }'`
36+
37+
if [ "$MD5SOURCE" != "$MD5DEST" ]; then
38+
echo "Files do not match $MD5SOURCE != $MD5DEST"
39+
exit 1
40+
fi
41+
42+
rm -rf test-$$
43+
rm testout.dat
44+
45+
cd $PWD
46+
exit 0
47+

examples/scpclient/scpclient.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ THREAD_RETURN WOLFSSH_THREAD scp_client(void* args)
344344
wc_ecc_fp_free(); /* free per thread cache */
345345
#endif
346346

347-
if (ret != WS_SUCCESS)
347+
if ((ret != WS_SUCCESS) && (ret != WS_CHANNEL_CLOSED))
348348
((func_args*)args)->return_code = 1;
349349
return 0;
350350
}

src/wolfscp.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,7 @@ int DoScpSource(WOLFSSH* ssh)
602602
ssh->scpBufferedSz);
603603
if (ret == WS_WINDOW_FULL || ret == WS_REKEYING) {
604604
ret = wolfSSH_worker(ssh, NULL);
605-
if (ret == WS_SUCCESS)
605+
if (ret == WS_SUCCESS || ssh->error == WS_WANT_READ)
606606
continue;
607607
}
608608
if (ret == WS_EXTDATA) {
@@ -616,8 +616,10 @@ int DoScpSource(WOLFSSH* ssh)
616616
* open file descriptor before exit */
617617
ScpSendCtx* sendCtx = NULL;
618618
sendCtx = (ScpSendCtx*)wolfSSH_GetScpSendCtx(ssh);
619-
if (sendCtx != NULL)
619+
if (sendCtx != NULL) {
620620
WFCLOSE(ssh->fs, sendCtx->fp);
621+
sendCtx->fp = NULL;
622+
}
621623
#endif
622624
WLOG(WS_LOG_ERROR, scpError, "failed to send file", ret);
623625
break;
@@ -1181,6 +1183,7 @@ static int ParseBasePathHelper(WOLFSSH* ssh, int cmdSz)
11811183

11821184
if (ScpPushDir(ssh->fs, &ctx, ssh->scpBasePath, ssh->ctx->heap) != WS_SUCCESS) {
11831185
WLOG(WS_LOG_DEBUG, "scp : issue opening base dir");
1186+
ssh->error = WS_INVALID_PATH_E;
11841187
ret = WS_FATAL_ERROR;
11851188
}
11861189
else {
@@ -2021,6 +2024,7 @@ int wsScpRecvCallback(WOLFSSH* ssh, int state, const char* basePath,
20212024
WLOG(WS_LOG_ERROR, scpError, "scp receive callback unable "
20222025
"to write requested size to file", bytes);
20232026
WFCLOSE(ssh->fs, fp);
2027+
fp = NULL;
20242028
ret = WS_SCP_ABORT;
20252029
} else {
20262030
#ifdef WOLFSCP_FLUSH
@@ -2047,6 +2051,7 @@ int wsScpRecvCallback(WOLFSSH* ssh, int state, const char* basePath,
20472051
flush_bytes = 0;
20482052
#endif
20492053
WFCLOSE(ssh->fs, fp);
2054+
fp = NULL;
20502055
}
20512056

20522057
/* set timestamp info */
@@ -2587,6 +2592,7 @@ static int ScpProcessEntry(WOLFSSH* ssh, char* fileName, word64* mTime,
25872592
if ((sendCtx->fp != NULL) &&
25882593
((ret < 0) || (*totalFileSz == (word32)ret))) {
25892594
WFCLOSE(ssh->fs, sendCtx->fp);
2595+
sendCtx->fp = NULL;
25902596
}
25912597
}
25922598

@@ -2758,6 +2764,7 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest,
27582764
if ((sendCtx != NULL) && (sendCtx->fp != NULL) &&
27592765
((ret < 0) || (*totalFileSz == (word32)ret))) {
27602766
WFCLOSE(ssh->fs, sendCtx->fp);
2767+
sendCtx->fp = NULL;
27612768
}
27622769

27632770
break;
@@ -2840,13 +2847,20 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest,
28402847
break;
28412848
}
28422849

2850+
if (sendCtx->fp == NULL) {
2851+
WLOG(WS_LOG_ERROR, "scp: file has been closed, abort");
2852+
ret = WS_SCP_ABORT;
2853+
break;
2854+
}
2855+
28432856
ret = (word32)WFREAD(ssh->fs, buf, 1, bufSz, sendCtx->fp);
28442857
if (ret == 0) { /* handle case of EOF */
28452858
ret = WS_EOF;
28462859
}
28472860

28482861
if ((ret <= 0) || (fileOffset + ret == *totalFileSz)) {
28492862
WFCLOSE(ssh->fs, sendCtx->fp);
2863+
sendCtx->fp = NULL;
28502864
}
28512865

28522866
break;

0 commit comments

Comments
 (0)