diff --git a/apps/wolfsshd/test/run_all_sshd_tests.sh b/apps/wolfsshd/test/run_all_sshd_tests.sh index 7e6fcca7..fad3811d 100755 --- a/apps/wolfsshd/test/run_all_sshd_tests.sh +++ b/apps/wolfsshd/test/run_all_sshd_tests.sh @@ -8,6 +8,7 @@ test_cases=( "sshd_term_size_test.sh" "sshd_large_sftp_test.sh" "sshd_bad_sftp_test.sh" + "sshd_scp_fail.sh" "sshd_term_close_test.sh" "ssh_kex_algos.sh" ) diff --git a/apps/wolfsshd/test/sshd_scp_fail.sh b/apps/wolfsshd/test/sshd_scp_fail.sh new file mode 100755 index 00000000..05797257 --- /dev/null +++ b/apps/wolfsshd/test/sshd_scp_fail.sh @@ -0,0 +1,47 @@ +#!/bin/sh + +# sshd local test + +PWD=`pwd` +cd ../../.. + +TEST_SCP_CLIENT="./examples/scpclient/wolfscp" +USER=`whoami` +PRIVATE_KEY="./keys/hansel-key-ecc.der" +PUBLIC_KEY="./keys/hansel-key-ecc.pub" + +if [ -z "$1" ] || [ -z "$2" ]; then + echo "expecting host and port as arguments" + echo "./sshd_exec_test.sh 127.0.0.1 22222" + exit 1 +fi + +mkdir test-$$ + +OUTDIR="`pwd`/test-$$" + +dd if=/dev/random of=$OUTDIR/test.dat bs=1024 count=512 + +echo "$TEST_SCP_CLIENT -u $USER -i $PRIVATE_KEY -j $PUBLIC_KEY -S$OUTDIR/test.dat:. -H $1 -p $2" +$TEST_SCP_CLIENT -u $USER -i $PRIVATE_KEY -j $PUBLIC_KEY -S$OUTDIR/test.dat:. -H $1 -p $2 + +RESULT=$? +if [ "$RESULT" != "0" ]; then + echo "Expecting to pass transfer" + exit 1 +fi + +MD5SOURCE=`md5sum $OUTDIR/test.dat | awk '{ print $1 }'` +MD5DEST=`md5sum test.dat | awk '{ print $1 }'` + +if [ "$MD5SOURCE" != "$MD5DEST" ]; then + echo "Files do not match $MD5SOURCE != $MD5DEST" + exit 1 +fi + +rm -rf test-$$ +rm testout.dat + +cd $PWD +exit 0 + diff --git a/examples/scpclient/scpclient.c b/examples/scpclient/scpclient.c index d974550b..1d6ca0b1 100644 --- a/examples/scpclient/scpclient.c +++ b/examples/scpclient/scpclient.c @@ -344,7 +344,7 @@ THREAD_RETURN WOLFSSH_THREAD scp_client(void* args) wc_ecc_fp_free(); /* free per thread cache */ #endif - if (ret != WS_SUCCESS) + if ((ret != WS_SUCCESS) && (ret != WS_CHANNEL_CLOSED)) ((func_args*)args)->return_code = 1; return 0; } diff --git a/src/wolfscp.c b/src/wolfscp.c index 1ba75964..d490b1fb 100644 --- a/src/wolfscp.c +++ b/src/wolfscp.c @@ -602,7 +602,7 @@ int DoScpSource(WOLFSSH* ssh) ssh->scpBufferedSz); if (ret == WS_WINDOW_FULL || ret == WS_REKEYING) { ret = wolfSSH_worker(ssh, NULL); - if (ret == WS_SUCCESS) + if (ret == WS_SUCCESS || ssh->error == WS_WANT_READ) continue; } if (ret == WS_EXTDATA) { @@ -616,8 +616,10 @@ int DoScpSource(WOLFSSH* ssh) * open file descriptor before exit */ ScpSendCtx* sendCtx = NULL; sendCtx = (ScpSendCtx*)wolfSSH_GetScpSendCtx(ssh); - if (sendCtx != NULL) + if (sendCtx != NULL) { WFCLOSE(ssh->fs, sendCtx->fp); + sendCtx->fp = NULL; + } #endif WLOG(WS_LOG_ERROR, scpError, "failed to send file", ret); break; @@ -1181,6 +1183,7 @@ static int ParseBasePathHelper(WOLFSSH* ssh, int cmdSz) if (ScpPushDir(ssh->fs, &ctx, ssh->scpBasePath, ssh->ctx->heap) != WS_SUCCESS) { WLOG(WS_LOG_DEBUG, "scp : issue opening base dir"); + ssh->error = WS_INVALID_PATH_E; ret = WS_FATAL_ERROR; } else { @@ -2021,6 +2024,7 @@ int wsScpRecvCallback(WOLFSSH* ssh, int state, const char* basePath, WLOG(WS_LOG_ERROR, scpError, "scp receive callback unable " "to write requested size to file", bytes); WFCLOSE(ssh->fs, fp); + fp = NULL; ret = WS_SCP_ABORT; } else { #ifdef WOLFSCP_FLUSH @@ -2047,6 +2051,7 @@ int wsScpRecvCallback(WOLFSSH* ssh, int state, const char* basePath, flush_bytes = 0; #endif WFCLOSE(ssh->fs, fp); + fp = NULL; } /* set timestamp info */ @@ -2587,6 +2592,7 @@ static int ScpProcessEntry(WOLFSSH* ssh, char* fileName, word64* mTime, if ((sendCtx->fp != NULL) && ((ret < 0) || (*totalFileSz == (word32)ret))) { WFCLOSE(ssh->fs, sendCtx->fp); + sendCtx->fp = NULL; } } @@ -2758,6 +2764,7 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest, if ((sendCtx != NULL) && (sendCtx->fp != NULL) && ((ret < 0) || (*totalFileSz == (word32)ret))) { WFCLOSE(ssh->fs, sendCtx->fp); + sendCtx->fp = NULL; } break; @@ -2840,6 +2847,12 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest, break; } + if (sendCtx->fp == NULL) { + WLOG(WS_LOG_ERROR, "scp: file has been closed, abort"); + ret = WS_SCP_ABORT; + break; + } + ret = (word32)WFREAD(ssh->fs, buf, 1, bufSz, sendCtx->fp); if (ret == 0) { /* handle case of EOF */ ret = WS_EOF; @@ -2847,6 +2860,7 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest, if ((ret <= 0) || (fileOffset + ret == *totalFileSz)) { WFCLOSE(ssh->fs, sendCtx->fp); + sendCtx->fp = NULL; } break;