mirror of https://github.com/wolfSSL/wolfssh.git
commit
be69a46db0
|
|
@ -42,7 +42,7 @@ jobs:
|
||||||
id: cache-wolfssl
|
id: cache-wolfssl
|
||||||
with:
|
with:
|
||||||
path: build-dir/
|
path: build-dir/
|
||||||
key: wolfssh-sftp-wolfssl-${{ matrix.wolfssl }}-${{ matrix.os }}
|
key: wolfssh-sftp-wolfssl-${{ matrix.wolfssl }}-${{ matrix.os }}-keygen
|
||||||
lookup-only: true
|
lookup-only: true
|
||||||
|
|
||||||
- name: Checkout, build, and install wolfssl
|
- name: Checkout, build, and install wolfssl
|
||||||
|
|
@ -52,7 +52,7 @@ jobs:
|
||||||
repository: wolfssl/wolfssl
|
repository: wolfssl/wolfssl
|
||||||
ref: ${{ matrix.wolfssl }}
|
ref: ${{ matrix.wolfssl }}
|
||||||
path: wolfssl
|
path: wolfssl
|
||||||
configure: --enable-ssh
|
configure: --enable-ssh --enable-keygen
|
||||||
check: false
|
check: false
|
||||||
install: true
|
install: true
|
||||||
|
|
||||||
|
|
@ -73,7 +73,7 @@ jobs:
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: build-dir/
|
path: build-dir/
|
||||||
key: wolfssh-sftp-wolfssl-${{ matrix.wolfssl }}-${{ matrix.os }}
|
key: wolfssh-sftp-wolfssl-${{ matrix.wolfssl }}-${{ matrix.os }}-keygen
|
||||||
fail-on-cache-miss: true
|
fail-on-cache-miss: true
|
||||||
|
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
@ -124,13 +124,13 @@ jobs:
|
||||||
expect eof
|
expect eof
|
||||||
EOF
|
EOF
|
||||||
chmod +x /tmp/sftp_test.exp
|
chmod +x /tmp/sftp_test.exp
|
||||||
|
|
||||||
# Install expect
|
# Install expect
|
||||||
sudo apt-get update && sudo apt-get install -y expect
|
sudo apt-get update && sudo apt-get install -y expect
|
||||||
|
|
||||||
# Run the expect script
|
# Run the expect script
|
||||||
/tmp/sftp_test.exp
|
/tmp/sftp_test.exp
|
||||||
|
|
||||||
# Verify the files match
|
# Verify the files match
|
||||||
echo "Verifying file integrity..."
|
echo "Verifying file integrity..."
|
||||||
if cmp -s /tmp/test.dat /tmp/sftp_test_dir/test_received.dat; then
|
if cmp -s /tmp/test.dat /tmp/sftp_test_dir/test_received.dat; then
|
||||||
|
|
@ -139,3 +139,90 @@ jobs:
|
||||||
echo "SFTP Test FAILED: Files do not match"
|
echo "SFTP Test FAILED: Files do not match"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
build_wolfssh_large_rw:
|
||||||
|
needs:
|
||||||
|
- build_wolfssl
|
||||||
|
- create_matrix
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [ ubuntu-latest ]
|
||||||
|
wolfssl: ${{ fromJson(needs.create_matrix.outputs['versions']) }}
|
||||||
|
name: Test wolfsftp large RW (10MB chunks, 3GB file)
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
timeout-minutes: 20
|
||||||
|
steps:
|
||||||
|
- name: Checking cache for wolfssl
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: build-dir/
|
||||||
|
key: wolfssh-sftp-wolfssl-${{ matrix.wolfssl }}-${{ matrix.os }}-keygen
|
||||||
|
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-all \
|
||||||
|
LDFLAGS="-L${{ github.workspace }}/build-dir/lib" \
|
||||||
|
CPPFLAGS="-I${{ github.workspace }}/build-dir/include -DWOLFSSH_NO_SFTP_TIMEOUT -DWOLFSSH_MAX_SFTP_RW=10485760 -DWOLFSSH_MAX_CHN_NAMESZ=4200"
|
||||||
|
|
||||||
|
- name: make
|
||||||
|
working-directory: ./wolfssh/
|
||||||
|
run: make
|
||||||
|
|
||||||
|
- name: Create 3GB test file
|
||||||
|
working-directory: ./wolfssh/
|
||||||
|
run: |
|
||||||
|
dd if=/dev/urandom of=seed.dat bs=1M count=10
|
||||||
|
for i in $(seq 1 308); do cat seed.dat >> large_test.dat; done
|
||||||
|
rm seed.dat
|
||||||
|
sha256sum large_test.dat > large_test.dat.sha256
|
||||||
|
echo "Created 3GB test file, SHA-256: $(cat large_test.dat.sha256)"
|
||||||
|
|
||||||
|
- name: Start echoserver
|
||||||
|
working-directory: ./wolfssh/
|
||||||
|
run: |
|
||||||
|
./examples/echoserver/echoserver -N -1 -R /tmp/echoserver_ready -d "$(pwd)" &
|
||||||
|
echo $! > /tmp/echoserver.pid
|
||||||
|
for i in $(seq 1 30); do
|
||||||
|
[ -s /tmp/echoserver_ready ] && break
|
||||||
|
sleep 0.2
|
||||||
|
done
|
||||||
|
if [ ! -s /tmp/echoserver_ready ]; then
|
||||||
|
echo "ERROR: echoserver failed to start"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "Echoserver ready on port $(cat /tmp/echoserver_ready)"
|
||||||
|
|
||||||
|
- name: SFTP get 3GB file with 10MB chunk size
|
||||||
|
working-directory: ./wolfssh/
|
||||||
|
run: |
|
||||||
|
port=$(cat /tmp/echoserver_ready)
|
||||||
|
./examples/sftpclient/wolfsftp -N -u jill -P upthehill -p "$port" \
|
||||||
|
-G -l /tmp/large_test_copy.dat -r "$(pwd)/large_test.dat"
|
||||||
|
|
||||||
|
- name: Verify file integrity
|
||||||
|
working-directory: ./wolfssh/
|
||||||
|
run: |
|
||||||
|
expected=$(awk '{print $1}' large_test.dat.sha256)
|
||||||
|
actual=$(sha256sum /tmp/large_test_copy.dat | awk '{print $1}')
|
||||||
|
echo "Expected SHA-256: $expected"
|
||||||
|
echo "Actual SHA-256: $actual"
|
||||||
|
if [ "$expected" != "$actual" ]; then
|
||||||
|
echo "FAIL: SHA-256 mismatch"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "PASS: 3GB SFTP transfer with WOLFSSH_MAX_SFTP_RW=10485760 succeeded"
|
||||||
|
|
||||||
|
- name: Stop echoserver
|
||||||
|
if: always()
|
||||||
|
run: kill "$(cat /tmp/echoserver.pid)" 2>/dev/null || true
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,432 @@
|
||||||
|
name: Windows wolfsshd SFTP Test
|
||||||
|
|
||||||
|
# This workflow tests wolfsshd and SFTP on Windows with:
|
||||||
|
# 1. Basic test: wolfsshd + SFTP client (pwd, ls, put/get small file)
|
||||||
|
# 2. Large file test: WOLFSSH_NO_SFTP_TIMEOUT, WOLFSSH_MAX_SFTP_RW=10485760,
|
||||||
|
# WOLFSSH_MAX_CHN_NAMESZ=4200 - get and put a 3GB file
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ 'master', 'main', 'release/**' ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ '*' ]
|
||||||
|
|
||||||
|
env:
|
||||||
|
WOLFSSL_SOLUTION_FILE_PATH: wolfssl64.sln
|
||||||
|
SOLUTION_FILE_PATH: wolfssh.sln
|
||||||
|
USER_SETTINGS_H_NEW: wolfssh/ide/winvs/user_settings.h
|
||||||
|
USER_SETTINGS_H: wolfssl/IDE/WIN/user_settings.h
|
||||||
|
INCLUDE_DIR: wolfssh
|
||||||
|
WOLFSSL_BUILD_CONFIGURATION: Release
|
||||||
|
WOLFSSH_BUILD_CONFIGURATION: Release
|
||||||
|
BUILD_PLATFORM: x64
|
||||||
|
TARGET_PLATFORM: 10
|
||||||
|
TEST_PORT: 22222
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: windows-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- test_type: basic
|
||||||
|
artifact_name: wolfssh-windows-build
|
||||||
|
- test_type: large_rw
|
||||||
|
artifact_name: wolfssh-windows-build-large-rw
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: wolfssl/wolfssl
|
||||||
|
path: wolfssl
|
||||||
|
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
path: wolfssh
|
||||||
|
|
||||||
|
- name: Add MSBuild to PATH
|
||||||
|
uses: microsoft/setup-msbuild@v1
|
||||||
|
|
||||||
|
- name: Update user_settings.h for wolfSSL build
|
||||||
|
working-directory: ${{env.GITHUB_WORKSPACE}}
|
||||||
|
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}}
|
||||||
|
|
||||||
|
- name: Restore wolfSSL NuGet packages
|
||||||
|
working-directory: ${{ github.workspace }}\wolfssl
|
||||||
|
run: nuget restore ${{env.WOLFSSL_SOLUTION_FILE_PATH}}
|
||||||
|
|
||||||
|
- name: Build wolfssl library
|
||||||
|
working-directory: ${{ github.workspace }}\wolfssl
|
||||||
|
run: msbuild /m /p:PlatformToolset=v142 /p:Platform=${{env.BUILD_PLATFORM}} /p:Configuration=${{env.WOLFSSL_BUILD_CONFIGURATION}} /t:wolfssl ${{env.WOLFSSL_SOLUTION_FILE_PATH}}
|
||||||
|
|
||||||
|
- name: Upload wolfSSL build artifacts
|
||||||
|
if: matrix.test_type == 'basic'
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: wolfssl-windows-build
|
||||||
|
path: |
|
||||||
|
wolfssl/IDE/WIN/${{env.WOLFSSL_BUILD_CONFIGURATION}}/${{env.BUILD_PLATFORM}}/**
|
||||||
|
wolfssl/IDE/WIN/${{env.WOLFSSL_BUILD_CONFIGURATION}}/**
|
||||||
|
wolfssl/${{env.WOLFSSL_BUILD_CONFIGURATION}}/${{env.BUILD_PLATFORM}}/**
|
||||||
|
wolfssl/${{env.WOLFSSL_BUILD_CONFIGURATION}}/**
|
||||||
|
|
||||||
|
- name: Update user_settings.h for sshd and SFTP
|
||||||
|
working-directory: ${{env.GITHUB_WORKSPACE}}
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
# Enable SSHD, SFTP support (second #if 0 block)
|
||||||
|
sed -i 's/#if 0/#if 1/g' ${{env.USER_SETTINGS_H_NEW}}
|
||||||
|
cp ${{env.USER_SETTINGS_H_NEW}} ${{env.USER_SETTINGS_H}}
|
||||||
|
# For large_rw test: add SFTP large file defines
|
||||||
|
if [ "${{ matrix.test_type }}" = "large_rw" ]; then
|
||||||
|
echo "" >> ${{env.USER_SETTINGS_H_NEW}}
|
||||||
|
echo "/* SFTP large file test defines */" >> ${{env.USER_SETTINGS_H_NEW}}
|
||||||
|
echo "#define WOLFSSH_NO_SFTP_TIMEOUT" >> ${{env.USER_SETTINGS_H_NEW}}
|
||||||
|
echo "#define WOLFSSH_MAX_SFTP_RW 10485760" >> ${{env.USER_SETTINGS_H_NEW}}
|
||||||
|
echo "#define WOLFSSH_MAX_CHN_NAMESZ 4200" >> ${{env.USER_SETTINGS_H_NEW}}
|
||||||
|
echo "Added WOLFSSH_NO_SFTP_TIMEOUT, WOLFSSH_MAX_SFTP_RW=10485760, WOLFSSH_MAX_CHN_NAMESZ=4200"
|
||||||
|
cp ${{env.USER_SETTINGS_H_NEW}} ${{env.USER_SETTINGS_H}}
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Restore NuGet packages
|
||||||
|
working-directory: ${{ github.workspace }}\wolfssh\ide\winvs
|
||||||
|
run: nuget restore ${{env.SOLUTION_FILE_PATH}}
|
||||||
|
|
||||||
|
- name: Build wolfssh
|
||||||
|
working-directory: ${{ github.workspace }}\wolfssh\ide\winvs
|
||||||
|
run: msbuild /m /p:PlatformToolset=v142 /p:Platform=${{env.BUILD_PLATFORM}} /p:WindowsTargetPlatformVersion=${{env.TARGET_PLATFORM}} /p:Configuration=${{env.WOLFSSH_BUILD_CONFIGURATION}} ${{env.SOLUTION_FILE_PATH}}
|
||||||
|
|
||||||
|
- name: Upload wolfSSH build artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{ matrix.artifact_name }}
|
||||||
|
if-no-files-found: error
|
||||||
|
path: |
|
||||||
|
wolfssh/ide/winvs/**/Release/**
|
||||||
|
|
||||||
|
test:
|
||||||
|
needs: build
|
||||||
|
runs-on: windows-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- test_type: basic
|
||||||
|
artifact_name: wolfssh-windows-build
|
||||||
|
- test_type: large_rw
|
||||||
|
artifact_name: wolfssh-windows-build-large-rw
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
path: wolfssh
|
||||||
|
|
||||||
|
- name: Download wolfSSH build artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{ matrix.artifact_name }}
|
||||||
|
path: .
|
||||||
|
|
||||||
|
- name: Download wolfSSL build artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: wolfssl-windows-build
|
||||||
|
path: .
|
||||||
|
|
||||||
|
- name: Create Windows user testuser and authorized_keys
|
||||||
|
working-directory: ${{ github.workspace }}\wolfssh
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
$homeDir = "C:\Users\testuser"
|
||||||
|
$sshDir = "$homeDir\.ssh"
|
||||||
|
$authKeysFile = "$sshDir\authorized_keys"
|
||||||
|
$pw = 'T3stP@ss!xY9'
|
||||||
|
|
||||||
|
New-Item -ItemType Directory -Path $homeDir -Force | Out-Null
|
||||||
|
New-Item -ItemType Directory -Path $sshDir -Force | Out-Null
|
||||||
|
|
||||||
|
$o = net user testuser $pw /add /homedir:$homeDir 2>&1
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
if ($o -match "already exists") {
|
||||||
|
net user testuser /homedir:$homeDir 2>$null
|
||||||
|
} else {
|
||||||
|
Write-Host "net user failed: $o"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Add-Content -Path $env:GITHUB_ENV -Value "TESTUSER_PASSWORD=$pw"
|
||||||
|
|
||||||
|
"" | Out-File -FilePath $authKeysFile -Encoding ASCII -NoNewline
|
||||||
|
icacls $authKeysFile /grant "testuser:R" /q
|
||||||
|
|
||||||
|
# Grant testuser full control of their home directory.
|
||||||
|
# New-Item creates the directory owned by the runner account; Windows
|
||||||
|
# only sets correct user ACLs during the normal profile-creation flow.
|
||||||
|
# Without this, ImpersonateLoggedOnUser succeeds but CreateFile fails
|
||||||
|
# with ACCESS_DENIED when wolfsshd tries to write files as testuser.
|
||||||
|
icacls $homeDir /grant "testuser:(OI)(CI)F" /T /q
|
||||||
|
|
||||||
|
$sid = (New-Object System.Security.Principal.NTAccount("testuser")).Translate([System.Security.Principal.SecurityIdentifier]).Value
|
||||||
|
$profKey = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$sid"
|
||||||
|
if (-not (Test-Path $profKey)) { New-Item -Path $profKey -Force | Out-Null }
|
||||||
|
Set-ItemProperty -Path $profKey -Name "ProfileImagePath" -Value $homeDir -Force
|
||||||
|
|
||||||
|
- name: Create wolfSSHd config file
|
||||||
|
working-directory: ${{ github.workspace }}\wolfssh
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
$keyPath = Join-Path "${{ github.workspace }}" "wolfssh\keys\server-key.pem"
|
||||||
|
$keyPathFull = (Resolve-Path $keyPath -ErrorAction Stop)
|
||||||
|
$configContent = @"
|
||||||
|
Port ${{env.TEST_PORT}}
|
||||||
|
PasswordAuthentication yes
|
||||||
|
PermitRootLogin yes
|
||||||
|
HostKey $($keyPathFull.Path)
|
||||||
|
AuthorizedKeysFile C:\Users\testuser\.ssh\authorized_keys
|
||||||
|
"@
|
||||||
|
$configContent | Out-File -FilePath sshd_config_test -Encoding ASCII
|
||||||
|
Get-Content sshd_config_test
|
||||||
|
|
||||||
|
- name: Find wolfSSH executables
|
||||||
|
working-directory: ${{ github.workspace }}\wolfssh
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
$searchRoot = "${{ github.workspace }}"
|
||||||
|
$sshdExe = Get-ChildItem -Path $searchRoot -Recurse -Filter "wolfsshd.exe" -ErrorAction SilentlyContinue |
|
||||||
|
Where-Object { $_.FullName -like "*Release*" } | Select-Object -First 1
|
||||||
|
if ($sshdExe) {
|
||||||
|
Add-Content -Path $env:GITHUB_ENV -Value "SSHD_PATH=$($sshdExe.FullName)"
|
||||||
|
} else {
|
||||||
|
Write-Host "ERROR: wolfsshd.exe not found"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$sftpExe = Get-ChildItem -Path $searchRoot -Recurse -Filter "wolfsftp.exe" -ErrorAction SilentlyContinue |
|
||||||
|
Where-Object { $_.FullName -like "*Release*" } | Select-Object -First 1
|
||||||
|
if (-not $sftpExe) {
|
||||||
|
$sftpExe = Get-ChildItem -Path $searchRoot -Recurse -Filter "wolfsftp-client.exe" -ErrorAction SilentlyContinue |
|
||||||
|
Where-Object { $_.FullName -like "*Release*" } | Select-Object -First 1
|
||||||
|
}
|
||||||
|
if ($sftpExe) {
|
||||||
|
Add-Content -Path $env:GITHUB_ENV -Value "SFTP_PATH=$($sftpExe.FullName)"
|
||||||
|
} else {
|
||||||
|
Write-Host "ERROR: SFTP client exe not found"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
- name: Copy wolfSSL DLL to executable directory
|
||||||
|
working-directory: ${{ github.workspace }}
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
$sshdPath = $env:SSHD_PATH
|
||||||
|
$sshdDir = Split-Path -Parent $sshdPath
|
||||||
|
if (Test-Path (Join-Path $sshdDir "wolfssl.lib")) { exit 0 }
|
||||||
|
$wolfsslDll = Get-ChildItem -Path "${{ github.workspace }}\wolfssl" -Recurse -Filter "wolfssl.dll" -ErrorAction SilentlyContinue | Select-Object -First 1
|
||||||
|
if ($wolfsslDll) {
|
||||||
|
Copy-Item -Path $wolfsslDll.FullName -Destination (Join-Path $sshdDir "wolfssl.dll") -Force
|
||||||
|
}
|
||||||
|
|
||||||
|
- name: Grant service access to config and keys
|
||||||
|
working-directory: ${{ github.workspace }}\wolfssh
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
icacls (Get-Location).Path /grant "NT AUTHORITY\SYSTEM:(OI)(CI)RX" /T /q
|
||||||
|
|
||||||
|
- name: Start wolfSSHd as Windows service
|
||||||
|
working-directory: ${{ github.workspace }}\wolfssh
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
$sshdPath = $env:SSHD_PATH
|
||||||
|
$configPathFull = (Resolve-Path "sshd_config_test").Path
|
||||||
|
$serviceName = "wolfsshd"
|
||||||
|
|
||||||
|
$existingService = Get-Service -Name $serviceName -ErrorAction SilentlyContinue
|
||||||
|
if ($existingService) {
|
||||||
|
if ($existingService.Status -eq 'Running') { Stop-Service -Name $serviceName -Force }
|
||||||
|
sc.exe delete $serviceName | Out-Null
|
||||||
|
Start-Sleep -Seconds 2
|
||||||
|
}
|
||||||
|
|
||||||
|
$binPath = "`"$sshdPath`" -f `"$configPathFull`" -p ${{env.TEST_PORT}}"
|
||||||
|
sc.exe create $serviceName binPath= $binPath
|
||||||
|
sc.exe start $serviceName
|
||||||
|
Start-Sleep -Seconds 5
|
||||||
|
|
||||||
|
$service = Get-Service -Name $serviceName -ErrorAction SilentlyContinue
|
||||||
|
if ($service.Status -ne 'Running') {
|
||||||
|
Write-Host "ERROR: Service failed to start"
|
||||||
|
sc.exe query $serviceName
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
Add-Content -Path $env:GITHUB_ENV -Value "SSHD_SERVICE_NAME=$serviceName"
|
||||||
|
|
||||||
|
- name: Test SFTP get non-existent file (no hang, correct error)
|
||||||
|
working-directory: ${{ github.workspace }}\wolfssh
|
||||||
|
shell: pwsh
|
||||||
|
timeout-minutes: 1
|
||||||
|
run: |
|
||||||
|
$sftpPath = $env:SFTP_PATH
|
||||||
|
$destFile = Join-Path $env:TEMP "copy.dat"
|
||||||
|
$getCommands = "get /this_file_does_not_exist_xyz $destFile`nquit"
|
||||||
|
$getCommands | Out-File -FilePath sftp_get_nonexistent_commands.txt -Encoding ASCII
|
||||||
|
|
||||||
|
$proc = Start-Process -FilePath $sftpPath `
|
||||||
|
-ArgumentList "-u", "testuser", "-P", $env:TESTUSER_PASSWORD, "-h", "localhost", "-p", "${{env.TEST_PORT}}" `
|
||||||
|
-RedirectStandardInput "sftp_get_nonexistent_commands.txt" `
|
||||||
|
-RedirectStandardOutput "sftp_get_nonexistent_out.txt" `
|
||||||
|
-RedirectStandardError "sftp_get_nonexistent_err.txt" `
|
||||||
|
-Wait -NoNewWindow -PassThru
|
||||||
|
|
||||||
|
Write-Host "=== SFTP Output ==="
|
||||||
|
$output = ""
|
||||||
|
if (Test-Path sftp_get_nonexistent_out.txt) {
|
||||||
|
$output = Get-Content sftp_get_nonexistent_out.txt -Raw
|
||||||
|
Write-Host $output
|
||||||
|
}
|
||||||
|
Write-Host "=== SFTP Error ==="
|
||||||
|
if (Test-Path sftp_get_nonexistent_err.txt) { Get-Content sftp_get_nonexistent_err.txt }
|
||||||
|
|
||||||
|
# Verify file was NOT created
|
||||||
|
if (Test-Path $destFile) {
|
||||||
|
Write-Host "ERROR: $destFile was created despite non-existent source file"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
# Verify error message was emitted
|
||||||
|
if ($output -notmatch "Error getting file") {
|
||||||
|
Write-Host "ERROR: Expected 'Error getting file' in output"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
Write-Host "PASS: SFTP get non-existent file did not create file, reported error correctly, did not hang"
|
||||||
|
|
||||||
|
- name: Test SFTP connection (basic)
|
||||||
|
if: matrix.test_type == 'basic'
|
||||||
|
working-directory: ${{ github.workspace }}\wolfssh
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
$sftpPath = $env:SFTP_PATH
|
||||||
|
$testCommands = "pwd`nls`nquit"
|
||||||
|
$testCommands | Out-File -FilePath sftp_commands.txt -Encoding ASCII
|
||||||
|
|
||||||
|
$process = Start-Process -FilePath $sftpPath `
|
||||||
|
-ArgumentList "-u", "testuser", "-P", $env:TESTUSER_PASSWORD, "-h", "localhost", "-p", "${{env.TEST_PORT}}" `
|
||||||
|
-RedirectStandardInput "sftp_commands.txt" `
|
||||||
|
-RedirectStandardOutput "sftp_output.txt" `
|
||||||
|
-RedirectStandardError "sftp_error.txt" `
|
||||||
|
-Wait -NoNewWindow -PassThru
|
||||||
|
|
||||||
|
Get-Content sftp_output.txt
|
||||||
|
Get-Content sftp_error.txt
|
||||||
|
if ($process.ExitCode -ne 0) {
|
||||||
|
Write-Host "ERROR: SFTP basic test failed with exit $($process.ExitCode)"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
Write-Host "Basic SFTP test passed"
|
||||||
|
|
||||||
|
- name: Create 3GB test file and run SFTP get/put
|
||||||
|
if: matrix.test_type == 'large_rw'
|
||||||
|
working-directory: ${{ github.workspace }}\wolfssh
|
||||||
|
shell: pwsh
|
||||||
|
timeout-minutes: 25
|
||||||
|
run: |
|
||||||
|
$sftpPath = $env:SFTP_PATH
|
||||||
|
$workDir = Join-Path $env:GITHUB_WORKSPACE "wolfssh"
|
||||||
|
$largeFile = Join-Path $workDir "large_test.dat"
|
||||||
|
$getDestPath = Join-Path $workDir "large_test_copy.dat"
|
||||||
|
|
||||||
|
# Create 3GB file: one random 10MB chunk repeated 307x + 2MB
|
||||||
|
Write-Host "Creating 3GB test file..."
|
||||||
|
$chunkSize = 10485760 # 10MB
|
||||||
|
$totalSize = [long]3221225472 # 3GB
|
||||||
|
$rng = New-Object System.Security.Cryptography.RNGCryptoServiceProvider
|
||||||
|
$chunk = New-Object byte[] $chunkSize
|
||||||
|
$rng.GetBytes($chunk)
|
||||||
|
$fs = [System.IO.File]::Create($largeFile)
|
||||||
|
$remaining = $totalSize
|
||||||
|
while ($remaining -gt 0) {
|
||||||
|
$toWrite = [int][Math]::Min([long]$chunkSize, $remaining)
|
||||||
|
$fs.Write($chunk, 0, $toWrite)
|
||||||
|
$remaining -= $toWrite
|
||||||
|
}
|
||||||
|
$fs.Close()
|
||||||
|
|
||||||
|
$hash = Get-FileHash -Path $largeFile -Algorithm SHA256
|
||||||
|
$hash.Hash | Out-File -FilePath (Join-Path $workDir "large_test.dat.sha256")
|
||||||
|
Write-Host "Created 3GB file, SHA256: $($hash.Hash)"
|
||||||
|
|
||||||
|
# SFTP PUT (upload)
|
||||||
|
# Use a relative remote path (no leading /) so the server resolves it
|
||||||
|
# under testuser's home directory. An absolute /large_test.dat maps to
|
||||||
|
# the drive root (C:\) where testuser has no write permission; relative
|
||||||
|
# large_test.dat is prefixed by workingDir (C:\Users\testuser) on the
|
||||||
|
# client and becomes C:\Users\testuser\large_test.dat on the server.
|
||||||
|
Write-Host "SFTP PUT 3GB file..."
|
||||||
|
$putCommands = "put $largeFile large_test.dat`nquit"
|
||||||
|
$putCommands | Out-File -FilePath (Join-Path $workDir "sftp_put_commands.txt") -Encoding ASCII
|
||||||
|
$proc = Start-Process -FilePath $sftpPath `
|
||||||
|
-ArgumentList "-u", "testuser", "-P", $env:TESTUSER_PASSWORD, "-h", "localhost", "-p", "${{env.TEST_PORT}}" `
|
||||||
|
-WorkingDirectory $workDir `
|
||||||
|
-RedirectStandardInput (Join-Path $workDir "sftp_put_commands.txt") `
|
||||||
|
-RedirectStandardOutput (Join-Path $workDir "sftp_put_out.txt") `
|
||||||
|
-RedirectStandardError (Join-Path $workDir "sftp_put_err.txt") `
|
||||||
|
-Wait -NoNewWindow -PassThru
|
||||||
|
|
||||||
|
$putOut = Get-Content (Join-Path $workDir "sftp_put_out.txt") -Raw -ErrorAction SilentlyContinue
|
||||||
|
Write-Host "=== SFTP PUT output ==="; Write-Host $putOut
|
||||||
|
if ($proc.ExitCode -ne 0 -or $putOut -match "Error pushing file") {
|
||||||
|
Get-Content (Join-Path $workDir "sftp_put_err.txt") -ErrorAction SilentlyContinue
|
||||||
|
Write-Host "ERROR: SFTP PUT failed"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
Write-Host "PUT succeeded"
|
||||||
|
|
||||||
|
# SFTP GET (download) - relative remote and local paths.
|
||||||
|
# Remote large_test.dat resolves to C:\Users\testuser\large_test.dat.
|
||||||
|
# Local large_test_copy.dat is relative to wolfsftp's CWD ($workDir).
|
||||||
|
Write-Host "SFTP GET 3GB file..."
|
||||||
|
$getCommands = "get large_test.dat large_test_copy.dat`nquit"
|
||||||
|
$getCommands | Out-File -FilePath (Join-Path $workDir "sftp_get_commands.txt") -Encoding ASCII
|
||||||
|
$proc2 = Start-Process -FilePath $sftpPath `
|
||||||
|
-ArgumentList "-u", "testuser", "-P", $env:TESTUSER_PASSWORD, "-h", "localhost", "-p", "${{env.TEST_PORT}}" `
|
||||||
|
-WorkingDirectory $workDir `
|
||||||
|
-RedirectStandardInput (Join-Path $workDir "sftp_get_commands.txt") `
|
||||||
|
-RedirectStandardOutput (Join-Path $workDir "sftp_get_out.txt") `
|
||||||
|
-RedirectStandardError (Join-Path $workDir "sftp_get_err.txt") `
|
||||||
|
-Wait -NoNewWindow -PassThru
|
||||||
|
|
||||||
|
$getOut = Get-Content (Join-Path $workDir "sftp_get_out.txt") -Raw -ErrorAction SilentlyContinue
|
||||||
|
Write-Host "=== SFTP GET output ==="; Write-Host $getOut
|
||||||
|
if ($proc2.ExitCode -ne 0 -or $getOut -match "Error getting file") {
|
||||||
|
Get-Content (Join-Path $workDir "sftp_get_err.txt") -ErrorAction SilentlyContinue
|
||||||
|
Write-Host "ERROR: SFTP GET failed"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
Write-Host "GET succeeded"
|
||||||
|
|
||||||
|
# Verify integrity (file is in $workDir from GET with relative path)
|
||||||
|
$expectedHash = (Get-Content (Join-Path $workDir "large_test.dat.sha256")).Trim()
|
||||||
|
$actualHash = (Get-FileHash -Path $getDestPath -Algorithm SHA256).Hash
|
||||||
|
Write-Host "File: $getDestPath"
|
||||||
|
Write-Host "Expected SHA256: $expectedHash"
|
||||||
|
Write-Host "Actual SHA256: $actualHash"
|
||||||
|
if ($expectedHash -ne $actualHash) {
|
||||||
|
Write-Host "ERROR: SHA256 mismatch - PUT/GET corruption"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
Write-Host "PASS: 3GB SFTP get/put succeeded"
|
||||||
|
|
||||||
|
- name: Cleanup
|
||||||
|
if: always()
|
||||||
|
working-directory: ${{ github.workspace }}\wolfssh
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
$serviceName = $env:SSHD_SERVICE_NAME
|
||||||
|
if (-not $serviceName) { $serviceName = "wolfsshd" }
|
||||||
|
$service = Get-Service -Name $serviceName -ErrorAction SilentlyContinue
|
||||||
|
if ($service) {
|
||||||
|
if ($service.Status -eq 'Running') { Stop-Service -Name $serviceName -Force }
|
||||||
|
sc.exe delete $serviceName | Out-Null
|
||||||
|
}
|
||||||
|
|
@ -154,6 +154,7 @@ static void myStatusCb(WOLFSSH* sshIn, word32* bytes, char* name)
|
||||||
word32 currentTime;
|
word32 currentTime;
|
||||||
#ifndef WOLFSSH_NO_TIMESTAMP
|
#ifndef WOLFSSH_NO_TIMESTAMP
|
||||||
static word32 lastOutputTime = 0;
|
static word32 lastOutputTime = 0;
|
||||||
|
static word32 lastPrintedBytes[2] = {0, 0};
|
||||||
word32 elapsedTime;
|
word32 elapsedTime;
|
||||||
#endif
|
#endif
|
||||||
char buf[80];
|
char buf[80];
|
||||||
|
|
@ -162,12 +163,24 @@ static void myStatusCb(WOLFSSH* sshIn, word32* bytes, char* name)
|
||||||
#ifndef WOLFSSH_NO_TIMESTAMP
|
#ifndef WOLFSSH_NO_TIMESTAMP
|
||||||
currentTime = current_time(0);
|
currentTime = current_time(0);
|
||||||
if (currentTime == lastOutputTime) {
|
if (currentTime == lastOutputTime) {
|
||||||
return;
|
if (bytes[0] != lastPrintedBytes[0] || bytes[1] != lastPrintedBytes[1]) {
|
||||||
|
/* Progress made in the same second — throttle but track latest */
|
||||||
|
lastPrintedBytes[0] = bytes[0];
|
||||||
|
lastPrintedBytes[1] = bytes[1];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* bytes unchanged: EOF final call — fall through to print */
|
||||||
}
|
}
|
||||||
lastOutputTime = currentTime;
|
else {
|
||||||
|
lastOutputTime = currentTime;
|
||||||
|
}
|
||||||
|
lastPrintedBytes[0] = bytes[0];
|
||||||
|
lastPrintedBytes[1] = bytes[1];
|
||||||
if (WSTRNCMP(currentFile, name, WSTRLEN(name)) != 0) {
|
if (WSTRNCMP(currentFile, name, WSTRLEN(name)) != 0) {
|
||||||
startTime = current_time(1);
|
startTime = current_time(1);
|
||||||
lastOutputTime = 0; /* Reset timer for new file transfer */
|
lastOutputTime = 0; /* Reset timer for new file transfer */
|
||||||
|
lastPrintedBytes[0] = 0;
|
||||||
|
lastPrintedBytes[1] = 0;
|
||||||
WMEMSET(currentFile, 0, WOLFSSH_MAX_FILENAME);
|
WMEMSET(currentFile, 0, WOLFSSH_MAX_FILENAME);
|
||||||
WSTRNCPY(currentFile, name, WOLFSSH_MAX_FILENAME);
|
WSTRNCPY(currentFile, name, WOLFSSH_MAX_FILENAME);
|
||||||
}
|
}
|
||||||
|
|
@ -756,8 +769,8 @@ static int doCmds(func_args* args)
|
||||||
|
|
||||||
ret = wolfSSH_SFTP_STAT(ssh, pt, &atrb);
|
ret = wolfSSH_SFTP_STAT(ssh, pt, &atrb);
|
||||||
err = wolfSSH_get_error(ssh);
|
err = wolfSSH_get_error(ssh);
|
||||||
} while ((err == WS_WANT_READ || err == WS_WANT_WRITE)
|
} while ((err == WS_WANT_READ || err == WS_WANT_WRITE ||
|
||||||
&& ret != WS_SUCCESS);
|
err == WS_REKEYING) && ret != WS_SUCCESS);
|
||||||
if (ret != WS_SUCCESS) {
|
if (ret != WS_SUCCESS) {
|
||||||
if (SFTP_FPUTS(args, "Error changing directory\n") < 0) {
|
if (SFTP_FPUTS(args, "Error changing directory\n") < 0) {
|
||||||
err_msg("fputs error");
|
err_msg("fputs error");
|
||||||
|
|
@ -844,8 +857,8 @@ static int doCmds(func_args* args)
|
||||||
|
|
||||||
ret = wolfSSH_SFTP_CHMOD(ssh, pt, mode);
|
ret = wolfSSH_SFTP_CHMOD(ssh, pt, mode);
|
||||||
err = wolfSSH_get_error(ssh);
|
err = wolfSSH_get_error(ssh);
|
||||||
} while ((err == WS_WANT_READ || err == WS_WANT_WRITE)
|
} while ((err == WS_WANT_READ || err == WS_WANT_WRITE ||
|
||||||
&& ret != WS_SUCCESS);
|
err == WS_REKEYING) && ret != WS_SUCCESS);
|
||||||
if (ret != WS_SUCCESS) {
|
if (ret != WS_SUCCESS) {
|
||||||
if (SFTP_FPUTS(args, "Unable to change permissions of ") < 0) {
|
if (SFTP_FPUTS(args, "Unable to change permissions of ") < 0) {
|
||||||
err_msg("fputs error");
|
err_msg("fputs error");
|
||||||
|
|
@ -901,8 +914,8 @@ static int doCmds(func_args* args)
|
||||||
|
|
||||||
ret = wolfSSH_SFTP_RMDIR(ssh, pt);
|
ret = wolfSSH_SFTP_RMDIR(ssh, pt);
|
||||||
err = wolfSSH_get_error(ssh);
|
err = wolfSSH_get_error(ssh);
|
||||||
} while ((err == WS_WANT_READ || err == WS_WANT_WRITE)
|
} while ((err == WS_WANT_READ || err == WS_WANT_WRITE ||
|
||||||
&& ret != WS_SUCCESS);
|
err == WS_REKEYING) && ret != WS_SUCCESS);
|
||||||
if (ret != WS_SUCCESS) {
|
if (ret != WS_SUCCESS) {
|
||||||
if (ret == WS_PERMISSIONS) {
|
if (ret == WS_PERMISSIONS) {
|
||||||
if (SFTP_FPUTS(args, "Insufficient permissions\n") < 0) {
|
if (SFTP_FPUTS(args, "Insufficient permissions\n") < 0) {
|
||||||
|
|
@ -954,8 +967,8 @@ static int doCmds(func_args* args)
|
||||||
|
|
||||||
ret = wolfSSH_SFTP_Remove(ssh, pt);
|
ret = wolfSSH_SFTP_Remove(ssh, pt);
|
||||||
err = wolfSSH_get_error(ssh);
|
err = wolfSSH_get_error(ssh);
|
||||||
} while ((err == WS_WANT_READ || err == WS_WANT_WRITE)
|
} while ((err == WS_WANT_READ || err == WS_WANT_WRITE ||
|
||||||
&& ret != WS_SUCCESS);
|
err == WS_REKEYING) && ret != WS_SUCCESS);
|
||||||
if (ret != WS_SUCCESS) {
|
if (ret != WS_SUCCESS) {
|
||||||
if (ret == WS_PERMISSIONS) {
|
if (ret == WS_PERMISSIONS) {
|
||||||
if (SFTP_FPUTS(args, "Insufficient permissions\n") < 0) {
|
if (SFTP_FPUTS(args, "Insufficient permissions\n") < 0) {
|
||||||
|
|
|
||||||
105
src/wolfsftp.c
105
src/wolfsftp.c
|
|
@ -6435,7 +6435,7 @@ static WS_SFTPNAME* wolfSSH_SFTP_DoName(WOLFSSH* ssh)
|
||||||
ret = wolfSSH_SFTP_buffer_read(ssh, &state->buffer,
|
ret = wolfSSH_SFTP_buffer_read(ssh, &state->buffer,
|
||||||
wolfSSH_SFTP_buffer_size(&state->buffer));
|
wolfSSH_SFTP_buffer_size(&state->buffer));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (ssh->error != WS_WANT_READ) {
|
if (!NoticeError(ssh)) {
|
||||||
wolfSSH_SFTP_ClearState(ssh, STATE_ID_NAME);
|
wolfSSH_SFTP_ClearState(ssh, STATE_ID_NAME);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -6443,7 +6443,7 @@ static WS_SFTPNAME* wolfSSH_SFTP_DoName(WOLFSSH* ssh)
|
||||||
|
|
||||||
wolfSSH_SFTP_buffer_rewind(&state->buffer);
|
wolfSSH_SFTP_buffer_rewind(&state->buffer);
|
||||||
wolfSSH_SFTP_DoStatus(ssh, reqId, &state->buffer);
|
wolfSSH_SFTP_DoStatus(ssh, reqId, &state->buffer);
|
||||||
if (ssh->error != WS_WANT_READ) {
|
if (!NoticeError(ssh)) {
|
||||||
wolfSSH_SFTP_ClearState(ssh, STATE_ID_NAME);
|
wolfSSH_SFTP_ClearState(ssh, STATE_ID_NAME);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -6458,7 +6458,7 @@ static WS_SFTPNAME* wolfSSH_SFTP_DoName(WOLFSSH* ssh)
|
||||||
wolfSSH_SFTP_buffer_size(&state->buffer) -
|
wolfSSH_SFTP_buffer_size(&state->buffer) -
|
||||||
wolfSSH_SFTP_buffer_idx(&state->buffer));
|
wolfSSH_SFTP_buffer_idx(&state->buffer));
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
if (ssh->error != WS_WANT_READ) {
|
if (!NoticeError(ssh)) {
|
||||||
wolfSSH_SFTP_ClearState(ssh, STATE_ID_NAME);
|
wolfSSH_SFTP_ClearState(ssh, STATE_ID_NAME);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -6909,8 +6909,7 @@ int wolfSSH_SFTP_CHMOD(WOLFSSH* ssh, char* n, char* oct)
|
||||||
case STATE_CHMOD_GET:
|
case STATE_CHMOD_GET:
|
||||||
/* get current attributes of path */
|
/* get current attributes of path */
|
||||||
if ((ret = wolfSSH_SFTP_STAT(ssh, n, &state->atr)) != WS_SUCCESS) {
|
if ((ret = wolfSSH_SFTP_STAT(ssh, n, &state->atr)) != WS_SUCCESS) {
|
||||||
if (ssh->error != WS_WANT_READ
|
if (!NoticeError(ssh)) {
|
||||||
&& ssh->error != WS_WANT_WRITE) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
|
@ -6990,14 +6989,12 @@ static int SFTP_STAT(WOLFSSH* ssh, char* dir, WS_SFTP_FILEATRB* atr, byte type)
|
||||||
WLOG(WS_LOG_SFTP, "SFTP LSTAT STATE: SEND_TYPE_REQ");
|
WLOG(WS_LOG_SFTP, "SFTP LSTAT STATE: SEND_TYPE_REQ");
|
||||||
ret = SendPacketType(ssh, type, (byte*)dir, state->dirSz);
|
ret = SendPacketType(ssh, type, (byte*)dir, state->dirSz);
|
||||||
if (ret != WS_SUCCESS) {
|
if (ret != WS_SUCCESS) {
|
||||||
if (ssh->error == WS_WANT_READ ||
|
if (NoticeError(ssh)) {
|
||||||
ssh->error == WS_WANT_WRITE)
|
|
||||||
return WS_FATAL_ERROR;
|
return WS_FATAL_ERROR;
|
||||||
else {
|
|
||||||
ret_fatal = 1;
|
|
||||||
state->state = STATE_LSTAT_CLEANUP;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
ret_fatal = 1;
|
||||||
|
state->state = STATE_LSTAT_CLEANUP;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
state->state = STATE_LSTAT_GET_HEADER;
|
state->state = STATE_LSTAT_GET_HEADER;
|
||||||
FALL_THROUGH;
|
FALL_THROUGH;
|
||||||
|
|
@ -7008,14 +7005,12 @@ static int SFTP_STAT(WOLFSSH* ssh, char* dir, WS_SFTP_FILEATRB* atr, byte type)
|
||||||
ret = SFTP_GetHeader(ssh, &state->reqId, &state->type,
|
ret = SFTP_GetHeader(ssh, &state->reqId, &state->type,
|
||||||
&state->buffer);
|
&state->buffer);
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
if (ssh->error == WS_WANT_READ ||
|
if (NoticeError(ssh)) {
|
||||||
ssh->error == WS_WANT_WRITE)
|
|
||||||
return WS_FATAL_ERROR;
|
return WS_FATAL_ERROR;
|
||||||
else {
|
|
||||||
state->state = STATE_LSTAT_CLEANUP;
|
|
||||||
ret_fatal = 1;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
state->state = STATE_LSTAT_CLEANUP;
|
||||||
|
ret_fatal = 1;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->state = STATE_LSTAT_CHECK_REQ_ID;
|
state->state = STATE_LSTAT_CHECK_REQ_ID;
|
||||||
|
|
@ -7042,7 +7037,7 @@ static int SFTP_STAT(WOLFSSH* ssh, char* dir, WS_SFTP_FILEATRB* atr, byte type)
|
||||||
ret = wolfSSH_SFTP_buffer_read(ssh, &state->buffer,
|
ret = wolfSSH_SFTP_buffer_read(ssh, &state->buffer,
|
||||||
wolfSSH_SFTP_buffer_size(&state->buffer));
|
wolfSSH_SFTP_buffer_size(&state->buffer));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (ssh->error != WS_WANT_READ) {
|
if (!NoticeError(ssh)) {
|
||||||
wolfSSH_SFTP_ClearState(ssh, STATE_ID_LSTAT);
|
wolfSSH_SFTP_ClearState(ssh, STATE_ID_LSTAT);
|
||||||
}
|
}
|
||||||
return WS_FATAL_ERROR;
|
return WS_FATAL_ERROR;
|
||||||
|
|
@ -7211,8 +7206,7 @@ int wolfSSH_SFTP_SetSTAT(WOLFSSH* ssh, char* dir, WS_SFTP_FILEATRB* atr)
|
||||||
/* send header and type specific data */
|
/* send header and type specific data */
|
||||||
case STATE_SET_ATR_SEND:
|
case STATE_SET_ATR_SEND:
|
||||||
if (wolfSSH_SFTP_buffer_send(ssh, &state->buffer) < 0) {
|
if (wolfSSH_SFTP_buffer_send(ssh, &state->buffer) < 0) {
|
||||||
if (ssh->error != WS_WANT_READ
|
if (!NoticeError(ssh)) {
|
||||||
&& ssh->error != WS_WANT_WRITE) {
|
|
||||||
ret = WS_FATAL_ERROR;
|
ret = WS_FATAL_ERROR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -7229,8 +7223,7 @@ int wolfSSH_SFTP_SetSTAT(WOLFSSH* ssh, char* dir, WS_SFTP_FILEATRB* atr)
|
||||||
case STATE_SET_ATR_GET:
|
case STATE_SET_ATR_GET:
|
||||||
maxSz = SFTP_GetHeader(ssh, &state->reqId, &type, &state->buffer);
|
maxSz = SFTP_GetHeader(ssh, &state->reqId, &type, &state->buffer);
|
||||||
if (maxSz <= 0) {
|
if (maxSz <= 0) {
|
||||||
if (ssh->error != WS_WANT_READ
|
if (!NoticeError(ssh)) {
|
||||||
&& ssh->error != WS_WANT_WRITE) {
|
|
||||||
ret = WS_FATAL_ERROR;
|
ret = WS_FATAL_ERROR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -7257,8 +7250,7 @@ int wolfSSH_SFTP_SetSTAT(WOLFSSH* ssh, char* dir, WS_SFTP_FILEATRB* atr)
|
||||||
ret = wolfSSH_SFTP_buffer_read(ssh, &state->buffer,
|
ret = wolfSSH_SFTP_buffer_read(ssh, &state->buffer,
|
||||||
wolfSSH_SFTP_buffer_size(&state->buffer));
|
wolfSSH_SFTP_buffer_size(&state->buffer));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (ssh->error != WS_WANT_READ
|
if (!NoticeError(ssh)) {
|
||||||
&& ssh->error != WS_WANT_WRITE) {
|
|
||||||
ret = WS_FATAL_ERROR;
|
ret = WS_FATAL_ERROR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -7730,12 +7722,8 @@ int wolfSSH_SFTP_SendReadPacket(WOLFSSH* ssh, byte* handle, word32 handleSz,
|
||||||
if (NoticeError(ssh)) {
|
if (NoticeError(ssh)) {
|
||||||
return WS_FATAL_ERROR;
|
return WS_FATAL_ERROR;
|
||||||
}
|
}
|
||||||
if (ssh->error != WS_WANT_READ &&
|
state->state = STATE_SEND_READ_CLEANUP;
|
||||||
ssh->error != WS_WANT_WRITE) {
|
continue;
|
||||||
state->state = STATE_SEND_READ_CLEANUP;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
wolfSSH_SFTP_buffer_free(ssh, &state->buffer);
|
wolfSSH_SFTP_buffer_free(ssh, &state->buffer);
|
||||||
state->state = STATE_SEND_READ_GET_HEADER;
|
state->state = STATE_SEND_READ_GET_HEADER;
|
||||||
|
|
@ -7746,11 +7734,11 @@ int wolfSSH_SFTP_SendReadPacket(WOLFSSH* ssh, byte* handle, word32 handleSz,
|
||||||
/* Get response */
|
/* Get response */
|
||||||
if ((ret = SFTP_GetHeader(ssh, &state->reqId, &state->type,
|
if ((ret = SFTP_GetHeader(ssh, &state->reqId, &state->type,
|
||||||
&state->buffer)) <= 0) {
|
&state->buffer)) <= 0) {
|
||||||
if (!NoticeError(ssh)) {
|
if (NoticeError(ssh)) {
|
||||||
state->state = STATE_SEND_READ_CLEANUP;
|
return WS_FATAL_ERROR;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
return WS_FATAL_ERROR;
|
state->state = STATE_SEND_READ_CLEANUP;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
ret = wolfSSH_SFTP_buffer_create(ssh, &state->buffer, ret);
|
ret = wolfSSH_SFTP_buffer_create(ssh, &state->buffer, ret);
|
||||||
if (ret != WS_SUCCESS) {
|
if (ret != WS_SUCCESS) {
|
||||||
|
|
@ -7789,11 +7777,11 @@ int wolfSSH_SFTP_SendReadPacket(WOLFSSH* ssh, byte* handle, word32 handleSz,
|
||||||
/* get size of string and place it into out buffer */
|
/* get size of string and place it into out buffer */
|
||||||
ret = wolfSSH_stream_read(ssh, szFlat, UINT32_SZ);
|
ret = wolfSSH_stream_read(ssh, szFlat, UINT32_SZ);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (!NoticeError(ssh)) {
|
if (NoticeError(ssh)) {
|
||||||
state->state = STATE_SEND_READ_CLEANUP;
|
return WS_FATAL_ERROR;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
return ret;
|
state->state = STATE_SEND_READ_CLEANUP;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
ato32(szFlat, &sz);
|
ato32(szFlat, &sz);
|
||||||
wolfSSH_SFTP_buffer_create(ssh, &state->buffer, sz);
|
wolfSSH_SFTP_buffer_create(ssh, &state->buffer, sz);
|
||||||
|
|
@ -7814,8 +7802,7 @@ int wolfSSH_SFTP_SendReadPacket(WOLFSSH* ssh, byte* handle, word32 handleSz,
|
||||||
out + state->recvSz,
|
out + state->recvSz,
|
||||||
wolfSSH_SFTP_buffer_size(&state->buffer));
|
wolfSSH_SFTP_buffer_size(&state->buffer));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (ssh->error == WS_WANT_READ ||
|
if (NoticeError(ssh)) {
|
||||||
ssh->error == WS_WANT_WRITE) {
|
|
||||||
return WS_FATAL_ERROR;
|
return WS_FATAL_ERROR;
|
||||||
}
|
}
|
||||||
WLOG(WS_LOG_SFTP, "Error reading remainder of data");
|
WLOG(WS_LOG_SFTP, "Error reading remainder of data");
|
||||||
|
|
@ -7852,12 +7839,11 @@ int wolfSSH_SFTP_SendReadPacket(WOLFSSH* ssh, byte* handle, word32 handleSz,
|
||||||
ret = wolfSSH_SFTP_buffer_read(ssh, &state->buffer,
|
ret = wolfSSH_SFTP_buffer_read(ssh, &state->buffer,
|
||||||
wolfSSH_SFTP_buffer_size(&state->buffer));
|
wolfSSH_SFTP_buffer_size(&state->buffer));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (ssh->error != WS_WANT_READ &&
|
if (NoticeError(ssh)) {
|
||||||
ssh->error != WS_WANT_WRITE) {
|
return WS_FATAL_ERROR;
|
||||||
state->state = STATE_SEND_READ_CLEANUP;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
return WS_FATAL_ERROR;
|
state->state = STATE_SEND_READ_CLEANUP;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
wolfSSH_SFTP_buffer_rewind(&state->buffer);
|
wolfSSH_SFTP_buffer_rewind(&state->buffer);
|
||||||
ret = wolfSSH_SFTP_DoStatus(ssh,
|
ret = wolfSSH_SFTP_DoStatus(ssh,
|
||||||
|
|
@ -8176,8 +8162,7 @@ int wolfSSH_SFTP_Close(WOLFSSH* ssh, byte* handle, word32 handleSz)
|
||||||
ret = wolfSSH_SFTP_buffer_read(ssh, &state->buffer,
|
ret = wolfSSH_SFTP_buffer_read(ssh, &state->buffer,
|
||||||
wolfSSH_SFTP_buffer_size(&state->buffer));
|
wolfSSH_SFTP_buffer_size(&state->buffer));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (ssh->error != WS_WANT_WRITE &&
|
if (!NoticeError(ssh)) {
|
||||||
ssh->error != WS_WANT_READ) {
|
|
||||||
wolfSSH_SFTP_buffer_free(ssh, &state->buffer);
|
wolfSSH_SFTP_buffer_free(ssh, &state->buffer);
|
||||||
}
|
}
|
||||||
return WS_FATAL_ERROR;
|
return WS_FATAL_ERROR;
|
||||||
|
|
@ -8523,8 +8508,7 @@ int wolfSSH_SFTP_Remove(WOLFSSH* ssh, char* f)
|
||||||
case STATE_RM_LSTAT:
|
case STATE_RM_LSTAT:
|
||||||
/* check file is there to be removed */
|
/* check file is there to be removed */
|
||||||
if ((ret = wolfSSH_SFTP_LSTAT(ssh, f, &atrb)) != WS_SUCCESS) {
|
if ((ret = wolfSSH_SFTP_LSTAT(ssh, f, &atrb)) != WS_SUCCESS) {
|
||||||
if (ssh->error != WS_WANT_WRITE
|
if (!NoticeError(ssh)) {
|
||||||
&& ssh->error != WS_WANT_READ) {
|
|
||||||
WLOG(WS_LOG_SFTP, "Error verifying file");
|
WLOG(WS_LOG_SFTP, "Error verifying file");
|
||||||
wolfSSH_SFTP_ClearState(ssh, STATE_ID_RM);
|
wolfSSH_SFTP_ClearState(ssh, STATE_ID_RM);
|
||||||
}
|
}
|
||||||
|
|
@ -8537,8 +8521,7 @@ int wolfSSH_SFTP_Remove(WOLFSSH* ssh, char* f)
|
||||||
ret = SendPacketType(ssh, WOLFSSH_FTP_REMOVE, (byte*)f,
|
ret = SendPacketType(ssh, WOLFSSH_FTP_REMOVE, (byte*)f,
|
||||||
(word32)WSTRLEN(f));
|
(word32)WSTRLEN(f));
|
||||||
if (ret != WS_SUCCESS) {
|
if (ret != WS_SUCCESS) {
|
||||||
if (ssh->error != WS_WANT_WRITE
|
if (!NoticeError(ssh)) {
|
||||||
&& ssh->error != WS_WANT_READ) {
|
|
||||||
wolfSSH_SFTP_ClearState(ssh, STATE_ID_RM);
|
wolfSSH_SFTP_ClearState(ssh, STATE_ID_RM);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
|
@ -8549,8 +8532,7 @@ int wolfSSH_SFTP_Remove(WOLFSSH* ssh, char* f)
|
||||||
case STATE_RM_GET:
|
case STATE_RM_GET:
|
||||||
ret = SFTP_GetHeader(ssh, &state->reqId, &type, &state->buffer);
|
ret = SFTP_GetHeader(ssh, &state->reqId, &type, &state->buffer);
|
||||||
if (ret <= 0 || type != WOLFSSH_FTP_STATUS) {
|
if (ret <= 0 || type != WOLFSSH_FTP_STATUS) {
|
||||||
if (ssh->error != WS_WANT_WRITE
|
if (!NoticeError(ssh)) {
|
||||||
&& ssh->error != WS_WANT_READ) {
|
|
||||||
WLOG(WS_LOG_SFTP, "Unexpected packet type");
|
WLOG(WS_LOG_SFTP, "Unexpected packet type");
|
||||||
wolfSSH_SFTP_ClearState(ssh, STATE_ID_RM);
|
wolfSSH_SFTP_ClearState(ssh, STATE_ID_RM);
|
||||||
}
|
}
|
||||||
|
|
@ -8568,8 +8550,7 @@ int wolfSSH_SFTP_Remove(WOLFSSH* ssh, char* f)
|
||||||
ret = wolfSSH_SFTP_buffer_read(ssh, &state->buffer,
|
ret = wolfSSH_SFTP_buffer_read(ssh, &state->buffer,
|
||||||
wolfSSH_SFTP_buffer_size(&state->buffer));
|
wolfSSH_SFTP_buffer_size(&state->buffer));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (ssh->error != WS_WANT_WRITE
|
if (!NoticeError(ssh)) {
|
||||||
&& ssh->error != WS_WANT_READ) {
|
|
||||||
WLOG(WS_LOG_SFTP, "Unexpected packet type");
|
WLOG(WS_LOG_SFTP, "Unexpected packet type");
|
||||||
wolfSSH_SFTP_ClearState(ssh, STATE_ID_RM);
|
wolfSSH_SFTP_ClearState(ssh, STATE_ID_RM);
|
||||||
}
|
}
|
||||||
|
|
@ -8630,8 +8611,7 @@ int wolfSSH_SFTP_RMDIR(WOLFSSH* ssh, char* dir)
|
||||||
ret = SendPacketType(ssh, WOLFSSH_FTP_RMDIR, (byte*)dir,
|
ret = SendPacketType(ssh, WOLFSSH_FTP_RMDIR, (byte*)dir,
|
||||||
(word32)WSTRLEN(dir));
|
(word32)WSTRLEN(dir));
|
||||||
if (ret != WS_SUCCESS) {
|
if (ret != WS_SUCCESS) {
|
||||||
if (ssh->error != WS_WANT_READ
|
if (!NoticeError(ssh)) {
|
||||||
&& ssh->error != WS_WANT_WRITE) {
|
|
||||||
wolfSSH_SFTP_ClearState(ssh, STATE_ID_RMDIR);
|
wolfSSH_SFTP_ClearState(ssh, STATE_ID_RMDIR);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
|
@ -8642,7 +8622,7 @@ int wolfSSH_SFTP_RMDIR(WOLFSSH* ssh, char* dir)
|
||||||
case STATE_RMDIR_GET:
|
case STATE_RMDIR_GET:
|
||||||
ret = SFTP_GetHeader(ssh, &state->reqId, &type, &state->buffer);
|
ret = SFTP_GetHeader(ssh, &state->reqId, &type, &state->buffer);
|
||||||
if (ret <= 0 || type != WOLFSSH_FTP_STATUS) {
|
if (ret <= 0 || type != WOLFSSH_FTP_STATUS) {
|
||||||
if (ssh->error != WS_WANT_READ) {
|
if (!NoticeError(ssh)) {
|
||||||
wolfSSH_SFTP_ClearState(ssh, STATE_ID_RMDIR);
|
wolfSSH_SFTP_ClearState(ssh, STATE_ID_RMDIR);
|
||||||
WLOG(WS_LOG_SFTP, "Unexpected packet type");
|
WLOG(WS_LOG_SFTP, "Unexpected packet type");
|
||||||
}
|
}
|
||||||
|
|
@ -8659,7 +8639,7 @@ int wolfSSH_SFTP_RMDIR(WOLFSSH* ssh, char* dir)
|
||||||
ret = wolfSSH_SFTP_buffer_read(ssh, &state->buffer,
|
ret = wolfSSH_SFTP_buffer_read(ssh, &state->buffer,
|
||||||
wolfSSH_SFTP_buffer_size(&state->buffer));
|
wolfSSH_SFTP_buffer_size(&state->buffer));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (ssh->error != WS_WANT_READ)
|
if (!NoticeError(ssh))
|
||||||
wolfSSH_SFTP_ClearState(ssh, STATE_ID_RMDIR);
|
wolfSSH_SFTP_ClearState(ssh, STATE_ID_RMDIR);
|
||||||
return WS_FATAL_ERROR;
|
return WS_FATAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
@ -8867,9 +8847,9 @@ int wolfSSH_SFTP_Get(WOLFSSH* ssh, char* from,
|
||||||
WLOG(WS_LOG_SFTP, "SFTP GET STATE: STAT");
|
WLOG(WS_LOG_SFTP, "SFTP GET STATE: STAT");
|
||||||
ret = wolfSSH_SFTP_STAT(ssh, from, &state->attrib);
|
ret = wolfSSH_SFTP_STAT(ssh, from, &state->attrib);
|
||||||
if (ret != WS_SUCCESS) {
|
if (ret != WS_SUCCESS) {
|
||||||
if (ssh->error == WS_WANT_READ ||
|
if (NoticeError(ssh)) {
|
||||||
ssh->error == WS_WANT_WRITE)
|
|
||||||
return WS_FATAL_ERROR;
|
return WS_FATAL_ERROR;
|
||||||
|
}
|
||||||
WLOG(WS_LOG_SFTP, "Error verifying file");
|
WLOG(WS_LOG_SFTP, "Error verifying file");
|
||||||
state->state = STATE_GET_CLEANUP;
|
state->state = STATE_GET_CLEANUP;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -8894,8 +8874,7 @@ int wolfSSH_SFTP_Get(WOLFSSH* ssh, char* from,
|
||||||
ret = wolfSSH_SFTP_Open(ssh, from, WOLFSSH_FXF_READ, NULL,
|
ret = wolfSSH_SFTP_Open(ssh, from, WOLFSSH_FXF_READ, NULL,
|
||||||
state->handle, &state->handleSz);
|
state->handle, &state->handleSz);
|
||||||
if (ret != WS_SUCCESS) {
|
if (ret != WS_SUCCESS) {
|
||||||
if (ssh->error == WS_WANT_READ ||
|
if (NoticeError(ssh)) {
|
||||||
ssh->error == WS_WANT_WRITE) {
|
|
||||||
return WS_FATAL_ERROR;
|
return WS_FATAL_ERROR;
|
||||||
}
|
}
|
||||||
WLOG(WS_LOG_SFTP, "Error getting handle");
|
WLOG(WS_LOG_SFTP, "Error getting handle");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue