From 502b5a60f584466143b1dc8579777d6009b361fb Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Tue, 25 Feb 2025 19:00:32 +0000 Subject: [PATCH] Fix SFTP data truncation issue by moving sentSzSave to state structure Co-Authored-By: andrew@wolfssl.com --- .github/workflows/sftp-test.yml | 140 ++++++++++++++++++++++++++++++++ src/wolfsftp.c | 7 +- 2 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/sftp-test.yml diff --git a/.github/workflows/sftp-test.yml b/.github/workflows/sftp-test.yml new file mode 100644 index 00000000..dfcc2bec --- /dev/null +++ b/.github/workflows/sftp-test.yml @@ -0,0 +1,140 @@ +name: wolfSSH SFTP Test + +on: + push: + branches: [ '*' ] + pull_request: + branches: [ '*' ] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + create_matrix: + runs-on: ubuntu-latest + outputs: + versions: ${{ steps.json.outputs.versions }} + steps: + - name: Create wolfSSL version matrix + id: json + run: | + current=`curl -s https://api.github.com/repos/wolfssl/wolfssl/releases | grep tag_name | cut -d : -f 2,3 | tr -d \" | tr -d , | tr -d ' ' | head -1` + last=`curl -s https://api.github.com/repos/wolfssl/wolfssl/releases | grep tag_name | cut -d : -f 2,3 | tr -d \" | tr -d , | tr -d ' ' | head -2 | tail -1` + VERSIONS=$(echo "[ \"master\", \"$current\", \"$last\" ]") + echo "wolfSSL versions found: $VERSIONS" + echo "versions=$VERSIONS" >> $GITHUB_OUTPUT + + build_wolfssl: + needs: create_matrix + strategy: + fail-fast: false + matrix: + os: [ ubuntu-latest ] + wolfssl: ${{ fromJson(needs.create_matrix.outputs['versions']) }} + name: Build wolfssl + runs-on: ${{ matrix.os }} + timeout-minutes: 4 + steps: + - name: Checking cache for wolfssl + uses: actions/cache@v4 + id: cache-wolfssl + with: + path: build-dir/ + key: wolfssh-sftp-wolfssl-${{ matrix.wolfssl }}-${{ matrix.os }} + lookup-only: true + + - name: Checkout, build, and install wolfssl + if: steps.cache-wolfssl.outputs.cache-hit != 'true' + uses: wolfSSL/actions-build-autotools-project@v1 + with: + repository: wolfssl/wolfssl + ref: ${{ matrix.wolfssl }} + path: wolfssl + configure: --enable-ssh + check: false + install: true + + build_wolfssh: + needs: + - build_wolfssl + - create_matrix + strategy: + fail-fast: false + matrix: + os: [ ubuntu-latest ] + wolfssl: ${{ fromJson(needs.create_matrix.outputs['versions']) }} + name: Build and test wolfsftp + runs-on: ${{ matrix.os }} + timeout-minutes: 10 + steps: + - name: Checking cache for wolfssl + uses: actions/cache@v4 + with: + path: build-dir/ + key: wolfssh-sftp-wolfssl-${{ matrix.wolfssl }}-${{ matrix.os }} + fail-on-cache-miss: true + + - uses: actions/checkout@v4 + with: + path: wolfssh/ + + - name: autogen + working-directory: ./wolfssh/ + run: ./autogen.sh + + - name: configure + working-directory: ./wolfssh/ + run : | + ./configure --enable-sftp LDFLAGS="-L${{ github.workspace }}/build-dir/lib" CPPFLAGS="-I${{ github.workspace }}/build-dir/include -DWOLFSSH_NO_FPKI" + + - name: make + working-directory: ./wolfssh/ + run: make + + - name: Create test file + run: | + dd if=/dev/urandom of=/tmp/test.dat bs=1M count=2 + echo "Created 2MB test file at /tmp/test.dat" + md5sum /tmp/test.dat > /tmp/test.md5 + + - name: Start echoserver + working-directory: ./wolfssh/ + run: | + ./examples/echoserver/echoserver -f & + echo "Echoserver started with PID: $!" + sleep 2 # Give the server time to start + + - name: Run SFTP test + working-directory: ./wolfssh/ + run: | + mkdir -p /tmp/sftp_test_dir + # Create expect script to automate the SFTP client interaction + cat > /tmp/sftp_test.exp << 'EOF' + #!/usr/bin/expect -f + set timeout 60 + spawn ./examples/sftpclient/wolfsftp -N -h 127.0.0.1 -p 22222 -u jill + expect "Password:" + send "upthehill\r" + expect "wolfSSH sftp>" + send "put /tmp/test.dat /tmp/sftp_test_dir/test_received.dat\r" + expect "wolfSSH sftp>" + send "exit\r" + expect eof + EOF + chmod +x /tmp/sftp_test.exp + + # Install expect + sudo apt-get update && sudo apt-get install -y expect + + # Run the expect script + /tmp/sftp_test.exp + + # Verify the files match + echo "Verifying file integrity..." + if cmp -s /tmp/test.dat /tmp/sftp_test_dir/test_received.dat; then + echo "SFTP Test PASSED: Files match" + else + echo "SFTP Test FAILED: Files do not match" + exit 1 + fi diff --git a/src/wolfsftp.c b/src/wolfsftp.c index e544b9b5..24a35329 100644 --- a/src/wolfsftp.c +++ b/src/wolfsftp.c @@ -346,6 +346,7 @@ typedef struct WS_SFTP_SEND_WRITE_STATE { WS_SFTP_BUFFER buffer; int maxSz; int sentSz; + int sentSzSave; } WS_SFTP_SEND_WRITE_STATE; @@ -7167,7 +7168,6 @@ int wolfSSH_SFTP_SendWritePacket(WOLFSSH* ssh, byte* handle, word32 handleSz, WS_SFTP_SEND_WRITE_STATE* state = NULL; int ret = WS_FATAL_ERROR; int status; - int sentSzSave = 0; byte type; WLOG(WS_LOG_SFTP, "Entering wolfSSH_SFTP_SendWritePacket()"); @@ -7195,6 +7195,7 @@ int wolfSSH_SFTP_SendWritePacket(WOLFSSH* ssh, byte* handle, word32 handleSz, case STATE_SEND_WRITE_INIT: WLOG(WS_LOG_SFTP, "SFTP SEND_WRITE STATE: INIT"); state->sentSz = 0; + state->sentSzSave = 0; if (wolfSSH_SFTP_buffer_create(ssh, &state->buffer, handleSz + WOLFSSH_SFTP_HEADER + UINT32_SZ * 4) != WS_SUCCESS) { @@ -7267,7 +7268,7 @@ int wolfSSH_SFTP_SendWritePacket(WOLFSSH* ssh, byte* handle, word32 handleSz, continue; } - sentSzSave += state->sentSz; + state->sentSzSave += state->sentSz; if (inSz > (word32)state->sentSz) { in += state->sentSz; inSz -= state->sentSz; @@ -7351,7 +7352,7 @@ int wolfSSH_SFTP_SendWritePacket(WOLFSSH* ssh, byte* handle, word32 handleSz, ret = WS_SFTP_STATUS_NOT_OK; } if (ret >= WS_SUCCESS) - ret = sentSzSave; + ret = state->sentSzSave; state->state = STATE_SEND_WRITE_CLEANUP; NO_BREAK;