Port Unix bash tests (#410)

Leverage upstream test infrastructure to run against windows openssh binaries.
This commit is contained in:
bagajjal 2019-12-09 15:12:46 -08:00 committed by GitHub
parent 9b327de3e7
commit a49bdce666
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 649 additions and 476 deletions

View File

@ -277,6 +277,12 @@ function Publish-Artifact
Add-Artifact -artifacts $artifacts -FileToAdd $Global:OpenSSHTestInfo["UninstallTestResultsFile"]
Add-Artifact -artifacts $artifacts -FileToAdd $Global:OpenSSHTestInfo["TestSetupLogFile"]
}
if ($Global:bash_tests_summary)
{
Add-Artifact -artifacts $artifacts -FileToAdd $Global:bash_tests_summary["BashTestSummaryFile"]
Add-Artifact -artifacts $artifacts -FileToAdd $Global:bash_tests_summary["BashTestLogFile"]
}
foreach ($artifact in $artifacts)
{
@ -324,7 +330,7 @@ function Invoke-OpenSSHTests
else
{
Write-Host "All Unit tests passed!"
Write-BuildMessage -Message "All Unit tests passed!" -Category Information
Write-BuildMessage -Message "All Unit tests passed!" -Category Information
}
# Run all E2E tests.
@ -339,7 +345,7 @@ function Invoke-OpenSSHTests
return
}
$xml = [xml](Get-Content $OpenSSHTestInfo["E2ETestResultsFile"] | out-string)
if ([int]$xml.'test-results'.failures -gt 0)
if ([int]$xml.'test-results'.failures -gt 0)
{
$errorMessage = "$($xml.'test-results'.failures) tests in regress\pesterTests failed. Detail test log is at $($OpenSSHTestInfo["E2ETestResultsFile"])."
Write-Warning $errorMessage
@ -347,7 +353,31 @@ function Invoke-OpenSSHTests
Set-BuildVariable TestPassed False
Write-Warning "Stop running further tests!"
return
}
}
# Run UNIX bash tests.
Invoke-OpenSSHBashTests
if (-not $Global:bash_tests_summary)
{
$errorMessage = "Failed to start OpenSSH bash tests"
Write-Warning $errorMessage
Write-BuildMessage -Message $errorMessage -Category Error
Set-BuildVariable TestPassed False
Write-Warning "Stop running further tests!"
return
}
if ($Global:bash_tests_summary["TotalBashTestsFailed"] -ne 0)
{
$total_bash_failed_tests = $Global:bash_tests_summary["TotalBashTestsFailed"]
$total_bash_tests = $Global:bash_tests_summary["TotalBashTests"]
$errorMessage = "At least one of the bash tests failed. [$total_bash_failed_tests of $total_bash_tests]"
Write-Warning $errorMessage
Write-BuildMessage -Message $errorMessage -Category Error
Set-BuildVariable TestPassed False
Write-Warning "Stop running further tests!"
return
}
Invoke-OpenSSHUninstallTest
if (($OpenSSHTestInfo -eq $null) -or (-not (Test-Path $OpenSSHTestInfo["UninstallTestResultsFile"])))

View File

@ -41,7 +41,7 @@ function Set-OpenSSHTestEnvironment
param
(
[string] $OpenSSHBinPath,
[string] $TestDataPath = "$env:SystemDrive\OpenSSHTests",
[string] $TestDataPath = "$env:SystemDrive\OpenSSHTests",
[Switch] $DebugMode,
[Switch] $NoAppVerifier,
[Switch] $PostmortemDebugging,
@ -68,7 +68,6 @@ function Set-OpenSSHTestEnvironment
$Global:OpenSSHTestInfo.Add("TestAccountPW", $OpenSSHTestAccountsPassword) # common password for all test accounts
$Global:OpenSSHTestInfo.Add("DebugMode", $DebugMode.IsPresent) # run openssh E2E in debug mode
$Script:EnableAppVerifier = -not ($NoAppVerifier.IsPresent)
if($Script:WindowsInBox = $true)
{
@ -100,8 +99,7 @@ WARNING: Following changes will be made to OpenSSH configuration
return
}
Install-OpenSSHTestDependencies
Install-OpenSSHTestDependencies
##### START: install sshd test service
#delete service if exists
@ -164,15 +162,13 @@ WARNING: Following changes will be made to OpenSSH configuration
}
Start-Service ssh-agent
#Prepare user config - known_hosts and ssh_config
$dotSshDirectoryPath = Join-Path $home .ssh
if(-not (Test-Path $dotSshDirectoryPath -PathType Container))
{
New-Item -ItemType Directory -Path $dotSshDirectoryPath -Force -ErrorAction SilentlyContinue | out-null
}
$knowHostsFilePath = Join-Path $dotSshDirectoryPath known_hosts
if (-not (Test-Path $knowHostsFilePath -PathType Leaf)) {
Copy-Item (Join-Path $Script:E2ETestDataDirectory known_hosts) $knowHostsFilePath -Force
@ -671,6 +667,38 @@ function Invoke-OpenSSHE2ETest
Pop-Location
}
<#
.Synopsis
Run UNIX bash tests using CYGWIN.
#>
function Invoke-OpenSSHBashTests
{
[string]$bashPath = [string]::Empty
# Check for cygwin
if (Test-Path $env:SystemDrive\cygwin\bin\sh.exe) {
$bashPath = "$env:SystemDrive\cygwin\bin\sh.exe"
} elseif (Test-Path $env:SystemDrive\cygwin64\bin\sh.exe) {
$bashPath = "$env:SystemDrive\cygwin64\bin\sh.exe"
} elseif (Test-Path $env:SystemDrive\tools\cygwin\bin\sh.exe) {
$bashPath = "$env:SystemDrive\tools\cygwin\bin\sh.exe"
} else {
# Install cygwin
Write-Host "Installing cygwin using chocolatey to $env:SystemDrive\cygwin folder"
choco install cygwin -y --params "/InstallDir:$env:SystemDrive\cygwin\ /NoStartMenu"
if (Test-Path $env:SystemDrive\cygwin\bin\sh.exe) {
$bashPath = "$env:SystemDrive\cygwin\bin\sh.exe"
} else {
Write-Error "Failed to install cygwin to $env:SystemDrive\cygwin folder" -ErrorAction Stop
return
}
}
$bashTestDirectory = Join-Path $repositoryRoot.FullName -ChildPath "regress"
&"$PSScriptRoot\bash_tests_iterator.ps1" -OpenSSHBinPath $Script:OpenSSHBinPath -BashTestsPath $bashTestDirectory -ShellPath $bashPath -ArtifactsDirectoryPath $bashTestDirectory
}
<#
.Synopsis
Run openssh unit tests.
@ -759,4 +787,4 @@ function Write-Log
}
}
Export-ModuleMember -Function Set-BasicTestInfo, Set-OpenSSHTestEnvironment, Clear-OpenSSHTestEnvironment, Invoke-OpenSSHSetupTest, Invoke-OpenSSHUnitTest, Invoke-OpenSSHE2ETest, Invoke-OpenSSHUninstallTest
Export-ModuleMember -Function Set-BasicTestInfo, Set-OpenSSHTestEnvironment, Clear-OpenSSHTestEnvironment, Invoke-OpenSSHSetupTest, Invoke-OpenSSHUnitTest, Invoke-OpenSSHE2ETest, Invoke-OpenSSHUninstallTest, Invoke-OpenSSHBashTests

View File

@ -1,276 +0,0 @@
param (
# Path to openssh binaries
[Parameter(Mandatory=$true)] [string] $OpenSSHBinPath,
# Path of regress folder which has all the bash testcases.
[Parameter(Mandatory=$true)] [string] $BashTestsPath,
# Path to CYGWIN / WSL.
[Parameter(Mandatory=$true)] [string] $ShellPath,
# Individual bash test file (Ex - connect.sh)
[Parameter(Mandatory=$false)] [string[]] $TestFilePath,
[Parameter(Mandatory=$false)] [string] $ArtifactsPath=".",
[switch] $SkipCleanup,
[switch] $SkipInstallSSHD
)
# Resolve the relative paths
$OpenSSHBinPath=resolve-path $OpenSSHBinPath -ErrorAction Stop | select -ExpandProperty Path
$BashTestsPath=resolve-path $BashTestsPath -ErrorAction Stop | select -ExpandProperty Path
$ShellPath=resolve-path $ShellPath -ErrorAction Stop | select -ExpandProperty Path
$ArtifactsPath=resolve-path $ArtifactsPath -ErrorAction Stop | select -ExpandProperty Path
if ($TestFilePath) {
$TestFilePath=resolve-path $TestFilePath -ErrorAction Stop | select -ExpandProperty Path
# convert to bash format
$TestFilePath=$TestFilePath -replace "\\","/"
}
# Make sure config.h exists. It is used by bashstests (Ex - sftp-glob.sh, cfgparse.sh)
# first check in $BashTestsPath folder. If not then it's parent folder. If not then in the $OpenSSHBinPath
if(Test-Path "$BashTestsPath\config.h" -PathType Leaf) {
$configPath="$BashTestsPath\config.h"
} elseif(Test-Path "$BashTestsPath\..\config.h" -PathType Leaf) {
$configPath=resolve-path "$BashTestsPath\..\config.h" -ErrorAction Stop | select -ExpandProperty Path
} elseif(Test-Path "$OpenSSHBinPath\config.h" -PathType Leaf) {
$configPath="$OpenSSHBinPath\config.h"
} else {
Write-Error "Couldn't find config.h"
exit
}
# store user directory
$user_pwd=pwd | select -ExpandProperty Path
# If we are using a SKU with desired OpenSSH binaries then we can skip these steps.
if(!$SkipInstallSSHD) {
# Make sure install-sshd.ps1 exists.
if(!(Test-Path "$PSScriptRoot\install-sshd.ps1" -PathType Leaf)) {
Write-Error "$PSScriptRoot\install-sshd.ps1 doesn't exists"
exit
}
# Make sure uninstall-sshd.ps1 exists.
if(!(Test-Path "$PSScriptRoot\uninstall-sshd.ps1" -PathType Leaf)) {
Write-Error "$PSScriptRoot\uninstall-sshd.ps1 doesn't exists"
exit
}
#copy to binary folder and execute install-sshd.ps1
Copy-Item $PSScriptRoot\install-sshd.ps1 -Force $OpenSSHBinPath
Copy-Item $PSScriptRoot\uninstall-sshd.ps1 -Force $OpenSSHBinPath
# We need ssh-agent to be installed as service to run some bash tests.
& "$OpenSSHBinPath\install-sshd.ps1"
}
try
{
# set the default shell
$registryPath = "HKLM:\Software\OpenSSH"
$dfltShell = "DefaultShell"
# Fetch the user configured default shell.
$out=(Get-ItemProperty -Path $registryPath -Name $dfltShell -ErrorAction SilentlyContinue)
if($out) {
$user_default_shell = $out.$dfltShell
Write-Output "User configured default shell: $user_default_shell"
}
if (!(Test-Path $registryPath)) {
# start and stop the sshd so that "HKLM:\Software\OpenSSH" registry path is created.
Start-Service sshd -ErrorAction Stop
Stop-Service sshd -ErrorAction SilentlyContinue
}
Set-ItemProperty -Path $registryPath -Name $dfltShell -Value $ShellPath -Force
$out=(Get-ItemProperty -Path $registryPath -Name $dfltShell -ErrorAction SilentlyContinue)
if($out.$dfltShell -ne $ShellPath) {
Write-Output "Failed to set HKLM:\Software\OpenSSH\DefaultShell to $ShellPath"
exit
}
# Prepend shell path to PATH. This is required to make the shell commands (like sleep, cat, etc) work properly.
$env:TEST_SHELL_PATH=$ShellPath -replace "\\","/"
$TEST_SHELL_DIR=split-path $ShellPath
if(!$env:path.StartsWith($TEST_SHELL_DIR, "CurrentCultureIgnoreCase"))
{
$env:path=$TEST_SHELL_DIR+";"+$env:path
}
$BashTestsPath=$BashTestsPath -replace "\\","/"
Push-location $BashTestsPath
# BUILDDIR: config.h location.
# BUILDDIR is used by bashstests (Ex - sftp-glob.sh, cfgparse.sh)
$BUILDDIR=resolve-path(split-path $configpath) | select -ExpandProperty Path
$tmp=&$ShellPath -c pwd
if ($tmp.StartsWith("/cygdrive/")) {
$shell_drv_fmt="/cygdrive/" # "/cygdrive/" - cygwin
$BUILDDIR=&$ShellPath -c "cygpath -u '$BUILDDIR'"
$OpenSSHBinPath_shell_fmt=&$ShellPath -c "cygpath -u '$OpenSSHBinPath'"
$BashTestsPath=&$ShellPath -c "cygpath -u '$BashTestsPath'"
} elseif ($tmp.StartsWith("/mnt/")) {
$shell_drv_fmt="/mnt/" # "/mnt/" - WSL bash
$BUILDDIR=&$ShellPath -c "wslpath -u '$BUILDDIR'"
$OpenSSHBinPath_shell_fmt=&$ShellPath -c "wslpath -u '$OpenSSHBinPath'"
$BashTestsPath=&$ShellPath -c "wslpath -u '$BashTestsPath'"
}
#set the environment variables.
$env:ShellPath=$ShellPath
$env:SSH_TEST_ENVIRONMENT=1
$env:TEST_SSH_TRACE="yes"
$env:TEST_SHELL="/bin/sh"
$env:TEST_SSH_PORT=22
$env:TEST_SSH_SSH=$OpenSSHBinPath_shell_fmt+"/ssh.exe"
$env:TEST_SSH_SSHD=$OpenSSHBinPath_shell_fmt+"/sshd.exe"
$env:TEST_SSH_SSHAGENT=$OpenSSHBinPath_shell_fmt+"/ssh-agent.exe"
$env:TEST_SSH_SSHADD=$OpenSSHBinPath_shell_fmt+"/ssh-add.exe"
$env:TEST_SSH_SSHKEYGEN=$OpenSSHBinPath_shell_fmt+"/ssh-keygen.exe"
$env:TEST_SSH_SSHKEYSCAN=$OpenSSHBinPath_shell_fmt+"/ssh-keyscan.exe"
$env:TEST_SSH_SFTP=$OpenSSHBinPath_shell_fmt+"/sftp.exe"
$env:TEST_SSH_SFTPSERVER=$OpenSSHBinPath_shell_fmt+"/sftp-server.exe"
$env:TEST_SSH_SCP=$OpenSSHBinPath_shell_fmt+"/scp.exe"
$env:BUILDDIR=$BUILDDIR
$env:TEST_WINDOWS_SSH=1
$user = &"$env:windir\system32\whoami.exe"
if($user.Contains($env:COMPUTERNAME.ToLower())) {
# for local accounts, skip COMPUTERNAME
$user = Split-Path $user -leaf
$env:TEST_SSH_USER=$user
} else {
# for domain user convert "domain\user" to "domain/user".
$user = $user -replace "\\","/"
$env:TEST_SSH_USER = $user
$env:TEST_SSH_USER_DOMAIN = Split-Path $user
}
# output to terminal
Write-Output "USER: $env:TEST_SSH_USER"
Write-Output "DOMAIN: $env:TEST_SSH_USER_DOMAIN"
Write-Output "OpenSSHBinPath: $OpenSSHBinPath_shell_fmt"
Write-Output "BUILDDIR: $BUILDDIR"
Write-Output "BashTestsPath: $BashTestsPath"
# remove, create the temp test directory
$temp_test_path="temp_test"
$null = Remove-Item -Recurse -Force $temp_test_path -ErrorAction SilentlyContinue
$null = New-Item -ItemType directory -Path $temp_test_path -ErrorAction Stop
# remove the summary, output files.
$test_summary="$ArtifactsPath\\bashtest_summary.txt"
$test_output="$ArtifactsPath\\bashtest_output.txt"
$null = Remove-Item -Force $test_summary -ErrorAction SilentlyContinue
$null = Remove-Item -Force $test_output -ErrorAction SilentlyContinue
[int]$total_tests = 0
[int]$total_tests_passed = 0
[int]$total_tests_failed = 0
[string]$failed_testcases = [string]::Empty
# These are the known failed testcases.
# agent.sh, krl.sh - User Cert authentication fails
# key-options.sh - pty testcases are failing (bug in conpty. conpty fails to launch cygwin bash)
# integrity.sh - It's dependent on regress\modpipe.exe, test is complicated. Need to debug more
# authinfo.sh - spawned conpty inherits all the environment variables from sshd.
# forward-control.sh - Need to debug more.
[string]$known_failed_testcases = "agent.sh key-options.sh forward-control.sh integrity.sh krl.sh authinfo.sh"
[string]$known_failed_testcases_skipped = [string]::Empty
$start_time = (Get-Date)
if($TestFilePath) {
# User can specify individual test file path.
$all_tests=$TestFilePath
} else {
# picking the gawk.exe from bash folder.
# TODO - check if gawk.exe is present in WSL.
$all_tests=gawk.exe 'sub(/.*LTESTS=/,""""){f=1} f{print $1; if (!/\\\\/) exit}' Makefile
}
foreach($test_case in $all_tests) {
if($TestFilePath) {
$TEST=$test_case
} else {
if(!$test_case.Contains(".sh")) {
$TEST=$BashTestsPath+"/"+$test_case+".sh"
} else {
$TEST=$BashTestsPath+"/"+$test_case
}
}
$test_case_name = [System.IO.Path]::GetFileName($TEST)
if($known_failed_testcases.Contains($test_case_name))
{
Write-Output "Skip the known failed test:$test_case_name"
$known_failed_testcases_skipped = $known_failed_testcases_skipped + "$test_case_name "
}
else
{
$msg="Executing $test_case_name " +[System.DateTime]::Now
Write-Output $msg
&$env:ShellPath -c "/usr/bin/sh $BashTestsPath/test-exec.sh $BashTestsPath/$temp_test_path $TEST" #>$null 2>&1
if($?)
{
$msg="$test_case_name PASSED " +[System.DateTime]::Now
Write-Output $msg
$total_tests_passed++
}
else
{
$msg="$test_case_name FAILED " +[System.DateTime]::Now
Write-Output $msg
$total_tests_failed++
$failed_testcases=$failed_testcases + "$test_case_name "
}
}
$total_tests++
}
$end_time = (Get-Date)
# Create artifacts
"Start time: $start_time" | Out-File -FilePath $test_summary -Append
"End time: $end_time" | Out-File -FilePath $test_summary -Append
"Total execution time: " + (NEW-TIMESPAN -Start $start_time -End $end_time).ToString("hh\:mm\:ss") | Out-File -FilePath $test_summary -Append
"Tests executed: $total_tests" | Out-File -FilePath $test_summary -Append
"Tests passed: $total_tests_passed" | Out-File -FilePath $test_summary -Append
"Tests failed: $total_tests_failed" | Out-File -FilePath $test_summary -Append
"Failed tests: $failed_testcases" | Out-File -FilePath $test_summary -Append
"Skipped known failed tests: $known_failed_testcases_skipped" | Out-File -FilePath $test_summary -Append
Write-Output "Artifacts are saved to $ArtifactsPath"
#output the summary
Write-Output "================================="
cat $test_summary
Write-Output "================================="
}
finally
{
# remove temp test directory
if (!$SkipCleanup)
{
# remove temp test folder
&$ShellPath -c "rm -rf $BashTestsPath/temp_test"
if(!$SkipInstallSSHD) {
# Uninstall the sshd, ssh-agent service
& "$PSScriptRoot\uninstall-sshd.ps1"
}
# Remove the test environment variable
Remove-Item ENV:\SSH_TEST_ENVIRONMENT
# Revert to user configured default shell.
if($user_default_shell) {
Set-ItemProperty -Path $registryPath -Name $dfltShell -Value $user_default_shell -Force
$out=(Get-ItemProperty -Path $registryPath -Name $dfltShell -ErrorAction SilentlyContinue)
if($out.$dfltShell -eq $user_default_shell) {
Write-Output "Reverted user configured default shell to $user_default_shell"
} else {
Write-Output "Failed to set HKLM:\Software\OpenSSH\DefaultShell to $user_default_shell"
}
} else {
Remove-ItemProperty -Path $registryPath -Name $dfltShell -ErrorAction SilentlyContinue
}
}
Push-location $user_pwd
}

View File

@ -0,0 +1,286 @@
param (
# Path to openssh binaries
[Parameter(Mandatory=$true)] [string] $OpenSSHBinPath,
# Path of regress folder which has all the bash testcases.
[Parameter(Mandatory=$true)] [string] $BashTestsPath,
# Path to CYGWIN / WSL.
[Parameter(Mandatory=$true)] [string] $ShellPath,
# Individual bash test file (Ex - connect.sh, scp.sh)
[Parameter(Mandatory=$false)] [string[]] $TestFilePath,
[Parameter(Mandatory=$false)] [string] $ArtifactsDirectoryPath=".",
[switch] $SkipCleanup,
[switch] $SkipInstallSSHD
)
$ErrorActionPreference = 'Continue'
# Resolve the relative paths
$OpenSSHBinPath = Resolve-Path $OpenSSHBinPath -ErrorAction Stop | select -ExpandProperty Path
$BashTestsPath = Resolve-Path $BashTestsPath -ErrorAction Stop | select -ExpandProperty Path
$ShellPath = Resolve-Path $ShellPath -ErrorAction Stop | select -ExpandProperty Path
$ArtifactsDirectoryPath = Resolve-Path $ArtifactsDirectoryPath -ErrorAction Stop | select -ExpandProperty Path
if ($TestFilePath) {
$TestFilePath = Resolve-Path $TestFilePath -ErrorAction Stop | select -ExpandProperty Path
# convert to bash format
$TestFilePath = $TestFilePath -replace "\\","/"
}
# Make sure config.h exists. It is used in some bashstests (Ex - sftp-glob.sh, cfgparse.sh)
# first check in $BashTestsPath folder. If not then it's parent folder. If not then in the $OpenSSHBinPath
if(Test-Path "$BashTestsPath\config.h" -PathType Leaf) {
$configPath = "$BashTestsPath\config.h"
} elseif(Test-Path "$BashTestsPath\..\config.h" -PathType Leaf) {
$configPath = Resolve-Path "$BashTestsPath\..\config.h" -ErrorAction Stop | select -ExpandProperty Path
} elseif(Test-Path "$OpenSSHBinPath\config.h" -PathType Leaf) {
$configPath = "$OpenSSHBinPath\config.h"
} else {
Write-Error "Couldn't find config.h"
exit
}
$user_pwd = pwd | select -ExpandProperty Path
# If we are using a SKU with desired OpenSSH binaries then we can skip these steps.
if(!$SkipInstallSSHD) {
# Make sure install-sshd.ps1 exists.
# This is required only for ssh-agent related bash tests.
if(!(Test-Path "$PSScriptRoot\install-sshd.ps1" -PathType Leaf)) {
Write-Error "$PSScriptRoot\install-sshd.ps1 doesn't exists"
exit
}
# Make sure uninstall-sshd.ps1 exists.
if(!(Test-Path "$PSScriptRoot\uninstall-sshd.ps1" -PathType Leaf)) {
Write-Error "$PSScriptRoot\uninstall-sshd.ps1 doesn't exists"
exit
}
#copy to binary folder and execute install-sshd.ps1
Copy-Item $PSScriptRoot\install-sshd.ps1 -Force $OpenSSHBinPath
Copy-Item $PSScriptRoot\uninstall-sshd.ps1 -Force $OpenSSHBinPath
# We need ssh-agent to be installed as service to run some bash tests.
& "$OpenSSHBinPath\install-sshd.ps1"
}
try
{
# set the default shell
$registryPath = "HKLM:\Software\OpenSSH"
$dfltShell = "DefaultShell"
# Fetch the user configured default shell.
$out = (Get-ItemProperty -Path $registryPath -Name $dfltShell -ErrorAction SilentlyContinue)
if ($out) {
$user_default_shell = $out.$dfltShell
Write-Output "User configured default shell: $user_default_shell"
}
if ($user_default_shell -ne $ShellPath)
{
if (!(Test-Path $registryPath)) {
# start and stop the sshd so that "HKLM:\Software\OpenSSH" registry path is created.
Start-Service sshd -ErrorAction Stop
Stop-Service sshd -ErrorAction SilentlyContinue
}
Set-ItemProperty -Path $registryPath -Name $dfltShell -Value $ShellPath -Force
$out = (Get-ItemProperty -Path $registryPath -Name $dfltShell -ErrorAction SilentlyContinue)
if ($out.$dfltShell -ne $ShellPath) {
Write-Output "Failed to set HKLM:\Software\OpenSSH\DefaultShell to $ShellPath"
exit
}
Write-Output "Successfully set the default shell (HKLM:\Software\OpenSSH\DefaultShell) to $ShellPath"
}
# Prepend shell path to PATH. This is required to make the shell commands (like sleep, cat, etc) work properly.
$env:TEST_SHELL_PATH = $ShellPath -replace "\\","/"
$TEST_SHELL_DIR = split-path $ShellPath
if(!$env:path.StartsWith($TEST_SHELL_DIR, "CurrentCultureIgnoreCase"))
{
$env:path = $TEST_SHELL_DIR + ";" + $env:path
}
$BashTestsPath = $BashTestsPath -replace "\\","/"
Push-location $BashTestsPath
# BUILDDIR: config.h location.
# BUILDDIR is used by bashstests (Ex - sftp-glob.sh, cfgparse.sh)
$BUILDDIR = Resolve-Path(split-path $configpath) | select -ExpandProperty Path
$tmp = &$ShellPath -c pwd
if ($tmp.StartsWith("/cygdrive/")) {
$shell_drv_fmt = "/cygdrive/" # cygwin
$BUILDDIR = &$ShellPath -c "cygpath -u '$BUILDDIR'"
$OpenSSHBinPath_shell_fmt=&$ShellPath -c "cygpath -u '$OpenSSHBinPath'"
$BashTestsPath = &$ShellPath -c "cygpath -u '$BashTestsPath'"
} elseif ($tmp.StartsWith("/mnt/")) {
$shell_drv_fmt = "/mnt/" # WSL bash
$BUILDDIR = &$ShellPath -c "wslpath -u '$BUILDDIR'"
$OpenSSHBinPath_shell_fmt=&$ShellPath -c "wslpath -u '$OpenSSHBinPath'"
$BashTestsPath = &$ShellPath -c "wslpath -u '$BashTestsPath'"
}
#set the environment variables.
$env:ShellPath = $ShellPath
$env:SSH_TEST_ENVIRONMENT = 1
$env:TEST_SSH_TRACE = "yes"
$env:TEST_SHELL = "/bin/sh"
$env:TEST_SSH_PORT = 22
$env:TEST_SSH_SSH = $OpenSSHBinPath_shell_fmt+"/ssh.exe"
$env:TEST_SSH_SSHD = $OpenSSHBinPath_shell_fmt+"/sshd.exe"
$env:TEST_SSH_SSHAGENT = $OpenSSHBinPath_shell_fmt+"/ssh-agent.exe"
$env:TEST_SSH_SSHADD = $OpenSSHBinPath_shell_fmt+"/ssh-add.exe"
$env:TEST_SSH_SSHKEYGEN = $OpenSSHBinPath_shell_fmt+"/ssh-keygen.exe"
$env:TEST_SSH_SSHKEYSCAN = $OpenSSHBinPath_shell_fmt+"/ssh-keyscan.exe"
$env:TEST_SSH_SFTP = $OpenSSHBinPath_shell_fmt+"/sftp.exe"
$env:TEST_SSH_SFTPSERVER = $OpenSSHBinPath_shell_fmt+"/sftp-server.exe"
$env:TEST_SSH_SCP = $OpenSSHBinPath_shell_fmt+"/scp.exe"
$env:BUILDDIR = $BUILDDIR
$env:TEST_WINDOWS_SSH = 1
$user = &"$env:windir\system32\whoami.exe"
if($user.Contains($env:COMPUTERNAME.ToLower())) {
# for local accounts, skip COMPUTERNAME
$user = Split-Path $user -leaf
$env:TEST_SSH_USER = $user
} else {
# for domain user convert "domain\user" to "domain/user".
$user = $user -replace "\\","/"
$env:TEST_SSH_USER = $user
$env:TEST_SSH_USER_DOMAIN = Split-Path $user
}
Write-Output "USER: $env:TEST_SSH_USER"
Write-Output "DOMAIN: $env:TEST_SSH_USER_DOMAIN"
Write-Output "OpenSSHBinPath: $OpenSSHBinPath_shell_fmt"
Write-Output "BUILDDIR: $BUILDDIR"
Write-Output "BashTestsPath: $BashTestsPath"
# remove, create the temp test directory
$temp_test_path = "temp_test"
$null = Remove-Item -Recurse -Force $temp_test_path -ErrorAction SilentlyContinue
$null = New-Item -ItemType directory -Path $temp_test_path -Force -ErrorAction Stop
# remove the summary, output files.
$bash_test_summary = "$ArtifactsDirectoryPath\bash_tests_summary.txt"
$bash_test_log_file = "$ArtifactsDirectoryPath\bash_tests_output.log"
$null = Remove-Item -Force $bash_test_summary -ErrorAction SilentlyContinue
$null = Remove-Item -Force $bash_test_log_file -ErrorAction SilentlyContinue
[int]$total_tests = 0
[int]$total_tests_passed = 0
[int]$total_tests_failed = 0
[string]$failed_testcases = [string]::Empty
# These are the known failed testcases.
$known_failed_testcases = @("agent.sh", "key-options.sh", "forward-control.sh", "integrity.sh", "krl.sh", "authinfo.sh")
$known_failed_testcases_skipped = @()
$start_time = (Get-Date)
if($TestFilePath) {
# User can specify individual test file path.
$all_tests = $TestFilePath
} else {
# picking the gawk.exe from bash folder.
# TODO - check if gawk.exe is present in WSL.
$all_tests = gawk.exe 'sub(/.*LTESTS=/,""""){f=1} f{print $1; if (!/\\\\/) exit}' Makefile
}
Write-Output ""
foreach ($test_file in $all_tests) {
if ($TestFilePath) {
$TEST = $test_file
} else {
if (!$test_file.Contains(".sh")) {
$TEST = $BashTestsPath + "/" + $test_file + ".sh"
} else {
$TEST = $BashTestsPath + "/" + $test_file
}
}
$test_file_name = [System.IO.Path]::GetFileName($TEST)
if ($known_failed_testcases.Contains($test_file_name))
{
Write-Output "Skip the known failed test:$test_file_name [$($all_tests.IndexOf($test_file) + 1) of $($all_tests.count)]"
$known_failed_testcases_skipped += "$test_file_name"
}
else
{
$msg = "Run $test_file_name [$($all_tests.IndexOf($test_file) + 1) of $($all_tests.count)] " + [System.DateTime]::Now
Write-Output $msg | Tee-Object -FilePath $bash_test_log_file -Append -ErrorAction Stop
&$env:ShellPath -c "/usr/bin/sh $BashTestsPath/test-exec.sh $BashTestsPath/$temp_test_path $TEST 2>&1" | Out-File -FilePath $bash_test_log_file -Append -ErrorAction Stop
if ($?)
{
$msg = "$test_file_name PASSED " + [System.DateTime]::Now
Write-Output $msg | Tee-Object -FilePath $bash_test_log_file -Append -ErrorAction Stop
$total_tests_passed++
}
else
{
$msg = "$test_file_name FAILED " + [System.DateTime]::Now
Write-Output $msg | Tee-Object -FilePath $bash_test_log_file -Append -ErrorAction Stop
$total_tests_failed++
$failed_testcases = $failed_testcases + "$test_file_name "
}
}
$total_tests++
}
$end_time = (Get-Date)
# Create artifacts
$Global:bash_tests_summary = [ordered]@{
"StartTime" = $start_time.ToString();
"EndTime" = $end_time.ToString();
"TotalExecutionTime" = (NEW-TIMESPAN -Start $start_time -End $end_time).ToString("hh\:mm\:ss");
"TotalBashTests" = $total_tests;
"TotalBashTestsPassed" = $total_tests_passed;
"TotalBashTestsFailed" = $total_tests_failed;
"TotalBashTestsSkipped" = $known_failed_testcases_skipped.Count;
"FailedBashTests" = $failed_testcases;
"SkippedBashTests" = $known_failed_testcases_skipped -join ', ';
"BashTestSummaryFile" = $bash_test_summary
"BashTestLogFile" = $bash_test_log_file
}
$Global:bash_tests_summary | ConvertTo-Json | Out-File -FilePath $bash_test_summary
#output the summary
Write-Output "`n============================================"
Get-Content -Raw $bash_test_summary
Write-Output "============================================`n"
}
finally
{
# remove temp test directory
if (!$SkipCleanup)
{
# remove temp test folder
&$ShellPath -c "rm -rf $BashTestsPath/temp_test"
if(!$SkipInstallSSHD) {
# Uninstall the sshd, ssh-agent service
& "$PSScriptRoot\uninstall-sshd.ps1"
}
# Remove the test environment variable
Remove-Item ENV:\SSH_TEST_ENVIRONMENT
# Revert to user configured default shell.
if($user_default_shell) {
Set-ItemProperty -Path $registryPath -Name $dfltShell -Value $user_default_shell -Force
$out=(Get-ItemProperty -Path $registryPath -Name $dfltShell -ErrorAction SilentlyContinue)
if($out.$dfltShell -eq $user_default_shell) {
Write-Output "Reverted user configured default shell to $user_default_shell"
} else {
Write-Output "Failed to set HKLM:\Software\OpenSSH\DefaultShell to $user_default_shell"
}
} else {
Remove-ItemProperty -Path $registryPath -Name $dfltShell -ErrorAction SilentlyContinue
}
}
Push-location $user_pwd
}

View File

@ -1709,166 +1709,187 @@ build_exec_command(const char * command)
return cmd_sp;
}
/*
* cmd is internally decoarated with a set of '"'
* to account for any spaces within the commandline
* the double quotes and backslash is escaped if needed
* this decoration is done only when additional arguments are passed in argv
*/
char *
build_commandline_string(const char* cmd, char *const argv[], BOOLEAN prepend_module_path)
{
char *cmdline, *t, *tmp = NULL, *path = NULL, *ret = NULL;
char * const *t1;
DWORD cmdline_len = 0, path_len = 0;
int add_module_path = 0;
/*
* cmd is internally decoarated with a set of '"'
* to account for any spaces within the commandline
* the double quotes and backslash is escaped if needed
* this decoration is done only when additional arguments are passed in argv
*/
char *
build_commandline_string(const char* cmd, char *const argv[], BOOLEAN prepend_module_path)
{
char *cmdline, *t, *tmp = NULL, *path = NULL, *ret = NULL;
char * const *t1;
DWORD cmdline_len = 0, path_len = 0;
int add_module_path = 0;
if (!cmd) {
error("%s invalid argument cmd:%s", __func__, cmd);
return NULL;
}
if (!(path = _strdup(cmd))) {
error("failed to duplicate %s", cmd);
return NULL;
}
path_len = (DWORD)strlen(path);
if (is_bash_test_env()) {
memset(path, 0, path_len + 1);
bash_to_win_path(cmd, path, path_len + 1);
path_len = (DWORD)strlen(path);
}
if (!is_absolute_path(path) && prepend_module_path)
add_module_path = 1;
/* compute total cmdline len*/
if (add_module_path)
cmdline_len += (DWORD)strlen(__progdir) + 1 + (DWORD)strlen(path) + 1 + 2;
else
cmdline_len += (DWORD)strlen(path) + 1 + 2;
if (argv) {
t1 = argv;
while (*t1) {
char *p = *t1++;
for (int i = 0; i < (int)strlen(p); i++) {
if (p[i] == '\\') {
char * b = p + i;
int additional_backslash = 0;
int backslash_count = 0;
/*
Backslashes are interpreted literally, unless they immediately
precede a double quotation mark.
*/
while (b != NULL && *b == '\\') {
backslash_count++;
b++;
if (b != NULL && *b == '\"') {
additional_backslash = 1;
break;
}
}
cmdline_len += backslash_count * (additional_backslash + 1);
i += backslash_count - 1;
}
else if (p[i] == '\"')
/* backslash will be added for every double quote.*/
cmdline_len += 2;
else
cmdline_len++;
}
cmdline_len += 1 + 2; /*for "around cmd arg and traling space*/
}
}
if ((cmdline = malloc(cmdline_len)) == NULL) {
errno = ENOMEM;
goto cleanup;
}
t = cmdline;
*t++ = '\"';
if (add_module_path) {
/* add current module path to start if needed */
memcpy(t, __progdir, strlen(__progdir));
t += strlen(__progdir);
*t++ = '\\';
}
if (path[0] != '\"') {
/* If path is <executable_path> <arg> then we should add double quotes after <executable_path> i.e., "<executable_path>" <arg> should be passed to CreateProcess().
* Example - If path is C:\cygwin64\bin\bash.exe /cygdrive/e/openssh-portable-latestw_all/openssh-portable/regress/scp-ssh-wrapper.sh then
* we should pass "C:\cygwin64\bin\bash.exe" /cygdrive/e/openssh-portable-latestw_all/openssh-portable/regress/scp-ssh-wrapper.sh
* to the CreateProcess() otherwise CreateProcess() will fail with error code 2.
*/
if (strstr(path, ".exe") && (tmp = strstr(strstr(path, ".exe"), " ")))
{
size_t tmp_pos = tmp - path;
memcpy(t, path, tmp_pos);
t += tmp_pos;
*t++ = '\"';
memcpy(t, tmp, strlen(path) - tmp_pos);
t += (strlen(path) - tmp_pos);
}
else {
memcpy(t, path, path_len);
t += path_len;
*t++ = '\"';
}
}
else {
/*path already contains "*/
memcpy(t, path + 1, path_len - 1);
t += path_len - 1;
}
*t = '\0';
t = cmdline + strlen(cmdline);
if (argv) {
t1 = argv;
while (*t1) {
*t++ = ' ';
char * p1 = *t1++;
BOOL add_quotes = FALSE;
/* leave as is if the command is surrounded by single quotes*/
if (p1[0] != '\'')
for (int i = 0; i < (int)strlen(p1); i++) {
if (p1[i] == ' ') {
add_quotes = TRUE;
break;
}
}
if (add_quotes)
*t++ = '\"';
for (int i = 0; i < (int)strlen(p1); i++) {
if (p1[i] == '\\') {
char * b = p1 + i;
int additional_backslash = 0;
int backslash_count = 0;
/*
* Backslashes are interpreted literally, unless they immediately
* precede a double quotation mark.
*/
while (b != NULL && *b == '\\') {
backslash_count++;
b++;
if (b != NULL && *b == '\"') {
additional_backslash = 1;
break;
}
}
i += backslash_count - 1;
int escaped_backslash_count = backslash_count * (additional_backslash + 1);
while (escaped_backslash_count--)
*t++ = '\\';
}
else if (p1[i] == '\"') {
/* Add backslash for every double quote.*/
*t++ = '\\';
*t++ = '\"';
}
else
*t++ = p1[i];
}
if (add_quotes)
*t++ = '\"';
}
}
*t = '\0';
ret = cmdline;
cmdline = NULL;
cleanup:
if (path)
free(path);
if (cmdline)
free(cmdline);
return ret;
}
if (!cmd) {
error("%s invalid argument cmd:%s", __func__, cmd);
return NULL;
}
if (!(path = _strdup(cmd))) {
error("failed to duplicate %s", cmd);
return NULL;
}
path_len = (DWORD)strlen(path);
if (is_bash_test_env()) {
memset(path, 0, path_len + 1);
bash_to_win_path(cmd, path, path_len + 1);
}
if (!is_absolute_path(path) && prepend_module_path)
add_module_path = 1;
/* compute total cmdline len*/
if (add_module_path)
cmdline_len += (DWORD)strlen(__progdir) + 1 + (DWORD)strlen(path) + 1 + 2;
else
cmdline_len += (DWORD)strlen(path) + 1 + 2;
if (argv) {
t1 = argv;
while (*t1) {
char *p = *t1++;
for (int i = 0; i < (int)strlen(p); i++) {
if (p[i] == '\\') {
char * b = p + i;
int additional_backslash = 0;
int backslash_count = 0;
/*
Backslashes are interpreted literally, unless they immediately
precede a double quotation mark.
*/
while (b != NULL && *b == '\\') {
backslash_count++;
b++;
if (b != NULL && *b == '\"') {
additional_backslash = 1;
break;
}
}
cmdline_len += backslash_count * (additional_backslash + 1);
i += backslash_count - 1;
}
else if (p[i] == '\"')
/* backslash will be added for every double quote.*/
cmdline_len += 2;
else
cmdline_len++;
}
cmdline_len += 1 + 2; /*for "around cmd arg and traling space*/
}
}
if ((cmdline = malloc(cmdline_len)) == NULL) {
errno = ENOMEM;
goto cleanup;
}
t = cmdline;
*t++ = '\"';
if (add_module_path) {
/* add current module path to start if needed */
memcpy(t, __progdir, strlen(__progdir));
t += strlen(__progdir);
*t++ = '\\';
}
if (path[0] != '\"') {
memcpy(t, path, path_len);
t += path_len;
*t++ = '\"';
}
else {
/*path already contains "*/
memcpy(t, path + 1, path_len - 1);
t += path_len - 1;
}
*t = '\0';
t = cmdline + strlen(cmdline);
if (argv) {
t1 = argv;
while (*t1) {
*t++ = ' ';
char * p1 = *t1++;
BOOL add_quotes = FALSE;
/* leave as is if the command is surrounded by single quotes*/
if (p1[0] != '\'')
for (int i = 0; i < (int)strlen(p1); i++) {
if (p1[i] == ' ') {
add_quotes = TRUE;
break;
}
}
if (add_quotes)
*t++ = '\"';
for (int i = 0; i < (int)strlen(p1); i++) {
if (p1[i] == '\\') {
char * b = p1 + i;
int additional_backslash = 0;
int backslash_count = 0;
/*
* Backslashes are interpreted literally, unless they immediately
* precede a double quotation mark.
*/
while (b != NULL && *b == '\\') {
backslash_count++;
b++;
if (b != NULL && *b == '\"') {
additional_backslash = 1;
break;
}
}
i += backslash_count - 1;
int escaped_backslash_count = backslash_count * (additional_backslash + 1);
while (escaped_backslash_count--)
*t++ = '\\';
}
else if (p1[i] == '\"') {
/* Add backslash for every double quote.*/
*t++ = '\\';
*t++ = '\"';
}
else
*t++ = p1[i];
}
if (add_quotes)
*t++ = '\"';
}
}
*t = '\0';
ret = cmdline;
cmdline = NULL;
cleanup:
if (path)
free(path);
if (cmdline)
free(cmdline);
return ret;
}
BOOL
is_bash_test_env()
{

View File

@ -127,6 +127,11 @@ ReadThread(_In_ LPVOID lpParameter)
pio->sync_read_status.error = GetLastError();
goto done;
}
/* If there is no data to be read then set the error to ERROR_HANDLE_EOF */
if (!pio->sync_read_status.transferred) {
pio->sync_read_status.error = ERROR_HANDLE_EOF;
}
}
done:

View File

@ -1044,7 +1044,7 @@ char * build_commandline_string(const char* cmd, char *const argv[], BOOLEAN pre
* spawned child will run as as_user if its not NULL
*/
static int
spawn_child_internal(char* cmd, char *const argv[], HANDLE in, HANDLE out, HANDLE err, unsigned long flags, HANDLE* as_user, BOOLEAN prepend_module_path)
spawn_child_internal(const char* cmd, char *const argv[], HANDLE in, HANDLE out, HANDLE err, unsigned long flags, HANDLE* as_user, BOOLEAN prepend_module_path)
{
PROCESS_INFORMATION pi;
STARTUPINFOW si;
@ -1262,7 +1262,7 @@ posix_spawn_internal(pid_t *pidp, const char *path, const posix_spawn_file_actio
if (_putenv_s(POSIX_FD_STATE, fd_info) != 0)
goto cleanup;
i = spawn_child_internal(argv[0], argv + 1, stdio_handles[STDIN_FILENO], stdio_handles[STDOUT_FILENO], stdio_handles[STDERR_FILENO], sc_flags, user_token, prepend_module_path);
i = spawn_child_internal(path, argv + 1, stdio_handles[STDIN_FILENO], stdio_handles[STDOUT_FILENO], stdio_handles[STDERR_FILENO], sc_flags, user_token, prepend_module_path);
if (i == -1)
goto cleanup;
if (pidp)

View File

@ -115,7 +115,6 @@ get_user_groups()
}
for (DWORD i = 0; i < group_buf->GroupCount; i++) {
/* only bother with group thats are 'enabled' from a security perspective */
if ((group_buf->Groups[i].Attributes & SE_GROUP_ENABLED) == 0 ||
!IsValidSid(group_buf->Groups[i].Sid))
@ -278,6 +277,7 @@ int
ga_match_pattern_list(const char *group_pattern)
{
int i, found = 0;
char *tmp = NULL;
/* group retrieval is expensive, optmizing the common case scenario - only one group with no wild cards and no negation */
if (!strchr(group_pattern, ',') && !strchr(group_pattern, '?') &&
@ -287,8 +287,15 @@ ga_match_pattern_list(const char *group_pattern)
if (get_user_groups() == -1)
fatal("unable to retrieve group info for user %s", user_name);
/* For domain groups we need special handling.
* We support both "domain\group_name" and "domain/group_name" formats.
*/
if (tmp = strstr(group_pattern, "/"))
*tmp = '\\';
for (i = 0; i < ngroups; i++) {
switch (match_pattern_list(groups_byname[i], group_pattern, 0)) {
/* Group names are case insensitive */
switch (match_pattern_list(groups_byname[i], group_pattern, 1)) {
case -1:
return 0; /* Negated match wins */
case 0:

10
match.c
View File

@ -177,8 +177,14 @@ match_usergroup_pattern_list(const char *string, const char *pattern)
#ifdef HAVE_CYGWIN
/* Windows usernames may be Unicode and are not case sensitive */
return cygwin_ug_match_pattern_list(string, pattern);
#elseif WINDOWS
if (match_pattern_list(ci->user, arg, 1) != 1)
#elif WINDOWS
/* We support both domain/username and domain\\username format */
char *tmp = NULL;
if (tmp = strstr(pattern, "/"))
*tmp = '\\';
/* Windows usernames are case insensitive */
return match_pattern_list(string, pattern, 1);
#else
/* Case insensitive match */
return match_pattern_list(string, pattern, 0);

View File

@ -26,8 +26,14 @@ timingsafe_bcmp(const void *b1, const void *b2, size_t n)
const unsigned char *p1 = b1, *p2 = b2;
int ret = 0;
for (; n > 0; n--)
for (; n > 0; n--) {
#ifdef WINDOWS
if (*p1 == '\r' && *(p1 + 1) == '\n' && *p2 == '\n')
p1++;
#endif // WINDOWS
ret |= *p1++ ^ *p2++;
}
return (ret != 0);
}

View File

@ -25,7 +25,7 @@ start_client()
if test $n -gt 60; then
if [ "$os" == "windows" ]; then
# We can't kill windows process from cygwin / wsl so use "stop-process"
powershell.exe /c "stop-process -id $client_pid"
powershell.exe /c "stop-process -id $client_pid" >/dev/null 2>&1
else
kill $client_pid
fi
@ -39,8 +39,8 @@ stop_client()
pid=`cat $pidfile`
if [ "$os" == "windows" ]; then
# We can't kill windows process from cygwin / wsl so use "stop-process"
powershell.exe /c "stop-process -id $pid"
powershell.exe /c "stop-process -name sleep"
powershell.exe /c "stop-process -id $pid" >/dev/null 2>&1
powershell.exe /c "stop-process -name sleep" >/dev/null 2>&1
else
if [ ! -z "$pid" ]; then
kill $pid
@ -174,6 +174,9 @@ for i in $params; do
trace "test spec $spec"
result=`${SUDO} ${SSHD} -f $OBJ/sshd_config -T -C "$spec" | \
awk '$1=="banner"{print $2}'`
if [ "$os" == "windows" ]; then
result=${result/$'\r'/} # remove CR (carriage return)
fi
if [ "$result" != "$expected" ]; then
fail "match $config expected $expected got $result"
fi

View File

@ -29,8 +29,12 @@ start_client()
sleep 1
n=`expr $n + 1`
if test $n -gt 60; then
kill $client_pid
fatal "timeout waiting for background ssh"
if [ "$os" == "windows" ]; then
powershell.exe /c "stop-process -Id $client_pid -Force" >/dev/null 2>&1
else
kill $client_pid
fatal "timeout waiting for background ssh"
fi
fi
done
return $r
@ -53,10 +57,14 @@ expect_client_fail()
stop_client()
{
pid=`cat $pidfile`
if [ ! -z "$pid" ]; then
kill $pid
if [ "$os" == "windows" ]; then
powershell.exe /c "stop-process -Id $pid -Force" >/dev/null 2>&1
else
if [ ! -z "$pid" ]; then
kill $pid
fi
wait
fi
wait
}
cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak

View File

@ -4,7 +4,11 @@
tid="hostkey rotate"
# Need full names here since they are used in HostKeyAlgorithms
HOSTKEY_TYPES="`${SSH} -Q key-plain`"
if [ "$os" == "windows" ]; then
HOSTKEY_TYPES=`${SSH} -Q key-plain | sed 's/\r$//'` # remove CR (carriage return)
else
HOSTKEY_TYPES=`${SSH} -Q key-plain`
fi
rm -f $OBJ/hkr.* $OBJ/ssh_proxy.orig
@ -21,9 +25,6 @@ trace "prepare hostkeys"
nkeys=0
all_algs=""
for k in $HOSTKEY_TYPES; do
if [ "$os" == "windows" ]; then
k=`echo $k | sed 's/\r$//'` # remove CR (carriage return)
fi
${SSHKEYGEN} -qt $k -f $OBJ/hkr.$k -N '' || fatal "ssh-keygen $k"
echo "Hostkey $OBJ/hkr.${k}" >> $OBJ/sshd_proxy.orig
nkeys=`expr $nkeys + 1`

View File

@ -105,11 +105,11 @@ if [ "$os" == "windows" ]; then
"powershell.exe /c \"!(Get-ChildItem $`windows_path $OBJ`/copy).IsReadOnly\" 1>/dev/null"
else
ro_test \
"setstat" \
"chmod 0700 $COPY" \
"touch $COPY; chmod 0400 $COPY" \
"test -x $COPY" \
"test ! -x $COPY"
"setstat" \
"chmod 0700 $COPY" \
"touch $COPY; chmod 0400 $COPY" \
"test -x $COPY" \
"test ! -x $COPY"
fi
ro_test \

View File

@ -72,31 +72,55 @@ test "$f" = "no" || fail "clearallforwardings override"
verbose "user first match"
user=`awk '$1=="User" {print $2}' $OBJ/ssh_config`
f=`${SSH} -GF $OBJ/ssh_config host | awk '/^user /{print $2}'`
if [ "$os" == "windows" ]; then
f=${f/$'\r'/} # remove CR (carriage return)
fi
test "$f" = "$user" || fail "user from config, expected '$user' got '$f'"
f=`${SSH} -GF $OBJ/ssh_config -o user=foo -l bar baz@host | awk '/^user /{print $2}'`
if [ "$os" == "windows" ]; then
f=${f/$'\r'/} # remove CR (carriage return)
fi
test "$f" = "foo" || fail "user first match -oUser, expected 'foo' got '$f' "
f=`${SSH} -GF $OBJ/ssh_config -lbar baz@host user=foo baz@host | awk '/^user /{print $2}'`
if [ "$os" == "windows" ]; then
f=${f/$'\r'/} # remove CR (carriage return)
fi
test "$f" = "bar" || fail "user first match -l, expected 'bar' got '$f'"
f=`${SSH} -GF $OBJ/ssh_config baz@host -o user=foo -l bar baz@host | awk '/^user /{print $2}'`
if [ "$os" == "windows" ]; then
f=${f/$'\r'/} # remove CR (carriage return)
fi
test "$f" = "baz" || fail "user first match user@host, expected 'baz' got '$f'"
verbose "pubkeyacceptedkeytypes"
# Default set
f=`${SSH} -GF none host | awk '/^pubkeyacceptedkeytypes /{print $2}'`
if [ "$os" == "windows" ]; then
f=${f/$'\r'/} # remove CR (carriage return)
fi
expect_result_present "$f" "ssh-ed25519" "ssh-ed25519-cert-v01.*"
expect_result_absent "$f" "ssh-dss"
# Explicit override
f=`${SSH} -GF none -opubkeyacceptedkeytypes=ssh-ed25519 host | \
awk '/^pubkeyacceptedkeytypes /{print $2}'`
if [ "$os" == "windows" ]; then
f=${f/$'\r'/} # remove CR (carriage return)
fi
expect_result_present "$f" "ssh-ed25519"
expect_result_absent "$f" "ssh-ed25519-cert-v01.*" "ssh-dss"
# Removal from default set
f=`${SSH} -GF none -opubkeyacceptedkeytypes=-ssh-ed25519-cert* host | \
awk '/^pubkeyacceptedkeytypes /{print $2}'`
if [ "$os" == "windows" ]; then
f=${f/$'\r'/} # remove CR (carriage return)
fi
expect_result_present "$f" "ssh-ed25519"
expect_result_absent "$f" "ssh-ed25519-cert-v01.*" "ssh-dss"
f=`${SSH} -GF none -opubkeyacceptedkeytypes=-ssh-ed25519 host | \
awk '/^pubkeyacceptedkeytypes /{print $2}'`
if [ "$os" == "windows" ]; then
f=${f/$'\r'/} # remove CR (carriage return)
fi
expect_result_present "$f" "ssh-ed25519-cert-v01.*"
expect_result_absent "$f" "ssh-ed25519" "ssh-dss"
# Append to default set.
@ -104,10 +128,16 @@ expect_result_absent "$f" "ssh-ed25519" "ssh-dss"
if [ "$dsa" = "1" ]; then
f=`${SSH} -GF none -opubkeyacceptedkeytypes=+ssh-dss-cert* host | \
awk '/^pubkeyacceptedkeytypes /{print $2}'`
if [ "$os" == "windows" ]; then
f=${f/$'\r'/} # remove CR (carriage return)
fi
expect_result_present "$f" "ssh-ed25519" "ssh-dss-cert-v01.*"
expect_result_absent "$f" "ssh-dss"
f=`${SSH} -GF none -opubkeyacceptedkeytypes=+ssh-dss host | \
awk '/^pubkeyacceptedkeytypes /{print $2}'`
if [ "$os" == "windows" ]; then
f=${f/$'\r'/} # remove CR (carriage return)
fi
expect_result_present "$f" "ssh-ed25519" "ssh-ed25519-cert-v01.*" "ssh-dss"
expect_result_absent "$f" "ssh-dss-cert-v01.*"
fi

View File

@ -362,8 +362,15 @@ stop_sshd ()
make_tmpdir ()
{
SSH_REGRESS_TMP="$($OBJ/mkdtemp openssh-XXXXXXXX)" || \
fatal "failed to create temporary directory"
if [ "$os" == "windows" ]; then
powershell.exe /c "New-Item -Path $OBJ\openssh-XXXXXXXX -ItemType Directory -Force" >/dev/null 2>&1
if [ $? -ne 0 ]; then
fatal "failed to create temporary directory"
fi
else
SSH_REGRESS_TMP="$($OBJ/mkdtemp openssh-XXXXXXXX)" || \
fatal "failed to create temporary directory"
fi
}
# helper
@ -514,6 +521,7 @@ rm -f $OBJ/known_hosts $OBJ/authorized_keys_$USER
SSH_KEYTYPES=`$SSH -Q key-plain`
if [ "$os" == "windows" ]; then
SSH_KEYTYPES=`echo $SSH_KEYTYPES | tr -d '\r','\n'` # remove \r\n
first_key_type=${SSH_KEYTYPES%% *}
if [ "x$USER_DOMAIN" != "x" ]; then
# For domain user, create folders
@ -529,9 +537,14 @@ if [ "$os" == "windows" ]; then
fi
fi
if [ "$os" == "windows" ]; then
OBJ_WIN_FORMAT=`windows_path $OBJ`
fi
for t in ${SSH_KEYTYPES}; do
# generate user key
trace "generating key type $t"
if [ ! -f $OBJ/$t ] || [ ${SSHKEYGEN_BIN} -nt $OBJ/$t ]; then
rm -f $OBJ/$t
${SSHKEYGEN} -q -N '' -t $t -f $OBJ/$t ||\
@ -552,7 +565,7 @@ for t in ${SSH_KEYTYPES}; do
$SUDO cp $OBJ/$t $OBJ/host.$t
if [ "$os" == "windows" ]; then
# set the file permissions (ACLs) properly
powershell.exe /c "get-acl `windows_path $OBJ`/$t | set-acl `windows_path $OBJ`/host.$t"
powershell.exe /c "get-acl $OBJ_WIN_FORMAT/$t | set-acl $OBJ_WIN_FORMAT/host.$t"
fi
echo HostKey $OBJ/host.$t >> $OBJ/sshd_config
@ -563,7 +576,7 @@ done
if [ "$os" == "windows" ]; then
# set the file permissions (ACLs) properly
powershell.exe /c "get-acl `windows_path $OBJ`/$first_key_type | set-acl `windows_path $OBJ`/authorized_keys_$USER"
powershell.exe /c "get-acl $OBJ_WIN_FORMAT/$first_key_type | set-acl $OBJ_WIN_FORMAT/authorized_keys_$USER"
fi
# Activate Twisted Conch tests if the binary is present
@ -626,7 +639,7 @@ fi
(
cat $OBJ/ssh_config
if [ "$os" == "windows" ]; then
echo proxycommand `windows_path ${SSHD}` -i -f `windows_path $OBJ`/sshd_proxy
echo proxycommand `windows_path ${SSHD}` -i -f $OBJ_WIN_FORMAT/sshd_proxy
else
echo proxycommand ${SUDO} sh ${SRC}/sshd-log-wrapper.sh ${TEST_SSHD_LOGFILE} ${SSHD} -i -f $OBJ/sshd_proxy
fi

View File

@ -364,7 +364,7 @@ test_build_commandline_string()
ASSERT_STRING_EQ(out, "\"c:\\windows\\system32\\cmd.exe\" /c arg");
free(out);
out = build_commandline_string("cmd.exe /c ping.exe", NULL, FALSE);
ASSERT_STRING_EQ(out, "\"cmd.exe /c ping.exe\"");
ASSERT_STRING_EQ(out, "\"cmd.exe\" /c ping.exe");
sprintf_s(in, PATH_MAX, "\"%s\\%s\"", __progdir, "ssh-shellhost.exe\" -c \"arg1 arg2\"");
out = build_commandline_string(in, NULL, TRUE);
ASSERT_STRING_EQ(out, in);

View File

@ -1181,7 +1181,12 @@ process_realpath(u_int32_t id)
}
debug3("request %u: realpath", id);
verbose("realpath \"%s\"", path);
#ifdef WINDOWS
if (realpath(path, resolvedname) == NULL) {
#else
if (sftp_realpath(path, resolvedname) == NULL) {
#endif // WINDOWS
send_status(id, errno_to_portable(errno));
} else {
Stat s;