latestw + Test Infra upgrades

Includes
- CR changes for upstream PR
- Fix in spawn_child logic
- Test Infra upgrades
This commit is contained in:
Yanbing 2017-03-24 12:35:52 -07:00 committed by Manoj Ampalam
parent 78995b5a42
commit 425bc4033f
60 changed files with 2006 additions and 1507 deletions

View File

@ -11,12 +11,12 @@ init:
build_script:
- ps: |
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppVeyor.psm1 -DisableNameChecking
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking
Invoke-AppVeyorBuild
after_build:
- ps: |
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppVeyor.psm1 -DisableNameChecking
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking
Install-OpenSSH
- ps: Write-Verbose "Restart computer ..."
- ps: Restart-Computer -Force
@ -25,23 +25,22 @@ after_build:
before_test:
- ps: |
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppVeyor.psm1 -DisableNameChecking
Install-TestDependencies
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking
Install-OpenSSHTestDependencies
Deploy-OpenSSHTests
Setup-OpenSSHTestEnvironment -Quiet
test_script:
- cmd: |
"%ProgramFiles%\PowerShell\6.0.0.14\powershell.exe" -Command "Import-Module \"%APPVEYOR_BUILD_FOLDER%\contrib\win32\openssh\AppVeyor.psm1\" -DisableNameChecking;Run-OpenSSHPesterTest"
- ps: |
Check-PesterTestResult
Run-OpenSSHUnitTest
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking
Run-OpenSSHTests
after_test:
- ps: |
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppVeyor.psm1 -DisableNameChecking
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking
Upload-OpenSSHTestResults
on_finish:
- ps: |
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppVeyor.psm1 -DisableNameChecking
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking
Publish-Artifact

View File

@ -227,15 +227,16 @@ sys_auth_passwd(Authctxt *authctxt, const char *password)
#elif defined(WINDOWS)
/*
* Authenticate on Windows - Pass credentials to ssh-agent and retrieve token
* upon succesful authentication
* upon successful authentication
* TODO - password is sent in plain text over IPC. Consider implications.
*/
extern int auth_sock;
int sys_auth_passwd(Authctxt *authctxt, const char *password)
{
struct sshbuf *msg = NULL;
size_t blen = 0;
DWORD token = 0;
struct sshbuf *msg = NULL;
int r;
extern int auth_sock;
int r = 0;
msg = sshbuf_new();
if (!msg)

4
auth.c
View File

@ -490,7 +490,7 @@ auth_secure_path(const char *name, struct stat *stp, const char *pw_dir,
uid_t uid, char *err, size_t errlen)
{
#ifdef WINDOWS
error("auth_secure_path should not be called in Windows");
error("auth_secure_path should not be called in Windows yet");
return -1;
#else /* !WINDOWS */
char buf[PATH_MAX], homedir[PATH_MAX];
@ -579,7 +579,7 @@ auth_openfile(const char *file, struct passwd *pw, int strict_modes,
FILE *f;
#ifdef WINDOWS
/* Windows POSIX adpater does not support fdopen() on open(file)*/
/* Windows POSIX adapter does not support fdopen() on open(file)*/
if ((f = fopen(file, "r")) == NULL) {
debug("Could not open %s '%s': %s", file_type, file,
strerror(errno));

View File

@ -178,14 +178,14 @@ userauth_pubkey(Authctxt *authctxt)
authenticated = 0;
#ifdef WINDOWS
/* Pass key challenge material to ssh-agent to retrieve token upon succesful authentication */
/* Pass key challenge material to ssh-agent to retrieve token upon successful authentication */
{
extern int auth_sock;
int r;
struct sshbuf *msg = NULL;
u_char *blob = NULL;
size_t blen = 0;
DWORD token = 0;
struct sshbuf *msg = NULL;
extern int auth_sock;
int r = 0;
while (1) {
msg = sshbuf_new();
@ -246,11 +246,7 @@ userauth_pubkey(Authctxt *authctxt)
* if a user is not allowed to login. is this an
* issue? -markus
*/
#ifdef WINDOWS /* key validation in done in agent for Windows */
{
#else /* !WINDOWS */
if (PRIVSEP(user_key_allowed(authctxt->pw, key, 0))) {
#endif /* !WINDOWS */
packet_start(SSH2_MSG_USERAUTH_PK_OK);
packet_put_string(pkalg, alen);
packet_put_string(pkblob, blen);

View File

@ -113,7 +113,6 @@ ssh_get_authentication_socket(int *fdp)
errno = oerrno;
return SSH_ERR_SYSTEM_ERROR;
}
if (fdp != NULL)
*fdp = sock;
else

View File

@ -0,0 +1,268 @@
$ErrorActionPreference = 'Stop'
Import-Module $PSScriptRoot\OpenSSHCommonUtils.psm1 -Force -DisableNameChecking
Import-Module $PSScriptRoot\OpenSSHBuildHelper.psm1 -Force -DisableNameChecking
Import-Module $PSScriptRoot\OpenSSHTestHelper.psm1 -Force -DisableNameChecking
$repoRoot = Get-RepositoryRoot
$script:messageFile = join-path $repoRoot.FullName "BuildMessage.log"
# Sets a build variable
Function Write-BuildMessage
{
param(
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $Message,
$Category,
[string] $Details)
if($env:AppVeyor)
{
Add-AppveyorMessage @PSBoundParameters
}
# write it to the log file, if present.
if (-not ([string]::IsNullOrEmpty($script:messageFile)))
{
Add-Content -Path $script:messageFile -Value "$Category--$Message"
}
}
# Sets a build variable
Function Set-BuildVariable
{
param(
[Parameter(Mandatory=$true)]
[string]
$Name,
[Parameter(Mandatory=$true)]
[string]
$Value
)
if($env:AppVeyor -and (Get-Command Set-AppveyorBuildVariable -ErrorAction Ignore) -ne $null)
{
Set-AppveyorBuildVariable @PSBoundParameters
}
elseif($env:AppVeyor)
{
appveyor SetVariable -Name $Name -Value $Value
}
else
{
Set-Item env:$Name -Value $Value
}
}
# Emulates running all of AppVeyor but locally
# should not be used on AppVeyor
function Invoke-AppVeyorFull
{
param(
[switch] $APPVEYOR_SCHEDULED_BUILD,
[switch] $CleanRepo
)
if($CleanRepo)
{
Clear-PSRepo
}
if($env:APPVEYOR)
{
throw "This function is to simulate appveyor, but not to be run from appveyor!"
}
if($APPVEYOR_SCHEDULED_BUILD)
{
$env:APPVEYOR_SCHEDULED_BUILD = 'True'
}
try {
Set-OpenSSHTestParams
Invoke-AppVeyorBuild
Install-OpenSSH
Install-OpenSSHTestDependencies
Deploy-OpenSSHTests
Setup-OpenSSHTestEnvironment
Run-OpenSSHTests
Publish-Artifact
}
finally {
if($APPVEYOR_SCHEDULED_BUILD -and $env:APPVEYOR_SCHEDULED_BUILD)
{
Remove-Item env:APPVEYOR_SCHEDULED_BUILD
}
}
}
# Implements the AppVeyor 'build_script' step
function Invoke-AppVeyorBuild
{
Set-BuildVariable TestPassed True
Build-OpenSSH -Configuration Release -NativeHostArch x64
Build-OpenSSH -Configuration Debug -NativeHostArch x86
Write-BuildMessage -Message "OpenSSH binaries build success!" -Category Information
}
<#
.Synopsis
Adds a build log to the list of published artifacts.
.Description
If a build log exists, it is renamed to reflect the associated CLR runtime then added to the list of
artifacts to publish. If it doesn't exist, a warning is written and the file is skipped.
The rename is needed since publishing overwrites the artifact if it already exists.
.Parameter artifacts
An array list to add the fully qualified build log path
.Parameter buildLog
The build log file produced by the build.
#>
function Add-BuildLog
{
param
(
[ValidateNotNull()]
[System.Collections.ArrayList] $artifacts,
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $buildLog
)
if (Test-Path -Path $buildLog)
{
$null = $artifacts.Add($buildLog)
}
else
{
Write-Warning "Skip publishing build log. $buildLog does not exist"
}
}
<#
.Synopsis
Publishes package build artifacts.
.Parameter artifacts
An array list to add the fully qualified build log path
.Parameter FileToAdd
Path to the file
#>
function Add-Artifact
{
param
(
[ValidateNotNull()]
[System.Collections.ArrayList] $artifacts,
[string] $FileToAdd
)
if (($FileToAdd -ne $null ) -and (Test-Path $FileToAdd -PathType Leaf))
{
$null = $artifacts.Add($FileToAdd)
}
else
{
Write-Host "Skip publishing package artifacts. $FileToAdd does not exist"
}
}
<#
.Synopsis
After build and test run completes, upload all artifacts from the build machine.
#>
function Publish-Artifact
{
Write-Host -ForegroundColor Yellow "Publishing project artifacts"
[System.Collections.ArrayList] $artifacts = [System.Collections.ArrayList]::new()
# Get the build.log file for each build configuration
Add-BuildLog -artifacts $artifacts -buildLog (Get-BuildLogFile -root $repoRoot.FullName)
Add-Artifact -artifacts $artifacts -FileToAdd $Global:OpenSSHTestInfo["UnitTestResultsFile"]
Add-Artifact -artifacts $artifacts -FileToAdd $Global:OpenSSHTestInfo["E2ETestResultsFile"]
Add-Artifact -artifacts $artifacts -FileToAdd $Global:OpenSSHTestInfo["TestSetupLogFile"]
foreach ($artifact in $artifacts)
{
Write-Host "Publishing $artifact as Appveyor artifact"
# NOTE: attempt to publish subsequent artifacts even if the current one fails
# TODO - Fix this
# Push-AppveyorArtifact $artifact -ErrorAction Continue
}
}
<#
.Synopsis
Runs the tests for this repo
#>
function Run-OpenSSHTests
{
Write-Host "Start running unit tests"
$unitTestFailed = Run-OpenSSHUnitTest
if($unitTestFailed)
{
Write-Host "At least one of the unit tests failed!" -ForegroundColor Yellow
Write-BuildMessage "At least one of the unit tests failed!" -Category Error
Set-BuildVariable TestPassed False
}
else
{
Write-Host "All Unit tests passed!"
Write-BuildMessage -Message "All Unit tests passed!" -Category Information
}
# Run all pester tests.
<#Run-OpenSSHPesterTest
if (-not (Test-Path $global:PesterTestResultsFile))
{
Write-Warning "Test result file $global:PesterTestResultsFile not found after tests."
Write-BuildMessage -Message "Test result file $global:PesterTestResultsFile not found after tests." -Category Error
Set-BuildVariable TestPassed False
}
$xml = [xml](Get-Content -raw $global:PesterTestResultsFile)
if ([int]$xml.'test-results'.failures -gt 0)
{
$errorMessage = "$($xml.'test-results'.failures) tests in regress\pesterTests failed. Detail test log is at $($global:PesterTestResultsFile)."
Write-Warning $errorMessage
Write-BuildMessage -Message $errorMessage -Category Error
Set-BuildVariable TestPassed False
}
# Writing out warning when the $Error.Count is non-zero. Tests Should clean $Error after success.
if ($Error.Count -gt 0)
{
Write-BuildMessage -Message "Tests Should clean $Error after success." -Category Warning
}#>
}
<#
.Synopsis
upload OpenSSH pester test results.
#>
function Upload-OpenSSHTestResults
{
if ($env:APPVEYOR_JOB_ID)
{
$resultFile = Resolve-Path $Global:OpenSSHTestInfo["E2ETestResultsFile"] -ErrorAction Ignore
if( (Test-Path $Global:OpenSSHTestInfo["E2ETestResultsFile"]) -and $resultFile)
{
(New-Object 'System.Net.WebClient').UploadFile("https://ci.appveyor.com/api/testresults/nunit/$($env:APPVEYOR_JOB_ID)", $resultFile)
Write-BuildMessage -Message "Test results uploaded!" -Category Information
}
}
if ($env:DebugMode)
{
Remove-Item $env:DebugMode
}
if($env:TestPassed -ieq 'True')
{
Write-BuildMessage -Message "The checkin validation success!" -Category Information
}
else
{
Write-BuildMessage -Message "The checkin validation failed!" -Category Error
throw "The checkin validation failed!"
}
}

View File

@ -1,5 +1,6 @@

Set-StrictMode -Version Latest
Set-StrictMode -Version Latest
Import-Module $PSScriptRoot\OpenSSHCommonUtils.psm1 -force -DisableNameChecking
[string] $script:platform = $env:PROCESSOR_ARCHITECTURE
[string] $script:vcPath = $null
[System.IO.DirectoryInfo] $script:OpenSSHRoot = $null
@ -132,7 +133,7 @@ function Write-BuildMsg
.Synopsis
Verifies all tools and dependencies required for building Open SSH are installed on the machine.
#>
function Start-SSHBootstrap
function Start-OpenSSHBootstrap
{
[bool] $silent = -not $script:Verbose
@ -140,7 +141,7 @@ function Start-SSHBootstrap
Write-BuildMsg -AsInfo -Message "Checking tools and dependencies" -Silent:$silent
$machinePath = [Environment]::GetEnvironmentVariable('Path', 'MACHINE')
$newMachineEnvironmentPath = $machinePath
$newMachineEnvironmentPath = $machinePath
# Install chocolatey
$chocolateyPath = "$env:AllUsersProfile\chocolatey\bin"
@ -289,7 +290,7 @@ function Copy-OpenSSLSDK
}
}
function Start-SSHBuild
function Build-OpenSSH
{
[CmdletBinding(SupportsShouldProcess=$false)]
param
@ -309,7 +310,6 @@ function Start-SSHBuild
$script:OpenSSHRoot = Get-Item -Path $repositoryRoot.FullName
$script:gitRoot = split-path $script:OpenSSHRoot
if($PSBoundParameters.ContainsKey("Verbose"))
{
$script:Verbose = ($PSBoundParameters['Verbose']).IsPresent
@ -324,7 +324,7 @@ function Start-SSHBuild
Write-BuildMsg -AsInfo -Message "Starting Open SSH build; Build Log: $($script:BuildLogFile)"
Start-SSHBootstrap
Start-OpenSSHBootstrap
Clone-Win32OpenSSH
Copy-OpenSSLSDK
@ -373,34 +373,176 @@ function Get-SolutionFile
}
<#
.Synopsis
Finds the root of the git repository
.Outputs
A System.IO.DirectoryInfo for the location of the root.
.Inputs
None
.Notes
FileNotFoundException is thrown if the current directory does not contain a CMakeLists.txt file.
.Synopsis
Deploy all required files to build a package and create zip file.
#>
function Get-RepositoryRoot
function Deploy-Win32OpenSSHBinaries
{
Set-StrictMode -Version Latest
$currentDir = (Get-Item -Path $PSCommandPath).Directory
[CmdletBinding()]
param
(
[ValidateSet('Debug', 'Release', '')]
[string]$Configuration = "",
[ValidateSet('x86', 'x64', '')]
[string]$NativeHostArch = "",
[string]$OpenSSHDir = "$env:SystemDrive\OpenSSH"
)
while ($null -ne $currentDir.Parent)
if (-not (Test-Path -Path $OpenSSHDir -PathType Container))
{
$path = Join-Path -Path $currentDir.FullName -ChildPath '.git'
if (Test-Path -Path $path)
{
return $currentDir
}
$currentDir = $currentDir.Parent
$null = New-Item -Path $OpenSSHDir -ItemType Directory -Force -ErrorAction Stop
}
throw new-object System.IO.DirectoryNotFoundException("Could not find the root of the GIT repository")
[string] $platform = $env:PROCESSOR_ARCHITECTURE
if(-not [String]::IsNullOrEmpty($NativeHostArch))
{
$folderName = $NativeHostArch
if($NativeHostArch -ieq 'x86')
{
$folderName = "Win32"
}
}
else
{
if($platform -ieq "AMD64")
{
$folderName = "x64"
}
else
{
$folderName = "Win32"
}
}
if([String]::IsNullOrEmpty($Configuration))
{
if( $folderName -ieq "Win32" )
{
$RealConfiguration = "Debug"
}
else
{
$RealConfiguration = "Release"
}
}
else
{
$RealConfiguration = $Configuration
}
[System.IO.DirectoryInfo] $repositoryRoot = Get-RepositoryRoot
$sourceDir = Join-Path $repositoryRoot.FullName -ChildPath "bin\$folderName\$RealConfiguration"
if((Get-Service ssh-agent -ErrorAction Ignore) -ne $null) {
Stop-Service ssh-agent -Force
}
Copy-Item -Path "$sourceDir\*" -Destination $OpenSSHDir -Include *.exe,*.dll -Exclude *unittest*.* -Force -ErrorAction Stop
$sourceDir = Join-Path $repositoryRoot.FullName -ChildPath "contrib\win32\openssh"
Copy-Item -Path "$sourceDir\*" -Destination $OpenSSHDir -Include *.ps1,sshd_config -Exclude AnalyzeCodeDiff.ps1 -Force -ErrorAction Stop
$packageName = "rktools.2003"
$rktoolsPath = "${env:ProgramFiles(x86)}\Windows Resource Kits\Tools\ntrights.exe"
if (-not (Test-Path -Path $rktoolsPath))
{
Write-Log -Message "$packageName not present. Installing $packageName."
choco install $packageName -y --force 2>&1 >> $script:BuildLogFile
if (-not (Test-Path -Path $rktoolsPath))
{
choco install $packageName -y --force 2>&1 >> $script:BuildLogFile
if (-not (Test-Path -Path $rktoolsPath))
{
throw "failed to download $packageName"
}
}
}
Copy-Item -Path $rktoolsPath -Destination $OpenSSHDir -Force -ErrorAction Stop
}
Export-ModuleMember -Function Start-SSHBuild, Get-RepositoryRoot, Get-BuildLogFile, Clone-Win32OpenSSH, Copy-OpenSSLSDK, Write-BuildMsg
<#
.Synopsis
Deploy all required files to a location and install the binaries
#>
function Install-OpenSSH
{
[CmdletBinding()]
param
(
[ValidateSet('Debug', 'Release', '')]
[string]$Configuration = "",
[ValidateSet('x86', 'x64', '')]
[string]$NativeHostArch = "",
[string]$OpenSSHDir = "$env:SystemDrive\OpenSSH"
)
Deploy-Win32OpenSSHBinaries @PSBoundParameters
Push-Location $OpenSSHDir
& ( "$OpenSSHDir\install-sshd.ps1")
.\ssh-keygen.exe -A
& ( "$OpenSSHDir\install-sshlsa.ps1")
#machine will be reboot after Install-openssh anyway
$machinePath = [Environment]::GetEnvironmentVariable('Path', 'MACHINE')
$newMachineEnvironmentPath = $machinePath
if (-not ($machinePath.ToLower().Contains($OpenSSHDir.ToLower())))
{
$newMachineEnvironmentPath = "$OpenSSHDir;$newMachineEnvironmentPath"
$env:Path = "$OpenSSHDir;$env:Path"
}
# Update machine environment path
if ($newMachineEnvironmentPath -ne $machinePath)
{
[Environment]::SetEnvironmentVariable('Path', $newMachineEnvironmentPath, 'MACHINE')
}
Set-Service sshd -StartupType Automatic
Set-Service ssh-agent -StartupType Automatic
Start-Service sshd
Pop-Location
Write-Log -Message "OpenSSH installed!"
}
<#
.Synopsis
uninstalled sshd and sshla
#>
function UnInstall-OpenSSH
{
[CmdletBinding()]
param
(
[string]$OpenSSHDir = "$env:SystemDrive\OpenSSH"
)
Push-Location $OpenSSHDir
if((Get-Service ssh-agent -ErrorAction Ignore) -ne $null) {
Stop-Service ssh-agent -Force
}
&( "$OpenSSHDir\uninstall-sshd.ps1")
&( "$OpenSSHDir\uninstall-sshlsa.ps1")
$machinePath = [Environment]::GetEnvironmentVariable('Path', 'MACHINE')
$newMachineEnvironmentPath = $machinePath
if ($machinePath.ToLower().Contains($OpenSSHDir.ToLower()))
{
$newMachineEnvironmentPath.Replace("$OpenSSHDir;", '')
$env:Path = $env:Path.Replace("$OpenSSHDir;", '')
}
# Update machine environment path
# machine will be reboot after Uninstall-OpenSSH
if ($newMachineEnvironmentPath -ne $machinePath)
{
[Environment]::SetEnvironmentVariable('Path', $newMachineEnvironmentPath, 'MACHINE')
}
Pop-Location
}
Export-ModuleMember -Function Build-OpenSSH, Get-BuildLogFile, Install-OpenSSH, UnInstall-OpenSSH

View File

@ -0,0 +1,31 @@
<#
.Synopsis
Finds the root of the git repository
.Outputs
A System.IO.DirectoryInfo for the location of the root.
.Inputs
None
.Notes
FileNotFoundException is thrown if the current directory does not contain a CMakeLists.txt file.
#>
function Get-RepositoryRoot
{
$currentDir = (Get-Item -Path $PSCommandPath).Directory
while ($null -ne $currentDir.Parent)
{
$path = Join-Path -Path $currentDir.FullName -ChildPath '.git'
if (Test-Path -Path $path)
{
return $currentDir
}
$currentDir = $currentDir.Parent
}
throw new-object System.IO.DirectoryNotFoundException("Could not find the root of the GIT repository")
}
Export-ModuleMember -Function Get-RepositoryRoot

View File

@ -0,0 +1,456 @@
$ErrorActionPreference = 'Stop'
Import-Module $PSScriptRoot\OpenSSHCommonUtils.psm1 -DisableNameChecking
# state object used by all tests, initialized in Setup-OpenSSHTetEnvironment
$Global:OpenSSHTestInfo = @{}
<# Hash Table definitions
#test listener name
$Global:OpenSSHTestInfo["Target"]
# test listener port
$Global:OpenSSHTestInfo["Port"]
# test user with single sign on capability
$Global:OpenSSHTestInfo["SSOUser"]
# test user to be used with explicit key for key auth
$Global:OpenSSHTestInfo["PubKeyUser"]
# test user for passwd based auth
$Global:OpenSSHTestInfo["PasswdUser"]
# common password for all test accounts
$Global:OpenSSHTestInfo["TestAccountPW"]
# openssh bin path
$Global:OpenSSHTestInfo["OpenSSHDir"]
# openssh tests path
$Global:OpenSSHTestInfo["OpenSSHTestDir"]
# openssh test setup log file
$Global:OpenSSHTestInfo["TestSetupLogFile"]
# openssh E2E test results file
$Global:OpenSSHTestInfo["E2ETestResultsFile"]
# openssh unittest test results file
$Global:OpenSSHTestInfo["UnitTestResultsFile"]
#>
# test environment parameters initialized with defaults
$Script:OpenSSHDir = "$env:SystemDrive\OpenSSH"
$Script:OpenSSHTestDir = "$env:SystemDrive\OpenSSHTests"
$Script:E2ETestResultsFile = Join-Path $Script:OpenSSHTestDir "E2ETestResultsFile.xml"
$Script:UnitTestResultsFile = Join-Path $Script:OpenSSHTestDir "UnitTestResults.txt"
$Script:TestSetupLogFile = Join-Path $Script:OpenSSHTestDir "TestSetupLog.txt"
$Script:SSOUser = "sshtest_ssouser"
$Script:PubKeyUser = "sshtest_pubkeyuser"
$Script:PasswdUser = "sshtest_passwduser"
$Script:OpenSSHTestAccountsPassword = "P@ssw0rd_1"
$Script:OpenSSHTestAccounts = $Script:SSOUser, $Script:PubKeyUser, $Script:PasswdUser
function Set-OpenSSHTestParams
{
param
(
[string] $OpenSSHDir = $Script:OpenSSHDir,
[string] $OpenSSHTestDir = $Script:OpenSSHTestDir,
[string] $E2ETestResultsFile = $Script:E2ETestResultsFile,
[string] $UnitTestResultsFile = $Script:UnitTestResultsFile,
[string] $TestSetupLogFile = $Script:TestSetupLogFile
)
$Script:OpenSSHDir = $OpenSSHDir
$Script:OpenSSHTestDir = $OpenSSHTestDir
$Script:E2ETestResultsFile = $E2ETestResultsFile
$Script:UnitTestResultsFile = $UnitTestResultsFile
$Script:TestSetupLogFile = $TestSetupLogFile
}
function Dump-OpenSSHTestParams
{
$out = @"
OpenSSHDir: $Script:OpenSSHDir
OpenSSHTestDir: $Script:OpenSSHTestDir
E2ETestResultsFile: $Script:E2ETestResultsFile
UnitTestResultsFile: $Script:UnitTestResultsFile
TestSetupLogFile: $Script:TestSetupLogFile
"@
Write-Host $out
}
<#
.SYNOPSIS
This function installs the tools required by our tests
1) Pester for running the tests
2) sysinternals required by the tests on windows.
#>
function Install-OpenSSHTestDependencies
{
[CmdletBinding()]
param ()
# Install chocolatey
if(-not (Get-Command "choco" -ErrorAction SilentlyContinue))
{
Write-Log -Message "Chocolatey not present. Installing chocolatey."
Invoke-Expression ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1')) 2>&1 >> $Script:TestSetupLogFile
}
$isModuleAvailable = Get-Module 'Pester' -ListAvailable
if (-not ($isModuleAvailable))
{
Write-Log -Message "Installing Pester..."
choco install Pester -y --force --limitoutput 2>&1 >> $Script:TestSetupLogFile
}
if ( -not (Test-Path "$env:ProgramData\chocolatey\lib\sysinternals\tools" ) ) {
Write-Log -Message "sysinternals not present. Installing sysinternals."
choco install sysinternals -y --force --limitoutput 2>&1 >> $Script:TestSetupLogFile
}
}
<#
.Synopsis
Setup-OpenSSHTestEnvironment
TODO - split these steps into client and server side
#>
function Setup-OpenSSHTestEnvironment
{
[CmdletBinding()]
param
(
[switch] $Quiet
)
$warning = @"
WARNING: Following changes will be made to OpenSSH configuration
- sshd_config will be backed up as sshd_config.ori
- will be replaced with a test sshd_config
- $env:USERPROFILE\.ssh\known_hosts will be backed up as known_hosts.ori
- will be replaced with a test known_hosts
- sshd test listener will be on port 47002
- $env:USERPROFILE\.ssh\known_hosts will be modified with test host key entry
- test accounts - ssouser, pubkeyuser and passwduser will be added
- To cleanup - Run Cleanup-OpenSSHTestEnvironment
"@
if (-not $Quiet) {
Write-Warning $warning
}
if (-not (Test-Path (Join-Path $Script:OpenSSHDir ssh.exe) -PathType Leaf))
{
Throw "cannot find OpenSSH binaries under $Script:OpenSSHDir Try Set-OpenSSHTestParams"
}
$sshcmd = get-command ssh.exe -ErrorAction Ignore
if($sshcmd -eq $null) {
Throw 'Cannot find ssh.exe. Make sure OpenSSH binary path is in %PATH%'
}
#ensure ssh.exe is being picked from $Script:OpenSSHDir. Multiple versions may exist
if ( (Split-Path $sshcmd.Source) -ine "$Script:OpenSSHDir" ) {
Throw "ssh.exe is being picked from $($sshcmd.Source) instead of $Script:OpenSSHDir. "
}
if (-not (Test-Path $Script:OpenSSHTestDir -PathType Container )) {
Throw "$Script:OpenSSHTestDir does not exist. Run Deploy-OpenSSHTests to deploy tests."
}
if ((Get-ChildItem $Script:OpenSSHTestDir).Count -eq 0) {
Throw "Nothing found in $Script:OpenSSHTestDir. Run Deploy-OpenSSHTests to deploy tests"
}
#Backup existing OpenSSH configuration
$backupConfigPath = Join-Path $Script:OpenSSHDir sshd_config.ori
if (-not (Test-Path $backupConfigPath -PathType Leaf)) {
Copy-Item (Join-Path $Script:OpenSSHDir sshd_config) $backupConfigPath -Force
}
# copy new sshd_config
Copy-Item (Join-Path $Script:OpenSSHTestDir sshd_config) (Join-Path $Script:OpenSSHDir sshd_config) -Force
Copy-Item $Script:OpenSSHTestDir\sshtest*hostkey* $Script:OpenSSHDir -Force
Restart-Service sshd -Force
#Backup existing known_hosts and replace with test version
#TODO - account for custom known_hosts locations
$knowHostsDirectoryPath = Join-Path $home .ssh
$knowHostsFilePath = Join-Path $knowHostsDirectoryPath known_hosts
if(-not (Test-Path $knowHostsDirectoryPath -PathType Container))
{
New-Item -ItemType Directory -Path $knowHostsDirectoryPath -Force -ErrorAction SilentlyContinue | out-null
}
if (Test-Path $knowHostsFilePath -PathType Leaf) {
Copy-Item $knowHostsFilePath (Join-Path $knowHostsDirectoryPath known_hosts.ori) -Force
}
Copy-Item (Join-Path $Script:OpenSSHTestDir known_hosts) $knowHostsFilePath -Force
# create test accounts
#TODO - this is Windows specific. Need to be in PAL
foreach ($user in $Script:OpenSSHTestAccounts)
{
net user $user $Script:OpenSSHTestAccountsPassword /ADD 2>&1 >> $Script:TestSetupLogFile
}
#setup single sign on for ssouser
#TODO - this is Windows specific. Need to be in PAL
$ssousersid = Get-UserSID -User sshtest_ssouser
$ssouserProfileRegistry = Join-Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList" $ssousersid
if (-not (Test-Path $ssouserProfileRegistry) ) {
#create profile
if (-not($env:DISPLAY)) { $env:DISPLAY = 1 }
$env:SSH_ASKPASS="$($env:ComSpec) /c echo $($Script:OpenSSHTestAccountsPassword)"
cmd /c "ssh -p 47002 sshtest_ssouser@localhost echo %userprofile% > profile.txt"
if ($env:DISPLAY -eq 1) { Remove-Item env:\DISPLAY }
remove-item "env:SSH_ASKPASS" -ErrorAction SilentlyContinue
}
$ssouserProfile = (Get-ItemProperty -Path $ssouserProfileRegistry -Name 'ProfileImagePath').ProfileImagePath
New-Item -ItemType Directory -Path (Join-Path $ssouserProfile .ssh) -Force -ErrorAction SilentlyContinue | out-null
$authorizedKeyPath = Join-Path $ssouserProfile .ssh\authorized_keys
$testPubKeyPath = Join-Path $Script:OpenSSHTestDir sshtest_userssokey_ed25519.pub
(Get-Content $testPubKeyPath -Raw).Replace("`r`n","`n") | Set-Content $testPubKeyPath -Force
Copy-Item $testPubKeyPath $authorizedKeyPath -Force -ErrorAction SilentlyContinue
$acl = get-acl $authorizedKeyPath
$ar = New-Object System.Security.AccessControl.FileSystemAccessRule("NT Service\sshd", "Read", "Allow")
$acl.SetAccessRule($ar)
Set-Acl $authorizedKeyPath $acl
$testPriKeypath = Join-Path $Script:OpenSSHTestDir sshtest_userssokey_ed25519
(Get-Content $testPriKeypath -Raw).Replace("`r`n","`n") | Set-Content $testPriKeypath -Force
cmd /c "ssh-add $testPriKeypath 2>&1 >> $Script:TestSetupLogFile"
$Global:OpenSSHTestInfo = @{}
# test listener name
$Global:OpenSSHTestInfo.Add("Target","localhost")
# test listener port
$Global:OpenSSHTestInfo.Add("Port", "47002")
# test user with single sign on capability
$Global:OpenSSHTestInfo.Add("SSOUser", $Script:SSOUser)
# test user to be used with explicit key for key auth
$Global:OpenSSHTestInfo.Add("PubKeyUser", $Script:PubKeyUser)
# test user for passwd based auth
$Global:OpenSSHTestInfo.Add("PasswdUser", $Script:PasswdUser)
# common password for all test accounts
$Global:OpenSSHTestInfo.Add("TestAccountPW", $Script:OpenSSHTestAccountsPassword)
# openssh bin path
$Global:OpenSSHTestInfo.Add("OpenSSHDir", $Script:OpenSSHDir)
# openssh tests path
$Global:OpenSSHTestInfo.Add("OpenSSHTestDir", $Script:OpenSSHTestDir)
# openssh test setup log file
$Global:OpenSSHTestInfo.Add("TestSetupLogFile", $Script:TestSetupLogFile)
# openssh E2E test results file
$Global:OpenSSHTestInfo.Add("E2ETestResultsFile", $Script:E2ETestResultsFile)
# openssh unittest test results file
$Global:OpenSSHTestInfo.Add("UnitTestResultsFile", $Script:UnitTestResultsFile)
}
<#
.Synopsis
Get-UserSID
#>
function Get-UserSID
{
param
(
[string]$Domain,
[string]$User
)
if([string]::IsNullOrEmpty($Domain))
{
$objUser = New-Object System.Security.Principal.NTAccount($User)
}
else
{
$objUser = New-Object System.Security.Principal.NTAccount($Domain, $User)
}
$strSID = $objUser.Translate([System.Security.Principal.SecurityIdentifier])
$strSID.Value
}
<#
.Synopsis
Cleanup-OpenSSHTestEnvironment
#>
function Cleanup-OpenSSHTestEnvironment
{
# .exe - Windows specific. TODO - PAL
if (-not (Test-Path (Join-Path $Script:OpenSSHDir ssh.exe) -PathType Leaf))
{
Throw "Cannot find OpenSSH binaries under $($Script:OpenSSHDir). Try -OpenSSHDir parameter"
}
#Restore sshd_config
$backupConfigPath = Join-Path $Script:OpenSSHDir sshd_config.ori
if (Test-Path $backupConfigPath -PathType Leaf) {
Copy-Item $backupConfigPath (Join-Path $Script:OpenSSHDir sshd_config) -Force -ErrorAction SilentlyContinue
Remove-Item (Join-Path $Script:OpenSSHDir sshd_config.ori) -Force -ErrorAction SilentlyContinue
Remove-Item $Script:OpenSSHDir\sshtest*hostkey* -Force -ErrorAction SilentlyContinue
Restart-Service sshd
}
#Restore known_hosts
$originKnowHostsPath = Join-Path $home .ssh\known_hosts.ori
if (Test-Path $originKnowHostsPath)
{
Copy-Item $originKnowHostsPath (Join-Path $home .ssh\known_hosts) -Force -ErrorAction SilentlyContinue
Remove-Item $originKnowHostsPath -Force -ErrorAction SilentlyContinue
}
#Delete accounts
foreach ($user in $Script:OpenSSHTestAccounts)
{
net user $user /delete
}
# remove registered keys
cmd /c "ssh-add -d (Join-Path $Script:OpenSSHTestDir sshtest_userssokey_ed25519) 2>&1 >> $Script:TestSetupLogFile"
$Global:OpenSSHTestInfo = $null
}
<#
.Synopsis
After build and test run completes, upload all artifacts from the build machine.
#>
function Deploy-OpenSSHTests
{
[CmdletBinding()]
param
(
[ValidateSet('Debug', 'Release', '')]
[string]$Configuration = "",
[ValidateSet('x86', 'x64', '')]
[string]$NativeHostArch = ""
)
if (-not (Test-Path -Path $Script:OpenSSHTestDir -PathType Container))
{
$null = New-Item -Path $Script:OpenSSHTestDir -ItemType Directory -Force -ErrorAction Stop
}
[string] $platform = $env:PROCESSOR_ARCHITECTURE
if(-not [String]::IsNullOrEmpty($NativeHostArch))
{
$folderName = $NativeHostArch
if($NativeHostArch -eq 'x86')
{
$folderName = "Win32"
}
}
else
{
if($platform -ieq "AMD64")
{
$folderName = "x64"
}
else
{
$folderName = "Win32"
}
}
if([String]::IsNullOrEmpty($Configuration))
{
if( $folderName -ieq "Win32" )
{
$RealConfiguration = "Debug"
}
else
{
$RealConfiguration = "Release"
}
}
else
{
$RealConfiguration = $Configuration
}
[System.IO.DirectoryInfo] $repositoryRoot = Get-RepositoryRoot
#copy all pester tests
$sourceDir = Join-Path $repositoryRoot.FullName -ChildPath "regress\pesterTests"
Copy-Item -Path "$sourceDir\*" -Destination $Script:OpenSSHTestDir -Include *.ps1,*.psm1, sshd_config, known_hosts, sshtest_* -Force -ErrorAction Stop
#copy all unit tests.
$sourceDir = Join-Path $repositoryRoot.FullName -ChildPath "bin\$folderName\$RealConfiguration"
Copy-Item -Path "$sourceDir\*" -Destination "$($Script:OpenSSHTestDir)\" -Container -Include unittest-* -Recurse -Force -ErrorAction Stop
}
<#
.Synopsis
Run OpenSSH pester tests.
#>
function Run-OpenSSHPesterTest
{
# Discover all CI tests and run them.
Push-Location $Script:OpenSSHTestDir
Write-Log -Message "Running OpenSSH Pester tests..."
$testFolders = Get-ChildItem *.tests.ps1 -Recurse -Exclude SSHDConfig.tests.ps1, SSH.Tests.ps1 | ForEach-Object{ Split-Path $_.FullName} | Sort-Object -Unique
Invoke-Pester $testFolders -OutputFormat NUnitXml -OutputFile $Script:E2ETestResultsFile -Tag 'CI'
Pop-Location
}
<#
.Synopsis
Run openssh unit tests.
#>
function Run-OpenSSHUnitTest
{
# Discover all CI tests and run them.
Push-Location $Script:OpenSSHTestDir
Write-Log -Message "Running OpenSSH unit tests..."
if (Test-Path $Script:UnitTestResultsFile)
{
$null = Remove-Item -Path $Script:UnitTestResultsFile -Force -ErrorAction SilentlyContinue
}
$testFolders = Get-ChildItem unittest-*.exe -Recurse -Exclude unittest-sshkey.exe,unittest-kex.exe |
ForEach-Object{ Split-Path $_.FullName} |
Sort-Object -Unique
$testfailed = $false
if ($testFolders -ne $null)
{
$testFolders | % {
Push-Location $_
$unittestFile = "$(Split-Path $_ -Leaf).exe"
Write-log "Running OpenSSH unit $unittestFile ..."
& .\$unittestFile >> $Script:UnitTestResultsFile
$errorCode = $LASTEXITCODE
if ($errorCode -ne 0)
{
$testfailed = $true
$errorMessage = "$($_.FullName) test failed for OpenSSH.`nExitCode: $errorCode. Detail test log is at $($Script:UnitTestResultsFile)."
Write-Warning $errorMessage
}
Pop-Location
}
}
Pop-Location
$testfailed
}
<#
Write-Log
#>
function Write-Log
{
param
(
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $Message
)
if(-not (Test-Path (Split-Path $Script:TestSetupLogFile) -PathType Container))
{
$null = New-Item -ItemType Directory -Path (Split-Path $Script:TestSetupLogFile) -Force -ErrorAction SilentlyContinue | out-null
}
if (-not ([string]::IsNullOrEmpty($Script:TestSetupLogFile)))
{
Add-Content -Path $Script:TestSetupLogFile -Value $Message
}
}
Export-ModuleMember -Function Set-OpenSSHTestParams, Dump-OpenSSHTestParams, Install-OpenSSHTestDependencies, Setup-OpenSSHTestEnvironment, Cleanup-OpenSSHTestEnvironment, Deploy-OpenSSHTests, Run-OpenSSHUnitTest, Run-OpenSSHPesterTest

View File

@ -126,14 +126,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unittest-win32compat", "uni
{0D02F0F0-013B-4EE3-906D-86517F3822C0} = {0D02F0F0-013B-4EE3-906D-86517F3822C0}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unittest-utf8", "unittest-utf8.vcxproj", "{114CAA59-46C0-4B87-BA86-C1946A68101D}"
ProjectSection(ProjectDependencies) = postProject
{05E1115F-8529-46D0-AAAF-52A404CE79A7} = {05E1115F-8529-46D0-AAAF-52A404CE79A7}
{8F9D3B74-8D33-448E-9762-26E8DCC6B2F4} = {8F9D3B74-8D33-448E-9762-26E8DCC6B2F4}
{DD483F7D-C553-4740-BC1A-903805AD0174} = {DD483F7D-C553-4740-BC1A-903805AD0174}
{0D02F0F0-013B-4EE3-906D-86517F3822C0} = {0D02F0F0-013B-4EE3-906D-86517F3822C0}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unittest-hostkeys", "unittest-hostkeys.vcxproj", "{890C6129-286F-4CD8-8252-FB8D3B4E6E1B}"
ProjectSection(ProjectDependencies) = postProject
{05E1115F-8529-46D0-AAAF-52A404CE79A7} = {05E1115F-8529-46D0-AAAF-52A404CE79A7}
@ -314,14 +306,6 @@ Global
{BF295BA9-4BF8-43F8-8CBF-FAE84815466C}.Release|x64.Build.0 = Release|x64
{BF295BA9-4BF8-43F8-8CBF-FAE84815466C}.Release|x86.ActiveCfg = Release|Win32
{BF295BA9-4BF8-43F8-8CBF-FAE84815466C}.Release|x86.Build.0 = Release|Win32
{114CAA59-46C0-4B87-BA86-C1946A68101D}.Debug|x64.ActiveCfg = Debug|x64
{114CAA59-46C0-4B87-BA86-C1946A68101D}.Debug|x64.Build.0 = Debug|x64
{114CAA59-46C0-4B87-BA86-C1946A68101D}.Debug|x86.ActiveCfg = Debug|Win32
{114CAA59-46C0-4B87-BA86-C1946A68101D}.Debug|x86.Build.0 = Debug|Win32
{114CAA59-46C0-4B87-BA86-C1946A68101D}.Release|x64.ActiveCfg = Release|x64
{114CAA59-46C0-4B87-BA86-C1946A68101D}.Release|x64.Build.0 = Release|x64
{114CAA59-46C0-4B87-BA86-C1946A68101D}.Release|x86.ActiveCfg = Release|Win32
{114CAA59-46C0-4B87-BA86-C1946A68101D}.Release|x86.Build.0 = Release|Win32
{890C6129-286F-4CD8-8252-FB8D3B4E6E1B}.Debug|x64.ActiveCfg = Debug|x64
{890C6129-286F-4CD8-8252-FB8D3B4E6E1B}.Debug|x64.Build.0 = Debug|x64
{890C6129-286F-4CD8-8252-FB8D3B4E6E1B}.Debug|x86.ActiveCfg = Debug|Win32
@ -369,7 +353,6 @@ Global
{8EC56B06-5A9A-4D6D-804D-037FE26FD43E} = {A8096E32-E084-4FA0-AE01-A8D909EB2BB4}
{CD9740CE-C96E-49B3-823F-012E09D17806} = {A8096E32-E084-4FA0-AE01-A8D909EB2BB4}
{BF295BA9-4BF8-43F8-8CBF-FAE84815466C} = {A8096E32-E084-4FA0-AE01-A8D909EB2BB4}
{114CAA59-46C0-4B87-BA86-C1946A68101D} = {A8096E32-E084-4FA0-AE01-A8D909EB2BB4}
{890C6129-286F-4CD8-8252-FB8D3B4E6E1B} = {A8096E32-E084-4FA0-AE01-A8D909EB2BB4}
{FC568FF0-60F2-4B2E-AF62-FD392EDBA1B9} = {A8096E32-E084-4FA0-AE01-A8D909EB2BB4}
{484A8CDE-B949-4BDA-B447-74685C8E032F} = {A8096E32-E084-4FA0-AE01-A8D909EB2BB4}

View File

@ -1,764 +0,0 @@
$ErrorActionPreference = 'Stop'
Import-Module $PSScriptRoot\build.psm1 -Force -DisableNameChecking
$repoRoot = Get-RepositoryRoot
$script:logFile = join-path $repoRoot.FullName "appveyor.log"
$script:messageFile = join-path $repoRoot.FullName "BuildMessage.log"
<#
Called by Write-BuildMsg to write to the build log, if it exists.
#>
function Write-Log
{
param
(
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $Message
)
# write it to the log file, if present.
if (-not ([string]::IsNullOrEmpty($script:logFile)))
{
Add-Content -Path $script:logFile -Value $Message
}
}
# Sets a build variable
Function Write-BuildMessage
{
param(
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $Message,
$Category,
[string] $Details)
if($env:AppVeyor)
{
Add-AppveyorMessage @PSBoundParameters
}
# write it to the log file, if present.
if (-not ([string]::IsNullOrEmpty($script:messageFile)))
{
Add-Content -Path $script:messageFile -Value "$Category--$Message"
}
}
# Sets a build variable
Function Set-BuildVariable
{
param(
[Parameter(Mandatory=$true)]
[string]
$Name,
[Parameter(Mandatory=$true)]
[string]
$Value
)
if($env:AppVeyor -and (Get-Command Set-AppveyorBuildVariable -ErrorAction Ignore) -ne $null)
{
Set-AppveyorBuildVariable @PSBoundParameters
}
elseif($env:AppVeyor)
{
appveyor SetVariable -Name $Name -Value $Value
}
else
{
Set-Item env:$Name -Value $Value
}
}
# Emulates running all of AppVeyor but locally
# should not be used on AppVeyor
function Invoke-AppVeyorFull
{
param(
[switch] $APPVEYOR_SCHEDULED_BUILD,
[switch] $CleanRepo
)
if($CleanRepo)
{
Clear-PSRepo
}
if($env:APPVEYOR)
{
throw "This function is to simulate appveyor, but not to be run from appveyor!"
}
if($APPVEYOR_SCHEDULED_BUILD)
{
$env:APPVEYOR_SCHEDULED_BUILD = 'True'
}
try {
Invoke-AppVeyorBuild
Install-OpenSSH
Install-TestDependencies
Run-OpenSSHTests
Publish-Artifact
}
finally {
if($APPVEYOR_SCHEDULED_BUILD -and $env:APPVEYOR_SCHEDULED_BUILD)
{
Remove-Item env:APPVEYOR_SCHEDULED_BUILD
}
}
}
# Implements the AppVeyor 'build_script' step
function Invoke-AppVeyorBuild
{
Set-BuildVariable TestPassed True
Start-SSHBuild -Configuration Release -NativeHostArch x64
Start-SSHBuild -Configuration Debug -NativeHostArch x86
Write-BuildMessage -Message "OpenSSH binaries build success!" -Category Information
}
<#
.Synopsis
This function invokes msiexec.exe to install PSCore on the AppVeyor build machine
#>
function Invoke-MSIEXEC
{
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[string] $InstallFile
)
Write-Log -Message "Installing $InstallFile..."
$arguments = @(
"/i"
"`"$InstallFile`""
"/qn"
"/norestart"
)
$process = Start-Process -FilePath msiexec.exe -ArgumentList $arguments -Wait -PassThru
if ($process.ExitCode -eq 0){
Write-Log -Message "$InstallFile has been successfully installed."
}
else {
Write-Log -Message "installer exit code $($process.ExitCode) for file $($InstallFile)"
}
return $process.ExitCode
}
<#
.Synopsis
This function installs PSCore MSI on the AppVeyor build machine
#>
function Install-PSCoreFromGithub
{
$downloadLocation = Download-PSCoreMSI
Write-Log -Message "Installing PSCore ..."
if(-not [string]::IsNullOrEmpty($downloadLocation))
{
$processExitCode = Invoke-MSIEXEC -InstallFile $downloadLocation
Write-Log -Message "Process exitcode: $processExitCode"
}
}
<#
.Synopsis
Retuns MSI location for PSCore for Win10, Windows 8.1 and 2012 R2
#>
function Get-PSCoreMSIDownloadURL
{
$osversion = [String][Environment]::OSVersion.Version
if($osversion.StartsWith("6"))
{
if ($($env:PROCESSOR_ARCHITECTURE).Contains('64'))
{
return 'https://github.com/PowerShell/PowerShell/releases/download/v6.0.0-alpha.14/PowerShell_6.0.0.14-alpha.14-win81-x64.msi'
}
else
{
return 'https://github.com/PowerShell/PowerShell/releases/download/v6.0.0-alpha.14/PowerShell_6.0.0.14-alpha.14-win7-x86.msi'
}
}
elseif ($osversion.Contains("10.0"))
{
if ($($env:PROCESSOR_ARCHITECTURE).Contains('64'))
{
return 'https://github.com/PowerShell/PowerShell/releases/download/v6.0.0-alpha.14/PowerShell_6.0.0.14-alpha.14-win10-x64.msi'
}
else
{
return 'https://github.com/PowerShell/PowerShell/releases/download/v6.0.0-alpha.14/PowerShell_6.0.0.14-alpha.14-win7-x86.msi'
}
}
}
<#
.Synopsis
This functions downloads MSI and returns the path where the file is downloaded.
#>
function Download-PSCoreMSI
{
$url = Get-PSCoreMSIDownloadURL
if([string]::IsNullOrEmpty($url))
{
Write-Log -Message "url is empty"
return ''
}
$parsed = $url.Substring($url.LastIndexOf("/") + 1)
if(-not (Test-path "$env:SystemDrive\PScore" -PathType Container))
{
$null = New-Item -ItemType Directory -Force -Path "$env:SystemDrive\PScore" | out-null
}
$downloadLocation = "$env:SystemDrive\PScore\$parsed"
if(-not (Test-path $downloadLocation -PathType Leaf))
{
Invoke-WebRequest -Uri $url -OutFile $downloadLocation -ErrorVariable v
}
if ($v)
{
Write-BuildMessage -Message "Failed to download PSCore MSI package from $url" -Category Error
throw "Failed to download PSCore MSI package from $url"
}
else
{
return $downloadLocation
}
}
<#
.SYNOPSIS
This function installs the tools required by our tests
1) Pester for running the tests
2) sysinternals required by the tests on windows.
#>
function Install-TestDependencies
{
[CmdletBinding()]
param ()
# Install chocolatey
if(-not (Get-Command "choco" -ErrorAction SilentlyContinue))
{
Write-Log -Message "Chocolatey not present. Installing chocolatey."
Invoke-Expression ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1')) 2>&1 >> $script:logFile
}
$isModuleAvailable = Get-Module 'Pester' -ListAvailable
if (-not ($isModuleAvailable))
{
Write-Log -Message "Installing Pester..."
choco install Pester -y --force --limitoutput 2>&1 >> $script:logFile
}
if ( -not (Test-Path "$env:ProgramData\chocolatey\lib\sysinternals\tools" ) ) {
Write-Log -Message "sysinternals not present. Installing sysinternals."
choco install sysinternals -y --force --limitoutput 2>&1 >> $script:logFile
}
<#if ( (-not (Test-Path "${env:ProgramFiles(x86)}\Windows Kits\8.1\Debuggers\" )) -and (-not (Test-Path "${env:ProgramFiles(x86)}\Windows Kits\10\Debuggers\" ))) {
Write-Log -Message "debugger not present. Installing windbg."
choco install windbg --force --limitoutput -y 2>&1 >> $script:logFile
}#>
Install-PSCoreFromGithub
$psCorePath = GetLocalPSCorePath
Set-BuildVariable -Name psPath -Value $psCorePath
Write-BuildMessage -Message "All testDependencies installed!" -Category Information
}
<#
.Synopsis
Get the path to the installed powershell score
#>
function GetLocalPSCorePath {
$psPath = Get-ChildItem "$env:ProgramFiles\PowerShell\*\powershell.exe" -Recurse -ErrorAction SilentlyContinue
if($psPath.Count -eq 0)
{
""
}
else
{
$psPath[-1].FullName
}
}
<#
.Synopsis
Deploy all required files to a location and install the binaries
#>
function Install-OpenSSH
{
[CmdletBinding()]
param
(
[string] $OpenSSHDir = "$env:SystemDrive\OpenSSH",
[ValidateSet('Debug', 'Release', '')]
[string]$Configuration = "",
[ValidateSet('x86', 'x64', '')]
[string]$NativeHostArch = ""
)
Build-Win32OpenSSHPackage @PSBoundParameters
Push-Location $OpenSSHDir
& ( "$OpenSSHDir\install-sshd.ps1")
.\ssh-keygen.exe -A
Start-Service ssh-agent
&( "$OpenSSHDir\install-sshlsa.ps1")
Set-Service sshd -StartupType Automatic
Set-Service ssh-agent -StartupType Automatic
Start-Service sshd
Pop-Location
Write-BuildMessage -Message "OpenSSH installed!" -Category Information
}
<#
.Synopsis
uninstalled sshd and sshla
#>
function UnInstall-OpenSSH
{
[CmdletBinding()]
param
(
[string] $OpenSSHDir = "$env:SystemDrive\OpenSSH"
)
Push-Location $OpenSSHDir
Stop-Service sshd
&( "$OpenSSHDir\uninstall-sshd.ps1")
&( "$OpenSSHDir\uninstall-sshlsa.ps1")
Pop-Location
}
<#
.Synopsis
Deploy all required files to build a package and create zip file.
#>
function Build-Win32OpenSSHPackage
{
[CmdletBinding()]
param
(
[string] $OpenSSHDir = "$env:SystemDrive\OpenSSH",
[ValidateSet('Debug', 'Release', '')]
[string]$Configuration = "",
[ValidateSet('x86', 'x64', '')]
[string]$NativeHostArch = ""
)
if (-not (Test-Path -Path $OpenSSHDir -PathType Container))
{
$null = New-Item -Path $OpenSSHDir -ItemType Directory -Force -ErrorAction Stop
}
[string] $platform = $env:PROCESSOR_ARCHITECTURE
if(-not [String]::IsNullOrEmpty($NativeHostArch))
{
$folderName = $NativeHostArch
if($NativeHostArch -ieq 'x86')
{
$folderName = "Win32"
}
}
else
{
if($platform -ieq "AMD64")
{
$folderName = "x64"
}
else
{
$folderName = "Win32"
}
}
if([String]::IsNullOrEmpty($Configuration))
{
if( $folderName -ieq "Win32" )
{
$RealConfiguration = "Debug"
}
else
{
$RealConfiguration = "Release"
}
}
else
{
$RealConfiguration = $Configuration
}
[System.IO.DirectoryInfo] $repositoryRoot = Get-RepositoryRoot
$sourceDir = Join-Path $repositoryRoot.FullName -ChildPath "bin\$folderName\$RealConfiguration"
Copy-Item -Path "$sourceDir\*" -Destination $OpenSSHDir -Include *.exe,*.dll -Exclude *unittest*.* -Force -ErrorAction Stop
$sourceDir = Join-Path $repositoryRoot.FullName -ChildPath "contrib\win32\openssh"
Copy-Item -Path "$sourceDir\*" -Destination $OpenSSHDir -Include *.ps1,sshd_config -Exclude AnalyzeCodeDiff.ps1 -Force -ErrorAction Stop
$packageName = "rktools.2003"
$rktoolsPath = "${env:ProgramFiles(x86)}\Windows Resource Kits\Tools\ntrights.exe"
if (-not (Test-Path -Path $rktoolsPath))
{
Write-Log -Message "$packageName not present. Installing $packageName."
choco install $packageName -y --force 2>&1 >> $script:logFile
if (-not (Test-Path -Path $rktoolsPath))
{
choco install $packageName -y --force 2>&1 >> $script:logFile
if (-not (Test-Path -Path $rktoolsPath))
{
Write-BuildMessage "Installation dependencies: failed to download $packageName. try again please." -Category Error
throw "failed to download $packageName"
}
}
}
Copy-Item -Path $rktoolsPath -Destination $OpenSSHDir -Force -ErrorAction Stop
$packageFolder = $env:SystemDrive
if ($env:APPVEYOR_BUILD_FOLDER)
{
$packageFolder = $env:APPVEYOR_BUILD_FOLDER
}
$package = "$packageFolder\Win32OpenSSH$RealConfiguration$folderName.zip"
$allPackage = "$packageFolder\Win32OpenSSH*.zip"
if (Test-Path $allPackage)
{
Remove-Item -Path $allPackage -Force -ErrorAction SilentlyContinue
}
Add-Type -assemblyname System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::CreateFromDirectory($OpenSSHDir, $package)
}
<#
.Synopsis
After build and test run completes, upload all artifacts from the build machine.
#>
function Deploy-OpenSSHTests
{
[CmdletBinding()]
param
(
[string] $OpenSSHTestDir = "$env:SystemDrive\OpenSSH",
[ValidateSet('Debug', 'Release', '')]
[string]$Configuration = "",
[ValidateSet('x86', 'x64', '')]
[string]$NativeHostArch = ""
)
if (-not (Test-Path -Path $OpenSSHTestDir -PathType Container))
{
$null = New-Item -Path $OpenSSHTestDir -ItemType Directory -Force -ErrorAction Stop
}
[string] $platform = $env:PROCESSOR_ARCHITECTURE
if(-not [String]::IsNullOrEmpty($NativeHostArch))
{
$folderName = $NativeHostArch
if($NativeHostArch -eq 'x86')
{
$folderName = "Win32"
}
}
else
{
if($platform -ieq "AMD64")
{
$folderName = "x64"
}
else
{
$folderName = "Win32"
}
}
if([String]::IsNullOrEmpty($Configuration))
{
if( $folderName -ieq "Win32" )
{
$RealConfiguration = "Debug"
}
else
{
$RealConfiguration = "Release"
}
}
else
{
$RealConfiguration = $Configuration
}
[System.IO.DirectoryInfo] $repositoryRoot = Get-RepositoryRoot
#copy all pester tests
$sourceDir = Join-Path $repositoryRoot.FullName -ChildPath "regress\pesterTests"
Copy-Item -Path "$sourceDir\*" -Destination $OpenSSHTestDir -Include *.ps1,*.psm1, sshd_config -Force -ErrorAction Stop
#copy all unit tests.
$sourceDir = Join-Path $repositoryRoot.FullName -ChildPath "bin\$folderName\$RealConfiguration"
Copy-Item -Path "$sourceDir\*" -Destination "$OpenSSHTestDir\" -Container -Include unittest-* -Recurse -Force -ErrorAction Stop
#restart the service to use the test copy of sshd_config
Restart-Service sshd
}
<#
.Synopsis
Adds a build log to the list of published artifacts.
.Description
If a build log exists, it is renamed to reflect the associated CLR runtime then added to the list of
artifacts to publish. If it doesn't exist, a warning is written and the file is skipped.
The rename is needed since publishing overwrites the artifact if it already exists.
.Parameter artifacts
An array list to add the fully qualified build log path
.Parameter buildLog
The build log file produced by the build.
#>
function Add-BuildLog
{
param
(
[ValidateNotNull()]
[System.Collections.ArrayList] $artifacts,
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $buildLog
)
if (Test-Path -Path $buildLog)
{
$null = $artifacts.Add($buildLog)
}
else
{
Write-Warning "Skip publishing build log. $buildLog does not exist"
}
}
<#
.Synopsis
Publishes package build artifacts.
.Parameter artifacts
An array list to add the fully qualified build log path
.Parameter packageFile
Path to the package
#>
function Add-Artifact
{
param
(
[ValidateNotNull()]
[System.Collections.ArrayList] $artifacts,
[string] $FileToAdd
)
$files = Get-ChildItem -Path $FileToAdd -ErrorAction Ignore
if ($files -ne $null)
{
$files | % {
$null = $artifacts.Add($_.FullName)
}
}
else
{
Write-Log -Message "Skip publishing package artifacts. $FileToAdd does not exist"
}
}
<#
.Synopsis
After build and test run completes, upload all artifacts from the build machine.
#>
function Publish-Artifact
{
Write-Host -ForegroundColor Yellow "Publishing project artifacts"
[System.Collections.ArrayList] $artifacts = [System.Collections.ArrayList]::new()
$packageFolder = $env:SystemDrive
if ($env:APPVEYOR_BUILD_FOLDER)
{
$packageFolder = $env:APPVEYOR_BUILD_FOLDER
}
Add-Artifact -artifacts $artifacts -FileToAdd "$packageFolder\Win32OpenSSH*.zip"
Add-Artifact -artifacts $artifacts -FileToAdd "$env:SystemDrive\OpenSSH\UnitTestResults.txt"
Add-Artifact -artifacts $artifacts -FileToAdd "$env:SystemDrive\OpenSSH\TestError.txt"
# Get the build.log file for each build configuration
Add-BuildLog -artifacts $artifacts -buildLog (Get-BuildLogFile -root $repoRoot.FullName)
Add-Artifact -artifacts $artifacts -FileToAdd "$script:logFile"
Add-Artifact -artifacts $artifacts -FileToAdd "$script:messageFile"
foreach ($artifact in $artifacts)
{
Write-Log -Message "Publishing $artifact as Appveyor artifact"
# NOTE: attempt to publish subsequent artifacts even if the current one fails
Push-AppveyorArtifact $artifact -ErrorAction "Continue"
}
}
<#
.Synopsis
Run OpenSSH pester tests.
#>
function Run-OpenSSHPesterTest
{
param($testRoot = "$env:SystemDrive\OpenSSH",
$outputXml = "$env:SystemDrive\OpenSSH\TestResults.xml")
# Discover all CI tests and run them.
Push-Location $testRoot
Write-Log -Message "Running OpenSSH Pester tests..."
$testFolders = Get-ChildItem *.tests.ps1 -Recurse | ForEach-Object{ Split-Path $_.FullName} | Sort-Object -Unique
Invoke-Pester $testFolders -OutputFormat NUnitXml -OutputFile $outputXml -Tag 'CI'
Pop-Location
}
function Check-PesterTestResult
{
param($outputXml = "$env:SystemDrive\OpenSSH\TestResults.xml")
if (-not (Test-Path $outputXml))
{
Write-Warning "$($xml.'test-results'.failures) tests in regress\pesterTests failed"
Write-BuildMessage -Message "Test result file $outputXml not found after tests." -Category Error
Set-BuildVariable TestPassed False
}
$xml = [xml](Get-Content -raw $outputXml)
if ([int]$xml.'test-results'.failures -gt 0)
{
$errorMessage = "$($xml.'test-results'.failures) tests in regress\pesterTests failed. Detail test log is at TestResults.xml."
Write-Warning $errorMessage
Write-BuildMessage -Message $errorMessage -Category Error
Set-BuildVariable TestPassed False
}
# Writing out warning when the $Error.Count is non-zero. Tests Should clean $Error after success.
if ($Error.Count -gt 0)
{
Write-BuildMessage -Message "Tests Should clean $Error after success." -Category Warning
$Error| Out-File "$testInstallFolder\TestError.txt" -Append
}
}
<#
.Synopsis
Run unit tests.
#>
function Run-OpenSSHUnitTest
{
param($testRoot = "$env:SystemDrive\OpenSSH",
$unitTestOutputFile = "$env:SystemDrive\OpenSSH\UnitTestResults.txt")
# Discover all CI tests and run them.
Push-Location $testRoot
Write-Log -Message "Running OpenSSH unit tests..."
if (Test-Path $unitTestOutputFile)
{
Remove-Item -Path $unitTestOutputFile -Force -ErrorAction SilentlyContinue
}
$testFolders = Get-ChildItem unittest-*.exe -Recurse -Exclude unittest-sshkey.exe,unittest-kex.exe |
ForEach-Object{ Split-Path $_.FullName} |
Sort-Object -Unique
$testfailed = $false
if ($testFolders -ne $null)
{
$testFolders | % {
Push-Location $_
$unittestFile = "$(Split-Path $_ -Leaf).exe"
Write-Output "Running OpenSSH unit $unittestFile ..."
& .\$unittestFile >> $unitTestOutputFile
$errorCode = $LASTEXITCODE
if ($errorCode -ne 0)
{
$testfailed = $true
$errorMessage = "$($_.FullName) test failed for OpenSSH.`nExitCode: $errorCode. Detail test log is at UnitTestResults.txt."
Write-Warning $errorMessage
Write-BuildMessage -Message $errorMessage -Category Error
Set-BuildVariable TestPassed False
}
Pop-Location
}
if(-not $testfailed)
{
Write-BuildMessage -Message "All Unit tests passed!" -Category Information
}
}
Pop-Location
}
<#
.Synopsis
Runs the tests for this repo
.Parameter testResultsFile
The name of the xml file to write pester results.
The default value is '.\testResults.xml'
.Example
.\RunTests.ps1
Runs the tests and creates the default 'testResults.xml'
#>
function Run-OpenSSHTests
{
[CmdletBinding()]
param
(
[string] $testResultsFile = "$env:SystemDrive\OpenSSH\TestResults.xml",
[string] $unitTestResultsFile = "$env:SystemDrive\OpenSSH\UnitTestResults.txt",
[string] $testInstallFolder = "$env:SystemDrive\OpenSSH"
)
Deploy-OpenSSHTests -OpenSSHTestDir $testInstallFolder
Run-OpenSSHUnitTest -testRoot $testInstallFolder -unitTestOutputFile $unitTestResultsFile
# Run all pester tests.
Run-OpenSSHPesterTest -testRoot $testInstallFolder -outputXml $testResultsFile
}
function Upload-OpenSSHTestResults
{
[CmdletBinding()]
param
(
[string] $testResultsFile = "$env:SystemDrive\OpenSSH\TestResults.xml"
)
if ($env:APPVEYOR_JOB_ID)
{
$resultFile = Resolve-Path $testResultsFile -ErrorAction Ignore
if($resultFile)
{
(New-Object 'System.Net.WebClient').UploadFile("https://ci.appveyor.com/api/testresults/nunit/$($env:APPVEYOR_JOB_ID)", $resultFile)
Write-BuildMessage -Message "Test results uploaded!" -Category Information
}
}
if ($env:DebugMode)
{
Remove-Item $env:DebugMode
}
if($env:TestPassed -ieq 'True')
{
Write-BuildMessage -Message "The checkin validation success!" -Category Information
}
else
{
Write-BuildMessage -Message "The checkin validation failed!" -Category Error
throw "The checkin validation failed!"
}
}
Export-ModuleMember -Function Set-BuildVariable, Invoke-AppVeyorBuild, Install-OpenSSH, Install-TestDependencies, GetLocalPSCorePath, Upload-OpenSSHTestResults, Run-OpenSSHTests, Publish-Artifact, Start-SSHBuild, Deploy-OpenSSHTests, Run-OpenSSHUnitTest,Run-OpenSSHPesterTest,Check-PesterTestResult

View File

@ -290,7 +290,6 @@
<ClInclude Include="$(OpenSSH-Src-Path)uuencode.h" />
<ClInclude Include="$(OpenSSH-Src-Path)version.h" />
<ClInclude Include="$(OpenSSH-Src-Path)xmalloc.h" />
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\wmain_common.c" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(OpenSSH-Src-Path)clientloop.c" />
@ -299,7 +298,8 @@
<ClCompile Include="$(OpenSSH-Src-Path)sshconnect.c" />
<ClCompile Include="$(OpenSSH-Src-Path)sshconnect1.c" />
<ClCompile Include="$(OpenSSH-Src-Path)sshconnect2.c" />
<ClCompile Include="$(OpenSSH-Src-Path)sshtty.c" />
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\wmain_common.c" />
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32_sshtty.c" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="version.rc" />

View File

@ -305,10 +305,10 @@
<ClCompile Include="$(OpenSSH-Src-Path)sshconnect2.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(OpenSSH-Src-Path)sshtty.c">
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\wmain_common.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\wmain_common.c">
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32_sshtty.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>

View File

@ -222,6 +222,7 @@
<ClCompile Include="$(OpenSSH-Src-Path)auth2-passwd.c" />
<ClCompile Include="$(OpenSSH-Src-Path)auth2-pubkey.c" />
<ClCompile Include="$(OpenSSH-Src-Path)auth2.c" />
<ClCompile Include="$(OpenSSH-Src-Path)groupaccess.c" />
<ClCompile Include="$(OpenSSH-Src-Path)gss-serv-krb5.c" />
<ClCompile Include="$(OpenSSH-Src-Path)gss-serv.c" />
<ClCompile Include="$(OpenSSH-Src-Path)kexdhs.c" />
@ -244,9 +245,8 @@
<ClCompile Include="$(OpenSSH-Src-Path)sftp-common.c" />
<ClCompile Include="$(OpenSSH-Src-Path)sshd.c" />
<ClCompile Include="$(OpenSSH-Src-Path)sshlogin.c" />
<ClCompile Include="$(OpenSSH-Src-Path)sshpty.c" />
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32_sshpty.c" />
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\wmain_sshd.c" />
<ClCompile Include="$(OpenSSH-Src-Path)groupaccess.c" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="version.rc" />

View File

@ -144,15 +144,15 @@
<ClCompile Include="$(OpenSSH-Src-Path)sshlogin.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(OpenSSH-Src-Path)sshpty.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\wmain_sshd.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(OpenSSH-Src-Path)groupaccess.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32_sshpty.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="version.rc">

View File

@ -204,8 +204,9 @@
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\sys\types.h" />
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\ctype.h" />
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\stdlib.h" />
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\debug.h" />
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\console.h" />
<ClInclude Include="..\win32compat\tnnet.h" />
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\tnnet.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@ -139,8 +139,9 @@
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\ctype.h">
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\debug.h" />
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\console.h" />
<ClInclude Include="..\win32compat\tnnet.h" />
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\tnnet.h" />
</ItemGroup>
<ItemGroup>
<Filter Include="inc">

View File

@ -1,39 +1,10 @@
/*
* Author: NoMachine <developers@nomachine.com>
*
* Copyright (c) 2009, 2011 NoMachine
* All rights reserved
*
* Support functions and system calls' replacements needed to let the
* software run on Win32 based operating systems.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#ifndef Debug_H
#define Debug_H
#define FAIL(CONDITION) if (CONDITION) goto fail
#define NTFAIL(NTFUNC) if((ntStat = (NTFUNC))) goto fail
#endif
/* Enable the following for verbose logging */
#if (0)
#define debug4 debug2
#define debug5 debug3
#else
#define debug4(a,...)
#define debug5(a,...)
#endif

View File

@ -39,6 +39,7 @@
#include "inc\utf.h"
#include "inc\fcntl.h"
#include "misc_internal.h"
#include "debug.h"
/* internal read buffer size */
#define READ_BUFFER_SIZE 100*1024
@ -97,7 +98,7 @@ fileio_connect(struct w32_io* pio, char* name)
int ret = 0;
if (pio->handle != 0 && pio->handle != INVALID_HANDLE_VALUE) {
debug("fileio_connect called in unexpected state, pio = %p", pio);
debug3("fileio_connect called in unexpected state, pio = %p", pio);
errno = EOTHER;
ret = -1;
goto cleanup;
@ -114,13 +115,13 @@ fileio_connect(struct w32_io* pio, char* name)
/* TODO - support nonblocking connect */
/* wait until we have a server pipe instance to connect */
while (h == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PIPE_BUSY) {
debug2("waiting for agent connection, retrying after 1 sec");
debug4("waiting for agent connection, retrying after 1 sec");
if ((ret = wait_for_any_event(NULL, 0, 1000) != 0) != 0)
goto cleanup;
}
if (h == INVALID_HANDLE_VALUE) {
debug("unable to connect to pipe %ls, error: %d", name_w, GetLastError());
debug3("unable to connect to pipe %ls, error: %d", name_w, GetLastError());
errno = errno_from_Win32LastError();
ret = -1;
goto cleanup;
@ -129,7 +130,7 @@ fileio_connect(struct w32_io* pio, char* name)
if (SetHandleInformation(h, HANDLE_FLAG_INHERIT,
pio->fd_flags & FD_CLOEXEC ? 0 : HANDLE_FLAG_INHERIT) == FALSE) {
errno = errno_from_Win32LastError();
debug("SetHandleInformation failed, error = %d, pio = %p", GetLastError(), pio);
debug3("SetHandleInformation failed, error = %d, pio = %p", GetLastError(), pio);
ret = -1;
goto cleanup;
}
@ -162,7 +163,7 @@ fileio_pipe(struct w32_io* pio[2])
if (pio == NULL) {
errno = EINVAL;
debug("pipe - ERROR invalid parameter");
debug3("pipe - ERROR invalid parameter");
return -1;
}
@ -170,7 +171,7 @@ fileio_pipe(struct w32_io* pio[2])
if (-1 == sprintf_s(pipe_name, PATH_MAX, "\\\\.\\Pipe\\W32PosixPipe.%08x.%08x",
GetCurrentProcessId(), pipe_counter++)) {
errno = EOTHER;
debug("pipe - ERROR sprintf_s %d", errno);
debug3("pipe - ERROR sprintf_s %d", errno);
goto error;
}
@ -189,7 +190,7 @@ fileio_pipe(struct w32_io* pio[2])
&sec_attributes);
if (read_handle == INVALID_HANDLE_VALUE) {
errno = errno_from_Win32LastError();
debug("pipe - CreateNamedPipe() ERROR:%d", errno);
debug3("pipe - CreateNamedPipe() ERROR:%d", errno);
goto error;
}
@ -203,7 +204,7 @@ fileio_pipe(struct w32_io* pio[2])
NULL);
if (write_handle == INVALID_HANDLE_VALUE) {
errno = errno_from_Win32LastError();
debug("pipe - ERROR CreateFile() :%d", errno);
debug3("pipe - ERROR CreateFile() :%d", errno);
goto error;
}
@ -213,7 +214,7 @@ fileio_pipe(struct w32_io* pio[2])
if (!pio_read || !pio_write) {
errno = ENOMEM;
debug("pip - ERROR:%d", errno);
debug3("pip - ERROR:%d", errno);
goto error;
}
@ -252,21 +253,21 @@ createFile_flags_setup(int flags, int mode, struct createFile_flags* cf_flags)
* O_RDONLY, O_WRONLY, or O_RDWR
*/
if ((rwflags != O_RDONLY) && (rwflags != O_WRONLY) && (rwflags != O_RDWR)) {
debug("open - flags ERROR: wrong rw flags: %d", flags);
debug3("open - flags ERROR: wrong rw flags: %d", flags);
errno = EINVAL;
return -1;
}
/*only following create and status flags currently supported*/
if (c_s_flags & ~(O_NONBLOCK | O_APPEND | O_CREAT | O_TRUNC | O_EXCL | O_BINARY)) {
debug("open - ERROR: Unsupported flags: %d", flags);
debug3("open - ERROR: Unsupported flags: %d", flags);
errno = ENOTSUP;
return -1;
}
/*validate mode*/
if (mode &~(S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) {
debug("open - ERROR: unsupported mode: %d", mode);
debug3("open - ERROR: unsupported mode: %d", mode);
errno = ENOTSUP;
return -1;
}
@ -319,17 +320,17 @@ fileio_open(const char *path_utf8, int flags, int mode)
HANDLE handle;
wchar_t *path_utf16 = NULL;
debug2("open - pathname:%s, flags:%d, mode:%d", path_utf8, flags, mode);
debug4("open - pathname:%s, flags:%d, mode:%d", path_utf8, flags, mode);
/* check input params*/
if (path_utf8 == NULL) {
errno = EINVAL;
debug("open - ERROR:%d", errno);
debug3("open - ERROR:%d", errno);
return NULL;
}
if ((path_utf16 = utf8_to_utf16(path_utf8)) == NULL) {
errno = ENOMEM;
debug("utf8_to_utf16 failed for file:%s error:%d", path_utf8, GetLastError());
debug3("utf8_to_utf16 failed for file:%s error:%d", path_utf8, GetLastError());
return NULL;
}
@ -342,7 +343,7 @@ fileio_open(const char *path_utf8, int flags, int mode)
if (handle == INVALID_HANDLE_VALUE) {
errno = errno_from_Win32LastError();
debug("failed to open file:%s error:%d", path_utf8, GetLastError());
debug3("failed to open file:%s error:%d", path_utf8, GetLastError());
free(path_utf16);
return NULL;
}
@ -352,7 +353,7 @@ fileio_open(const char *path_utf8, int flags, int mode)
if (pio == NULL) {
CloseHandle(handle);
errno = ENOMEM;
debug("fileio_open(), failed to allocate memory error:%d", errno);
debug3("fileio_open(), failed to allocate memory error:%d", errno);
return NULL;
}
@ -369,7 +370,7 @@ VOID CALLBACK
ReadCompletionRoutine(_In_ DWORD dwErrorCode, _In_ DWORD dwNumberOfBytesTransfered, _Inout_ LPOVERLAPPED lpOverlapped)
{
struct w32_io* pio = (struct w32_io*)((char*)lpOverlapped - offsetof(struct w32_io, read_overlapped));
debug2("ReadCB pio:%p, pending_state:%d, error:%d, received:%d",
debug4("ReadCB pio:%p, pending_state:%d, error:%d, received:%d",
pio, pio->read_details.pending, dwErrorCode, dwNumberOfBytesTransfered);
pio->read_details.error = dwErrorCode;
pio->read_details.remaining = dwNumberOfBytesTransfered;
@ -383,13 +384,13 @@ ReadCompletionRoutine(_In_ DWORD dwErrorCode, _In_ DWORD dwNumberOfBytesTransfer
int
fileio_ReadFileEx(struct w32_io* pio, unsigned int bytes_requested)
{
debug2("ReadFileEx io:%p", pio);
debug4("ReadFileEx io:%p", pio);
if (pio->read_details.buf == NULL) {
pio->read_details.buf = malloc(READ_BUFFER_SIZE);
if (!pio->read_details.buf) {
errno = ENOMEM;
debug2("ReadFileEx - ERROR: %d, io:%p", errno, pio);
debug4("ReadFileEx - ERROR: %d, io:%p", errno, pio);
return -1;
}
}
@ -404,7 +405,7 @@ fileio_ReadFileEx(struct w32_io* pio, unsigned int bytes_requested)
pio->read_details.pending = TRUE;
else {
errno = errno_from_Win32LastError();
debug("ReadFileEx() ERROR:%d, io:%p", GetLastError(), pio);
debug3("ReadFileEx() ERROR:%d, io:%p", GetLastError(), pio);
return -1;
}
@ -417,18 +418,18 @@ fileio_read(struct w32_io* pio, void *dst, unsigned int max)
{
int bytes_copied;
debug3("read - io:%p remaining:%d", pio, pio->read_details.remaining);
debug5("read - io:%p remaining:%d", pio, pio->read_details.remaining);
/* if read is pending */
if (pio->read_details.pending) {
if (w32_io_is_blocking(pio)) {
debug2("read - io is pending, blocking call made, io:%p", pio);
debug4("read - io is pending, blocking call made, io:%p", pio);
while (fileio_is_io_available(pio, TRUE) == FALSE) {
if (-1 == wait_for_any_event(NULL, 0, INFINITE))
return -1;
}
}
errno = EAGAIN;
debug2("read - io is already pending, io:%p", pio);
debug4("read - io is already pending, io:%p", pio);
return -1;
}
@ -442,14 +443,14 @@ fileio_read(struct w32_io* pio, void *dst, unsigned int max)
if ((FILETYPE(pio) == FILE_TYPE_PIPE)
&& (errno == ERROR_BROKEN_PIPE)) {
/* write end of the pipe closed */
debug("read - no more data, io:%p", pio);
debug3("read - no more data, io:%p", pio);
errno = 0;
return 0;
}
/* on W2012, ReadFileEx on file throws a synchronous EOF error*/
else if ((FILETYPE(pio) == FILE_TYPE_DISK)
&& (errno == ERROR_HANDLE_EOF)) {
debug("read - no more data, io:%p", pio);
debug3("read - no more data, io:%p", pio);
errno = 0;
return 0;
}
@ -468,7 +469,7 @@ fileio_read(struct w32_io* pio, void *dst, unsigned int max)
}
else if (pio->read_details.pending) {
errno = EAGAIN;
debug2("read - IO is pending, io:%p", pio);
debug4("read - IO is pending, io:%p", pio);
return -1;
}
}
@ -478,12 +479,12 @@ fileio_read(struct w32_io* pio, void *dst, unsigned int max)
/*write end of the pipe is closed or pipe broken or eof reached*/
if ((pio->read_details.error == ERROR_BROKEN_PIPE) ||
(pio->read_details.error == ERROR_HANDLE_EOF)) {
debug2("read - (2) no more data, io:%p", pio);
debug4("read - (2) no more data, io:%p", pio);
errno = 0;
pio->read_details.error = 0;
return 0;
}
debug("read - ERROR from cb :%d, io:%p", errno, pio);
debug3("read - ERROR from cb :%d, io:%p", errno, pio);
pio->read_details.error = 0;
return -1;
}
@ -492,7 +493,7 @@ fileio_read(struct w32_io* pio, void *dst, unsigned int max)
memcpy(dst, pio->read_details.buf + pio->read_details.completed, bytes_copied);
pio->read_details.remaining -= bytes_copied;
pio->read_details.completed += bytes_copied;
debug2("read - io:%p read: %d remaining: %d", pio, bytes_copied,
debug4("read - io:%p read: %d remaining: %d", pio, bytes_copied,
pio->read_details.remaining);
return bytes_copied;
}
@ -504,13 +505,13 @@ WriteCompletionRoutine(_In_ DWORD dwErrorCode,
{
struct w32_io* pio =
(struct w32_io*)((char*)lpOverlapped - offsetof(struct w32_io, write_overlapped));
debug2("WriteCB - pio:%p, pending_state:%d, error:%d, transferred:%d of remaining: %d",
debug4("WriteCB - pio:%p, pending_state:%d, error:%d, transferred:%d of remaining: %d",
pio, pio->write_details.pending, dwErrorCode, dwNumberOfBytesTransfered,
pio->write_details.remaining);
pio->write_details.error = dwErrorCode;
/* TODO - assert that remaining == dwNumberOfBytesTransfered */
if ((dwErrorCode == 0) && (pio->write_details.remaining != dwNumberOfBytesTransfered)) {
debug("WriteCB - ERROR: broken assumption, io:%p, wrote:%d, remaining:%d", pio,
debug3("WriteCB - ERROR: broken assumption, io:%p, wrote:%d, remaining:%d", pio,
dwNumberOfBytesTransfered, pio->write_details.remaining);
DebugBreak();
}
@ -525,26 +526,26 @@ fileio_write(struct w32_io* pio, const void *buf, unsigned int max)
{
int bytes_copied;
debug2("write - io:%p", pio);
debug4("write - io:%p", pio);
if (pio->write_details.pending) {
if (w32_io_is_blocking(pio)) {
debug2("write - io pending, blocking call made, io:%p", pio);
debug4("write - io pending, blocking call made, io:%p", pio);
while (pio->write_details.pending)
if (wait_for_any_event(NULL, 0, INFINITE) == -1)
return -1;
} else {
errno = EAGAIN;
debug2("write - IO is already pending, io:%p", pio);
debug4("write - IO is already pending, io:%p", pio);
return -1;
}
}
if (pio->write_details.error) {
errno = errno_from_Win32Error(pio->write_details.error);
debug("write - ERROR:%d on prior unblocking write, io:%p", errno, pio);
debug3("write - ERROR:%d on prior unblocking write, io:%p", errno, pio);
pio->write_details.error = 0;
if ((FILETYPE(pio) == FILE_TYPE_PIPE) && (errno == ERROR_BROKEN_PIPE)) {
debug("write - ERROR:read end of the pipe closed, io:%p", pio);
debug3("write - ERROR:read end of the pipe closed, io:%p", pio);
errno = EPIPE;
}
return -1;
@ -554,7 +555,7 @@ fileio_write(struct w32_io* pio, const void *buf, unsigned int max)
pio->write_details.buf = malloc(WRITE_BUFFER_SIZE);
if (pio->write_details.buf == NULL) {
errno = ENOMEM;
debug("write - ERROR:%d, io:%p", errno, pio);
debug3("write - ERROR:%d, io:%p", errno, pio);
return -1;
}
pio->write_details.buf_size = WRITE_BUFFER_SIZE;
@ -579,10 +580,10 @@ fileio_write(struct w32_io* pio, const void *buf, unsigned int max)
errno = errno_from_Win32LastError();
/* read end of the pipe closed ? */
if ((FILETYPE(pio) == FILE_TYPE_PIPE) && (errno == ERROR_BROKEN_PIPE)) {
debug("write - ERROR:read end of the pipe closed, io:%p", pio);
debug3("write - ERROR:read end of the pipe closed, io:%p", pio);
errno = EPIPE;
}
debug("write ERROR from cb(2):%d, io:%p", errno, pio);
debug3("write ERROR from cb(2):%d, io:%p", errno, pio);
return -1;
}
}
@ -604,11 +605,11 @@ fileio_write(struct w32_io* pio, const void *buf, unsigned int max)
/* if write has completed, pick up any error reported*/
if (!pio->write_details.pending && pio->write_details.error) {
errno = errno_from_Win32Error(pio->write_details.error);
debug("write - ERROR from cb:%d, io:%p", pio->write_details.error, pio);
debug3("write - ERROR from cb:%d, io:%p", pio->write_details.error, pio);
pio->write_details.error = 0;
return -1;
}
debug2("write - reporting %d bytes written, io:%p", bytes_copied, pio);
debug4("write - reporting %d bytes written, io:%p", bytes_copied, pio);
return bytes_copied;
}
@ -618,7 +619,7 @@ int
fileio_fstat(struct w32_io* pio, struct _stat64 *buf)
{
int fd = _open_osfhandle((intptr_t)pio->handle, 0);
debug2("fstat - pio:%p", pio);
debug4("fstat - pio:%p", pio);
if (fd == -1) {
errno = EOTHER;
return -1;
@ -654,9 +655,9 @@ fileio_stat(const char *path, struct _stat64 *buf)
long
fileio_lseek(struct w32_io* pio, long offset, int origin)
{
debug2("lseek - pio:%p", pio);
debug4("lseek - pio:%p", pio);
if (origin != SEEK_SET) {
debug("lseek - ERROR, origin is not supported %d", origin);
debug3("lseek - ERROR, origin is not supported %d", origin);
errno = ENOTSUP;
return -1;
}
@ -671,7 +672,7 @@ FILE*
fileio_fdopen(struct w32_io* pio, const char *mode)
{
int fd_flags = 0;
debug2("fdopen - io:%p", pio);
debug4("fdopen - io:%p", pio);
/* logic below doesn't work with overlapped file HANDLES */
if (mode[1] == '\0') {
@ -686,12 +687,12 @@ fileio_fdopen(struct w32_io* pio, const char *mode)
break;
default:
errno = ENOTSUP;
debug("fdopen - ERROR unsupported mode %s", mode);
debug3("fdopen - ERROR unsupported mode %s", mode);
return NULL;
}
} else {
errno = ENOTSUP;
debug("fdopen - ERROR unsupported mode %s", mode);
debug3("fdopen - ERROR unsupported mode %s", mode);
return NULL;
}
@ -699,7 +700,7 @@ fileio_fdopen(struct w32_io* pio, const char *mode)
if (fd == -1) {
errno = EOTHER;
debug("fdopen - ERROR:%d _open_osfhandle()", errno);
debug3("fdopen - ERROR:%d _open_osfhandle()", errno);
return NULL;
}
@ -732,7 +733,7 @@ fileio_on_select(struct w32_io* pio, BOOL rd)
int
fileio_close(struct w32_io* pio)
{
debug2("fileclose - pio:%p", pio);
debug4("fileclose - pio:%p", pio);
/* handle can be null on AF_UNIX sockets that are not yet connected */
if (WINHANDLE(pio) == 0 || WINHANDLE(pio) == INVALID_HANDLE_VALUE) {

View File

@ -81,4 +81,21 @@ char *crypt(const char *key, const char *salt);
int link(const char *oldpath, const char *newpath);
int readlink(const char *path, char *link, int linklen);
int spawn_child(char* cmd, int in, int out, int err, unsigned long flags);
int spawn_child(char* cmd, char** argv, int in, int out, int err, unsigned long flags);
/*
* readpassphrase.h definitions
* cannot create a separate header due to the way
* its included in openbsdcompat.h
*/
#define RPP_ECHO_OFF 0x00 /* Turn off echo (default). */
#define RPP_ECHO_ON 0x01 /* Leave echo on. */
#define RPP_REQUIRE_TTY 0x02 /* Fail if there is no tty. */
#define RPP_FORCELOWER 0x04 /* Force input to lower case. */
#define RPP_FORCEUPPER 0x08 /* Force input to upper case. */
#define RPP_SEVENBIT 0x10 /* Strip the high bit from input. */
#define RPP_STDIN 0x20 /* Read from stdin, not /dev/tty */
char * readpassphrase(const char *, char *, size_t, int);

View File

@ -33,6 +33,7 @@
#include <time.h>
#include <Shlwapi.h>
#include "inc\unistd.h"
#include "inc\sys\stat.h"
#include "inc\sys\statvfs.h"
#include "inc\sys\time.h"
@ -44,6 +45,7 @@
#include "inc\fcntl.h"
#include "inc\utf.h"
#include "signal_internal.h"
#include "debug.h"
static char* s_programdir = NULL;
@ -249,7 +251,7 @@ w32_fopen_utf8(const char *path, const char *mode)
if (MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, PATH_MAX) == 0 ||
MultiByteToWideChar(CP_UTF8, 0, mode, -1, wmode, 5) == 0) {
errno = EFAULT;
debug("WideCharToMultiByte failed for %c - ERROR:%d", path, GetLastError());
debug3("WideCharToMultiByte failed for %c - ERROR:%d", path, GetLastError());
return NULL;
}
@ -402,15 +404,26 @@ w32_ioctl(int d, int request, ...)
}
}
/*
* spawn a child process
* - specified by cmd with agruments argv
* - with std handles set to in, out, err
* - flags are passed to CreateProcess call
*
* cmd will be internally decoarated with a set of '"'
* to account for any spaces within the commandline
* this decoration is done only when additional arguments are passed in argv
*/
int
spawn_child(char* cmd, int in, int out, int err, DWORD flags)
spawn_child(char* cmd, char** argv, int in, int out, int err, DWORD flags)
{
PROCESS_INFORMATION pi;
STARTUPINFOW si;
BOOL b;
char *abs_cmd, *t;
wchar_t * cmd_utf16;
int add_module_path = 0;
char *cmdline, *t, **t1;
DWORD cmdline_len = 0;
wchar_t * cmdline_utf16;
int add_module_path = 0, ret = -1;
/* should module path be added */
do {
@ -424,31 +437,57 @@ spawn_child(char* cmd, int in, int out, int err, DWORD flags)
add_module_path = 1;
} while (0);
/* add current module path to start if needed */
if (add_module_path) {
char* ctr;
abs_cmd = malloc(strlen(w32_programdir()) + 1 + strlen(cmd) + 1);
if (abs_cmd == NULL) {
errno = ENOMEM;
return -1;
}
ctr = abs_cmd;
memcpy(ctr, w32_programdir(), strlen(w32_programdir()));
ctr += strlen(w32_programdir());
*ctr++ = '\\';
memcpy(ctr, cmd, strlen(cmd) + 1);
} else
abs_cmd = cmd;
/* compute total cmdline len*/
if (add_module_path)
cmdline_len += strlen(w32_programdir()) + 1 + strlen(cmd) + 1 + 2;
else
cmdline_len += strlen(cmd) + 1 + 2;
debug("spawning %s", abs_cmd);
if ((cmd_utf16 = utf8_to_utf16(abs_cmd)) == NULL) {
errno = ENOMEM;
return -1;
if (argv) {
t1 = argv;
while (*t1)
cmdline_len += strlen(*t1++) + 1 + 2;
}
if (abs_cmd != cmd)
free(abs_cmd);
if ((cmdline = malloc(cmdline_len)) == NULL) {
errno = ENOMEM;
goto cleanup;
}
/* add current module path to start if needed */
t = cmdline;
if (argv && argv[0])
*t++ = '\"';
if (add_module_path) {
memcpy(t, w32_programdir(), strlen(w32_programdir()));
t += strlen(w32_programdir());
*t++ = '\\';
}
memcpy(t, cmd, strlen(cmd));
t += strlen(cmd);
if (argv && argv[0])
*t++ = '\"';
if (argv) {
t1 = argv;
while (*t1) {
*t++ = ' ';
*t++ = '\"';
memcpy(t, *t1, strlen(*t1));
t += strlen(*t1);
*t++ = '\"';
t1++;
}
}
*t = '\0';
if ((cmdline_utf16 = utf8_to_utf16(cmdline)) == NULL) {
errno = ENOMEM;
goto cleanup;
}
memset(&si, 0, sizeof(STARTUPINFOW));
si.cb = sizeof(STARTUPINFOW);
@ -457,22 +496,29 @@ spawn_child(char* cmd, int in, int out, int err, DWORD flags)
si.hStdError = w32_fd_to_handle(err);
si.dwFlags = STARTF_USESTDHANDLES;
b = CreateProcessW(NULL, cmd_utf16, NULL, NULL, TRUE, flags, NULL, NULL, &si, &pi);
debug3("spawning %ls", cmdline_utf16);
b = CreateProcessW(NULL, cmdline_utf16, NULL, NULL, TRUE, flags, NULL, NULL, &si, &pi);
if (b) {
if (register_child(pi.hProcess, pi.dwProcessId) == -1) {
TerminateProcess(pi.hProcess, 0);
CloseHandle(pi.hProcess);
pi.dwProcessId = -1;
goto cleanup;
}
CloseHandle(pi.hThread);
} else {
errno = GetLastError();
pi.dwProcessId = -1;
goto cleanup;
}
free(cmd_utf16);
return pi.dwProcessId;
ret = pi.dwProcessId;
cleanup:
if (cmdline)
free(cmdline);
if (cmdline_utf16)
free(cmdline_utf16);
return ret;
}
void
@ -618,13 +664,13 @@ settimes(wchar_t * path, FILETIME *cretime, FILETIME *acttime, FILETIME *modtime
if (handle == INVALID_HANDLE_VALUE) {
/* TODO - convert Win32 error to errno */
errno = GetLastError();
debug("w32_settimes - CreateFileW ERROR:%d", errno);
debug3("w32_settimes - CreateFileW ERROR:%d", errno);
return -1;
}
if (SetFileTime(handle, cretime, acttime, modtime) == 0) {
errno = GetLastError();
debug("w32_settimes - SetFileTime ERROR:%d", errno);
debug3("w32_settimes - SetFileTime ERROR:%d", errno);
CloseHandle(handle);
return -1;
}
@ -953,12 +999,12 @@ statvfs(const char *path, struct statvfs *buf)
wchar_t* path_utf16 = utf8_to_utf16(sanitized_path(path));
if (GetDiskFreeSpaceW(path_utf16, &sectorsPerCluster, &bytesPerSector,
&freeClusters, &totalClusters) == TRUE) {
debug3("path : [%s]", path);
debug3("sectorsPerCluster : [%lu]", sectorsPerCluster);
debug3("bytesPerSector : [%lu]", bytesPerSector);
debug3("bytesPerCluster : [%lu]", sectorsPerCluster * bytesPerSector);
debug3("freeClusters : [%lu]", freeClusters);
debug3("totalClusters : [%lu]", totalClusters);
debug5("path : [%s]", path);
debug5("sectorsPerCluster : [%lu]", sectorsPerCluster);
debug5("bytesPerSector : [%lu]", bytesPerSector);
debug5("bytesPerCluster : [%lu]", sectorsPerCluster * bytesPerSector);
debug5("freeClusters : [%lu]", freeClusters);
debug5("totalClusters : [%lu]", totalClusters);
buf->f_bsize = sectorsPerCluster * bytesPerSector;
buf->f_frsize = sectorsPerCluster * bytesPerSector;
@ -975,7 +1021,7 @@ statvfs(const char *path, struct statvfs *buf)
free(path_utf16);
return 0;
} else {
debug3("ERROR: Cannot get free space for [%s]. Error code is : %d.\n", path, GetLastError());
debug5("ERROR: Cannot get free space for [%s]. Error code is : %d.\n", path, GetLastError());
free(path_utf16);
return -1;
@ -996,3 +1042,58 @@ w32_strerror(int errnum)
return _sys_errlist_ext[errnum - EADDRINUSE];
return strerror(errnum);
}
/*
* Temporary implementation of readpassphrase.
* TODO - this needs to be reimplemented as per
* https://linux.die.net/man/3/readpassphrase
*/
char *
readpassphrase(const char *prompt, char *out, size_t out_len, int flags) {
char *askpass = NULL;
char *ret = NULL;
DWORD mode;
size_t len = 0;
int retr = 0;
/* prompt user */
wchar_t* wtmp = utf8_to_utf16(prompt);
if (wtmp == NULL)
fatal("unable to alloc memory");
_cputws(wtmp);
free(wtmp);
len = retr = 0;
while (_kbhit())
_getch();
while (len < out_len) {
out[len] = (unsigned char)_getch();
if (out[len] == '\r') {
if (_kbhit()) /* read linefeed if its there */
_getch();
break;
}
else if (out[len] == '\n') {
break;
}
else if (out[len] == '\b') { /* backspace */
if (len > 0)
len--; /* overwrite last character */
}
else if (out[len] == '\003') {
/* exit on Ctrl+C */
fatal("");
}
else {
len++; /* keep reading in the loop */
}
}
out[len] = '\0'; /* get rid of the cr/lf */
_cputs("\n"); /*show a newline as we do not echo password or the line */
return out;
}

View File

@ -41,6 +41,7 @@
#include "inc\grp.h"
#include "inc\utf.h"
#include "misc_internal.h"
#include "debug.h"
static struct passwd pw;
static char* pw_shellpath = NULL;
@ -128,7 +129,7 @@ get_passwd(const char *user_utf8, LPWSTR user_sid)
if (user_sid == NULL) {
NET_API_STATUS status;
if ((status = NetUserGetInfo(udom_utf16, uname_utf16, 23, &user_info)) != NERR_Success) {
debug("NetUserGetInfo() failed with error: %d for user: %ls and domain: %ls \n", status, uname_utf16, udom_utf16);
debug3("NetUserGetInfo() failed with error: %d for user: %ls and domain: %ls \n", status, uname_utf16, udom_utf16);
if ((dsStatus = DsGetDcNameW(NULL, udom_utf16, NULL, NULL, DS_DIRECTORY_SERVICE_PREFERRED, &pdc)) != ERROR_SUCCESS) {
error("DsGetDcNameW() failed with error: %d \n", dsStatus);
@ -137,14 +138,14 @@ get_passwd(const char *user_utf8, LPWSTR user_sid)
}
if ((status = NetUserGetInfo(pdc->DomainControllerName, uname_utf16, 23, &user_info)) != NERR_Success) {
debug("NetUserGetInfo() with domainController: %ls failed with error: %d \n", pdc->DomainControllerName, status);
debug3("NetUserGetInfo() with domainController: %ls failed with error: %d \n", pdc->DomainControllerName, status);
errno = ENOENT;
goto done;
}
}
if (ConvertSidToStringSidW(((LPUSER_INFO_23)user_info)->usri23_user_sid, &user_sid_local) == FALSE) {
debug("NetUserGetInfo() Succeded but ConvertSidToStringSidW() failed with error: %d\n", GetLastError());
debug3("NetUserGetInfo() Succeded but ConvertSidToStringSidW() failed with error: %d\n", GetLastError());
errno = ENOENT;
goto done;
}

View File

@ -32,6 +32,7 @@
#include "w32fd.h"
#include "signal_internal.h"
#include "inc\signal.h"
#include "debug.h"
#undef signal
#undef raise
@ -56,28 +57,28 @@ extern struct _children children;
static VOID CALLBACK
sigint_APCProc(_In_ ULONG_PTR dwParam)
{
debug3("SIGINT APCProc()");
debug5("SIGINT APCProc()");
sigaddset(&pending_signals, W32_SIGINT);
}
static VOID CALLBACK
sigterm_APCProc(_In_ ULONG_PTR dwParam)
{
debug3("SIGTERM APCProc()");
debug5("SIGTERM APCProc()");
sigaddset(&pending_signals, W32_SIGTERM);
}
static VOID CALLBACK
sigtstp_APCProc(_In_ ULONG_PTR dwParam)
{
debug3("SIGTSTP APCProc()");
debug5("SIGTSTP APCProc()");
sigaddset(&pending_signals, W32_SIGTSTP);
}
BOOL WINAPI
native_sig_handler(DWORD dwCtrlType)
{
debug("Native Ctrl+C handler, CtrlType %d", dwCtrlType);
debug3("Native Ctrl+C handler, CtrlType %d", dwCtrlType);
switch (dwCtrlType) {
case CTRL_C_EVENT:
QueueUserAPC(sigint_APCProc, main_thread, (ULONG_PTR)NULL);
@ -100,7 +101,7 @@ native_sig_handler(DWORD dwCtrlType)
static VOID CALLBACK
sigwinch_APCProc(_In_ ULONG_PTR dwParam)
{
debug3("SIGTERM APCProc()");
debug5("SIGTERM APCProc()");
sigaddset(&pending_signals, W32_SIGWINCH);
}
@ -128,7 +129,7 @@ sighandler_t
w32_signal(int signum, sighandler_t handler)
{
sighandler_t prev;
debug2("signal() sig:%d, handler:%p", signum, handler);
debug4("signal() sig:%d, handler:%p", signum, handler);
if (signum >= W32_SIGMAX) {
errno = EINVAL;
return W32_SIG_ERR;
@ -144,7 +145,7 @@ w32_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
{
/* this is only used by sshd to block SIGCHLD while doing waitpid() */
/* our implementation of waidpid() is never interrupted, so no need to implement this for now*/
debug3("sigprocmask() how:%d");
debug5("sigprocmask() how:%d");
return 0;
}
@ -153,7 +154,7 @@ w32_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
int
w32_raise(int sig)
{
debug("raise sig:%d", sig);
debug3("raise sig:%d", sig);
if (sig == W32_SIGSEGV)
return raise(SIGSEGV); /* raise native exception handler*/
@ -191,7 +192,7 @@ sw_process_pending_signals()
sigset_t pending_tmp = pending_signals;
BOOL sig_int = FALSE; /* has any signal actually interrupted */
debug3("process_signals()");
debug5("process_signals()");
int i, exp[] = { W32_SIGCHLD , W32_SIGINT , W32_SIGALRM, W32_SIGTERM, W32_SIGTSTP, W32_SIGWINCH };
/* check for expected signals*/
@ -199,7 +200,7 @@ sw_process_pending_signals()
sigdelset(&pending_tmp, exp[i]);
if (pending_tmp) {
/* unexpected signals queued up */
debug("process_signals() - ERROR unexpected signals in queue: %d", pending_tmp);
debug3("process_signals() - ERROR unexpected signals in queue: %d", pending_tmp);
errno = ENOTSUP;
DebugBreak();
return -1;
@ -228,7 +229,7 @@ sw_process_pending_signals()
DebugBreak();
if (sig_int) {
debug("process_queued_signals: WARNING - A signal has interrupted and was processed");
debug3("process_queued_signals: WARNING - A signal has interrupted and was processed");
errno = EINTR;
return -1;
}
@ -257,7 +258,7 @@ wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds)
num_all_events = num_events + live_children;
if (num_all_events > MAXIMUM_WAIT_OBJECTS) {
debug("wait() - ERROR max events reached");
debug3("wait() - ERROR max events reached");
errno = ENOTSUP;
return -1;
}
@ -265,7 +266,7 @@ wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds)
memcpy(all_events, children.handles, live_children * sizeof(HANDLE));
memcpy(all_events + live_children, events, num_events * sizeof(HANDLE));
debug3("wait() on %d events and %d children", num_events, live_children);
debug5("wait() on %d events and %d children", num_events, live_children);
/* TODO - implement signal catching and handling */
if (num_all_events) {
DWORD ret = WaitForMultipleObjectsEx(num_all_events, all_events, FALSE, milli_seconds, TRUE);
@ -284,7 +285,7 @@ wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds)
return 0;
} else { /* some other error*/
errno = EOTHER;
debug("ERROR: unxpected wait end: %d", ret);
debug3("ERROR: unxpected wait end: %d", ret);
return -1;
}
} else {
@ -296,7 +297,7 @@ wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds)
return 0;
} else { /* some other error */
errno = EOTHER;
debug("ERROR: unxpected SleepEx error: %d", ret);
debug3("ERROR: unxpected SleepEx error: %d", ret);
return -1;
}
}

View File

@ -30,6 +30,7 @@
#include "signal_internal.h"
#include "inc\signal.h"
#include "debug.h"
struct _timer_info timer_info;
extern sigset_t pending_signals;
@ -49,7 +50,7 @@ w32_alarm(unsigned int sec)
ULONGLONG sec_passed;
int ret = 0;
debug3("alarm() %d secs", sec);
debug5("alarm() %d secs", sec);
errno = 0;
/* cancel any live timer if seconds is 0*/
if (sec == 0) {
@ -63,7 +64,7 @@ w32_alarm(unsigned int sec)
due.QuadPart *= sec;
/* this call resets the timer if it is already active */
if (!SetWaitableTimer(timer_info.timer, &due, 0, sigalrm_APC, NULL, FALSE)) {
debug("alram() - ERROR SetWaitableTimer() %d", GetLastError());
debug3("alram() - ERROR SetWaitableTimer() %d", GetLastError());
return 0;;
}

View File

@ -30,6 +30,7 @@
#include "signal_internal.h"
#include "inc\sys\wait.h"
#include "debug.h"
struct _children children;
@ -38,7 +39,7 @@ register_child(HANDLE child, DWORD pid)
{
DWORD first_zombie_index;
debug("Register child %p pid %d, %d zombies of %d", child, pid,
debug3("Register child %p pid %d, %d zombies of %d", child, pid,
children.num_zombies, children.num_children);
if (children.num_children == MAX_CHILDREN) {
errno = ENOMEM;
@ -65,7 +66,7 @@ int
sw_remove_child_at_index(DWORD index)
{
DWORD last_non_zombie;
debug("Unregister child at index %d, %d zombies of %d", index,
debug3("Unregister child at index %d, %d zombies of %d", index,
children.num_zombies, children.num_children);
if ((index >= children.num_children) || (children.num_children == 0)) {
@ -103,7 +104,7 @@ sw_child_to_zombie(DWORD index)
DWORD last_non_zombie, zombie_pid;
HANDLE zombie_handle;
debug("zombie'ing child at index %d, %d zombies of %d", index,
debug3("zombie'ing child at index %d, %d zombies of %d", index,
children.num_zombies, children.num_children);
if (index >= children.num_children) {
@ -152,7 +153,7 @@ waitpid(int pid, int *status, int options)
DWORD index, ret, ret_id, exit_code, timeout = 0;
HANDLE process = NULL;
debug3("waitpid - pid:%d, options:%d", pid, options);
debug5("waitpid - pid:%d, options:%d", pid, options);
if (options & (~WNOHANG)) {
errno = ENOTSUP;
DebugBreak();

View File

@ -36,6 +36,7 @@
#include <stddef.h>
#include "w32fd.h"
#include "inc\utf.h"
#include "debug.h"
#define INTERNAL_SEND_BUFFER_SIZE 70*1024 //70KB
#define INTERNAL_RECV_BUFFER_SIZE 70*1024 //70KB
@ -103,7 +104,7 @@ int
socketio_acceptEx(struct w32_io* pio)
{
struct acceptEx_context *context;
debug3("acceptEx - io:%p", pio);
debug5("acceptEx - io:%p", pio);
context = (struct acceptEx_context *)pio->internal.context;
ResetEvent(pio->read_overlapped.hEvent);
@ -111,7 +112,7 @@ socketio_acceptEx(struct w32_io* pio)
context->accept_socket = socket(AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
if (context->accept_socket == INVALID_SOCKET) {
errno = errno_from_WSALastError();
debug("acceptEx - socket() ERROR:%d, io:%p", errno, pio);
debug3("acceptEx - socket() ERROR:%d, io:%p", errno, pio);
return -1;
}
@ -130,7 +131,7 @@ socketio_acceptEx(struct w32_io* pio)
/* if overlapped io is in progress, we are good */
if (WSAGetLastError() != ERROR_IO_PENDING) {
errno = errno_from_WSALastError();
debug("acceptEx - AcceptEx() ERROR:%d, io:%p", errno, pio);
debug3("acceptEx - AcceptEx() ERROR:%d, io:%p", errno, pio);
return -1;
}
}
@ -147,7 +148,7 @@ CALLBACK WSARecvCompletionRoutine(IN DWORD dwError,
{
struct w32_io* pio =
(struct w32_io*)((char*)lpOverlapped - offsetof(struct w32_io, read_overlapped));
debug2("WSARecvCompletionCB - io:%p, pending_state:%d, flags:%d, error:%d, received:%d",
debug4("WSARecvCompletionCB - io:%p, pending_state:%d, flags:%d, error:%d, received:%d",
pio, pio->read_details.pending, dwFlags, dwError, cbTransferred);
if (!dwError && !cbTransferred)
dwError = ERROR_GRACEFUL_DISCONNECT;
@ -166,7 +167,7 @@ socketio_WSARecv(struct w32_io* pio, BOOL* completed)
WSABUF wsabuf;
DWORD recv_flags = 0;
debug3("WSARecv - pio: %p", pio);
debug5("WSARecv - pio: %p", pio);
if (completed)
*completed = FALSE;
@ -176,7 +177,7 @@ socketio_WSARecv(struct w32_io* pio, BOOL* completed)
wsabuf.buf = malloc(wsabuf.len);
if (!wsabuf.buf) {
errno = ENOMEM;
debug("WSARecv - ERROR:%d, io:%p", errno, pio);
debug3("WSARecv - ERROR:%d, io:%p", errno, pio);
return -1;
}
@ -189,17 +190,17 @@ socketio_WSARecv(struct w32_io* pio, BOOL* completed)
if (ret == 0) {
pio->read_details.pending = TRUE;
/* receive has completed but APC is pending to be scheduled */
debug2("WSARecv - WSARecv() returned 0, io:%p", pio);
debug4("WSARecv - WSARecv() returned 0, io:%p", pio);
if (completed)
*completed = TRUE;
} else { /* (ret == SOCKET_ERROR) */
if (WSAGetLastError() == WSA_IO_PENDING) {
/* io is initiated and pending */
debug2("WSARecv - reported IO pending");
debug4("WSARecv - reported IO pending");
pio->read_details.pending = TRUE;
} else {
errno = errno_from_WSALastError();
debug("WSARecv - WSARecv() ERROR: io:%p %d", pio, errno);
debug3("WSARecv - WSARecv() ERROR: io:%p %d", pio, errno);
return -1;
}
}
@ -214,7 +215,7 @@ socketio_socket(int domain, int type, int protocol)
struct w32_io *pio = (struct w32_io*)malloc(sizeof(struct w32_io));
if (!pio) {
errno = ENOMEM;
debug("socket - ERROR:%d, io:%p", errno, pio);
debug3("socket - ERROR:%d, io:%p", errno, pio);
return NULL;
}
@ -223,7 +224,7 @@ socketio_socket(int domain, int type, int protocol)
if (pio->sock == INVALID_SOCKET) {
errno = errno_from_WSALastError();
free(pio);
debug("socket - socket() ERROR:%d, io:%p", errno, pio);
debug3("socket - socket() ERROR:%d, io:%p", errno, pio);
return NULL;
}
@ -235,7 +236,7 @@ socketio_socket(int domain, int type, int protocol)
int ret = (expr); \
if (ret == SOCKET_ERROR) { \
errno = errno_from_WSALastError(); \
debug("%s - ERROR:%d", __FUNCTION__, errno); \
debug3("%s - ERROR:%d", __FUNCTION__, errno); \
} \
return ret; \
} while (0)
@ -248,7 +249,7 @@ socketio_setsockopt(struct w32_io* pio, int level, int optname, const char* optv
(optname == TCP_NODELAY) || (optname == IPV6_V6ONLY))
SET_ERRNO_ON_ERROR(setsockopt(pio->sock, level, optname, optval, optlen));
else {
debug("setsockop - ERROR: unsupported optname:%d io:%p", optname, pio);
debug3("setsockop - ERROR: unsupported optname:%d io:%p", optname, pio);
errno = ENOTSUP;
return -1;
}
@ -283,7 +284,7 @@ socketio_listen(struct w32_io* pio, int backlog)
if (SOCKET_ERROR == listen(pio->sock, backlog)) {
errno = errno_from_WSALastError();
debug("listen - listen() ERROR:%d io:%p", errno, pio);
debug3("listen - listen() ERROR:%d io:%p", errno, pio);
return -1;
}
@ -296,7 +297,7 @@ socketio_listen(struct w32_io* pio, int backlog)
context = (struct acceptEx_context*)malloc(sizeof(struct acceptEx_context));
if (context == NULL) {
errno = ENOMEM;
debug("listen - ERROR:%d, io:%p", errno, pio);
debug3("listen - ERROR:%d, io:%p", errno, pio);
return -1;
}
memset(context, 0, sizeof(struct acceptEx_context));
@ -307,7 +308,7 @@ socketio_listen(struct w32_io* pio, int backlog)
&dwBytes, NULL, NULL)) {
free(context);
errno = errno_from_WSALastError();
debug("listen - Ioctl1 ERROR:%d, io:%p", errno, pio);
debug3("listen - Ioctl1 ERROR:%d, io:%p", errno, pio);
return -1;
}
@ -318,7 +319,7 @@ socketio_listen(struct w32_io* pio, int backlog)
&dwBytes, NULL, NULL)) {
free(context);
errno = errno_from_WSALastError();
debug("listen - Ioctl2 ERROR:%d, io:%p", errno, pio);
debug3("listen - Ioctl2 ERROR:%d, io:%p", errno, pio);
return -1;
}
@ -326,7 +327,7 @@ socketio_listen(struct w32_io* pio, int backlog)
if ((pio->read_overlapped.hEvent) == NULL) {
free(context);
errno = ENOMEM;
debug("listen - CreateEvent() ERROR:%d, io:%p", errno, pio);
debug3("listen - CreateEvent() ERROR:%d, io:%p", errno, pio);
return -1;
}
@ -350,16 +351,16 @@ int
socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags)
{
BOOL completed = FALSE;
debug3("recv - io:%p", pio);
debug5("recv - io:%p", pio);
if ((buf == NULL) || (len == 0)) {
errno = EINVAL;
debug("recv - ERROR: invalid arguments, buf:%p, len:%d, io:%p", buf, len, pio);
debug3("recv - ERROR: invalid arguments, buf:%p, len:%d, io:%p", buf, len, pio);
return -1;
}
if (flags != 0) {
errno = ENOTSUP;
debug("recv - ERROR: flags are not currently supported, io:%p", pio);
debug3("recv - ERROR: flags are not currently supported, io:%p", pio);
return -1;
}
@ -368,14 +369,14 @@ socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags)
if (pio->read_details.pending) {
/* if recv is now in blocking mode, wait for data to be available */
if (w32_io_is_blocking(pio)) {
debug2("recv - io is pending, call is blocking, io:%p", pio);
debug4("recv - io is pending, call is blocking, io:%p", pio);
while (socketio_is_io_available(pio, TRUE) == FALSE) {
if (0 != wait_for_any_event(NULL, 0, INFINITE))
return -1;
}
} else {
errno = EAGAIN;
debug2("recv - io is already pending, io:%p", pio);
debug4("recv - io is already pending, io:%p", pio);
return -1;
}
}
@ -387,7 +388,7 @@ socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags)
num_bytes_copied);
pio->read_details.remaining -= num_bytes_copied;
pio->read_details.completed += num_bytes_copied;
debug2("recv - returning %d bytes from prior completed IO, remaining:%d, io:%p",
debug4("recv - returning %d bytes from prior completed IO, remaining:%d, io:%p",
num_bytes_copied, pio->read_details.remaining, pio);
return num_bytes_copied;
}
@ -395,12 +396,12 @@ socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags)
/* if there was an error on async call, return */
if (pio->read_details.error) {
if (pio->read_details.error == ERROR_GRACEFUL_DISCONNECT) {
debug2("recv - connection closed, io:%p", pio);
debug4("recv - connection closed, io:%p", pio);
/* connection is closed */
return 0;
} else {
errno = errno_from_WSAError(pio->read_details.error);
debug("recv - from CB ERROR:%d, io:%p", pio->read_details.error, pio);
debug3("recv - from CB ERROR:%d, io:%p", pio->read_details.error, pio);
pio->read_details.error = 0;
return -1;
}
@ -411,19 +412,19 @@ socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags)
if (completed) {
/* Let APC be scheduled */
debug2("recv - Letting APC to execute, io:%p", pio);
debug4("recv - Letting APC to execute, io:%p", pio);
SleepEx(0, TRUE);
if (pio->read_details.pending) {
/* this shouldn't be happening */
errno = EOTHER;
debug("recv - ERROR: Unexpected IO state, io:%p", pio);
debug3("recv - ERROR: Unexpected IO state, io:%p", pio);
return -1;
}
}
if (w32_io_is_blocking(pio)) {
/* wait until io is done */
debug3("recv - socket in blocking mode, io:%p", pio);
debug5("recv - socket in blocking mode, io:%p", pio);
while (socketio_is_io_available(pio, TRUE) == FALSE) {
if (0 != wait_for_any_event(NULL, 0, INFINITE))
return -1;
@ -431,7 +432,7 @@ socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags)
} else {
if (socketio_is_io_available(pio, TRUE) == FALSE) {
errno = EAGAIN;
debug2("recv - IO is pending, io:%p", pio);
debug4("recv - IO is pending, io:%p", pio);
return -1;
}
}
@ -443,12 +444,12 @@ socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags)
if (pio->read_details.error) {
if (pio->read_details.error == ERROR_GRACEFUL_DISCONNECT) {
/* connection is closed */
debug2("recv - connection closed(2), io:%p", pio);
debug4("recv - connection closed(2), io:%p", pio);
return 0;
} else {
errno = errno_from_WSAError(pio->read_details.error);
pio->read_details.error = 0;
debug("recv - from CB(2) ERROR:%d, io:%p", errno, pio);
debug3("recv - from CB(2) ERROR:%d, io:%p", errno, pio);
return -1;
}
}
@ -458,13 +459,13 @@ socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags)
memcpy(buf, pio->read_details.buf, num_bytes_copied);
pio->read_details.remaining -= num_bytes_copied;
pio->read_details.completed = num_bytes_copied;
debug2("recv - (2) returning %d bytes from completed IO, remaining:%d, io:%p",
debug4("recv - (2) returning %d bytes from completed IO, remaining:%d, io:%p",
num_bytes_copied, pio->read_details.remaining, pio);
return num_bytes_copied;
} else {
/* this should not happen */
errno = EOTHER;
debug("recv - (2) ERROR:Unexpected IO state, io:%p", pio);
debug3("recv - (2) ERROR:Unexpected IO state, io:%p", pio);
return -1;
}
}
@ -476,13 +477,13 @@ CALLBACK WSASendCompletionRoutine(IN DWORD dwError,
IN DWORD dwFlags)
{
struct w32_io* pio = (struct w32_io*)((char*)lpOverlapped - offsetof(struct w32_io, write_overlapped));
debug2("WSASendCB - io:%p, pending_state:%d, error:%d, sent:%d of remaining:%d",
debug4("WSASendCB - io:%p, pending_state:%d, error:%d, sent:%d of remaining:%d",
pio, pio->write_details.pending, dwError, cbTransferred,
pio->write_details.remaining);
pio->write_details.error = dwError;
/* TODO - assert that remaining == cbTransferred */
if ((dwError == 0) && (pio->write_details.remaining != cbTransferred)) {
debug("WSASendCB - ERROR: broken assumption, io:%p, sent:%d, remaining:%d", pio,
debug3("WSASendCB - ERROR: broken assumption, io:%p, sent:%d, remaining:%d", pio,
cbTransferred, pio->write_details.remaining);
DebugBreak();
}
@ -497,16 +498,16 @@ socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags)
int ret = 0;
WSABUF wsabuf;
debug2("send - io:%p", pio);
debug4("send - io:%p", pio);
if ((buf == NULL) || (len == 0)) {
errno = EINVAL;
debug("send - ERROR invalid arguments, buf:%p, len:%d, io:%p", buf, len, pio);
debug3("send - ERROR invalid arguments, buf:%p, len:%d, io:%p", buf, len, pio);
return -1;
}
if (flags != 0) {
errno = ENOTSUP;
debug("send - ERROR: flags are not currently supported, io:%p", pio);
debug3("send - ERROR: flags are not currently supported, io:%p", pio);
return -1;
}
@ -514,20 +515,20 @@ socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags)
/* if io is already pending */
if (pio->write_details.pending) {
if (w32_io_is_blocking(pio)) {
debug2("send - io is pending, call is blocking, io:%p", pio);
debug4("send - io is pending, call is blocking, io:%p", pio);
while (pio->write_details.pending)
if (wait_for_any_event(NULL, 0, INFINITE) == -1)
return -1;
} else {
errno = EAGAIN;
debug2("send - IO currently pending, EAGAIN, io:%p", pio);
debug4("send - IO currently pending, EAGAIN, io:%p", pio);
return -1;
}
}
if (pio->write_details.error) {
errno = errno_from_WSAError(pio->write_details.error);
debug("ERROR:%d, io:%p", errno, pio);
debug3("ERROR:%d, io:%p", errno, pio);
return -1;
}
@ -537,7 +538,7 @@ socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags)
wsabuf.buf = malloc(wsabuf.len);
if (!wsabuf.buf) {
errno = ENOMEM;
debug("send - ERROR:%d, io:%p", errno, pio);
debug3("send - ERROR:%d, io:%p", errno, pio);
return -1;
}
@ -554,13 +555,13 @@ socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags)
if (ret == 0) {
/* send has completed and APC is scheduled, let it run */
debug2("send - WSASend() returned 0, APC scheduled io:%p", pio);
debug4("send - WSASend() returned 0, APC scheduled io:%p", pio);
pio->write_details.pending = TRUE;
pio->write_details.remaining = wsabuf.len;
SleepEx(0, TRUE);
if ((pio->write_details.pending) || (pio->write_details.remaining != 0)) {
errno = EOTHER;
debug("send - ERROR: Unexpected IO state, io:%p", pio);
debug3("send - ERROR: Unexpected IO state, io:%p", pio);
return -1;
}
@ -569,12 +570,12 @@ socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags)
} else {
if (WSAGetLastError() == WSA_IO_PENDING) {
/* io is initiated and pending */
debug2("send - WSASend reported IO pending, io:%p", pio);
debug4("send - WSASend reported IO pending, io:%p", pio);
pio->write_details.pending = TRUE;
pio->write_details.remaining = wsabuf.len;
if (w32_io_is_blocking(pio)) {
/* wait until io is done */
debug3("send - waiting as socket is in blocking mode, io:%p", pio);
debug5("send - waiting as socket is in blocking mode, io:%p", pio);
while (pio->write_details.pending)
if (wait_for_any_event(NULL, 0, INFINITE) == -1) {
/* if interrupted but send has completed, we are good*/
@ -584,11 +585,11 @@ socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags)
}
}
debug3("send - returning %d, io:%p", wsabuf.len, pio);
debug5("send - returning %d, io:%p", wsabuf.len, pio);
return wsabuf.len;
} else {
errno = errno_from_WSALastError();
debug("send - WSASend() ERROR:%d, io:%p", errno, pio);
debug3("send - WSASend() ERROR:%d, io:%p", errno, pio);
return -1;
}
}
@ -605,13 +606,13 @@ socketio_shutdown(struct w32_io* pio, int how)
int
socketio_close(struct w32_io* pio)
{
debug2("close - io:%p", pio);
debug4("close - io:%p", pio);
closesocket(pio->sock);
/* wait for pending io to abort */
SleepEx(0, TRUE);
if (((pio->internal.state == SOCK_CONNECTED) || (pio->internal.state == SOCK_ACCEPTED)) &&
(pio->read_details.pending || pio->write_details.pending)) {
debug2("close - IO is still pending on closed socket. read:%d, write:%d, io:%p",
debug4("close - IO is still pending on closed socket. read:%d, write:%d, io:%p",
pio->read_details.pending, pio->write_details.pending, pio);
DebugBreak();
}
@ -649,7 +650,7 @@ socketio_accept(struct w32_io* pio, struct sockaddr* addr, int* addrlen)
struct sockaddr *local_address, *remote_address;
int local_address_len, remote_address_len;
debug3("accept - io:%p", pio);
debug5("accept - io:%p", pio);
/* start io if not already started */
if (pio->read_details.pending == FALSE) {
if (socketio_acceptEx(pio) != 0)
@ -666,7 +667,7 @@ socketio_accept(struct w32_io* pio, struct sockaddr* addr, int* addrlen)
/* if i/o is not ready */
if (FALSE == socketio_is_io_available(pio, TRUE)) {
errno = EAGAIN;
debug2("accept is pending, io:%p", pio);
debug4("accept is pending, io:%p", pio);
return NULL;
}
}
@ -677,21 +678,21 @@ socketio_accept(struct w32_io* pio, struct sockaddr* addr, int* addrlen)
if (pio->read_details.error) {
errno = errno_from_WSAError(pio->read_details.error);
debug("accept - ERROR: async io completed with error: %d, io:%p", errno, pio);
debug3("accept - ERROR: async io completed with error: %d, io:%p", errno, pio);
goto on_error;
}
if (0 != setsockopt(context->accept_socket, SOL_SOCKET,
SO_UPDATE_ACCEPT_CONTEXT, (char*)&pio->sock, sizeof(pio->sock))) {
errno = errno_from_WSALastError();
debug("accept - ERROR: setsockopt failed:%d, io:%p", errno, pio);
debug3("accept - ERROR: setsockopt failed:%d, io:%p", errno, pio);
goto on_error;
}
accept_io = (struct w32_io*)malloc(sizeof(struct w32_io));
if (!accept_io) {
errno = ENOMEM;
debug("accept - ERROR:%d, io:%p", errno, pio);
debug3("accept - ERROR:%d, io:%p", errno, pio);
goto on_error;
}
memset(accept_io, 0, sizeof(struct w32_io));
@ -699,7 +700,7 @@ socketio_accept(struct w32_io* pio, struct sockaddr* addr, int* addrlen)
accept_io->sock = context->accept_socket;
accept_io->internal.state = SOCK_ACCEPTED;
context->accept_socket = INVALID_SOCKET;
debug2("accept io:%p", accept_io);
debug4("accept io:%p", accept_io);
if ((addr != NULL) && (addrlen != NULL)) {
context->lpfnGuidGetAcceptExSockaddrs(context->lpOutputBuf, 0,
@ -735,7 +736,7 @@ socketio_connectex(struct w32_io* pio, const struct sockaddr* name, int namelen)
GUID connectex_guid = WSAID_CONNECTEX;
LPFN_CONNECTEX ConnectEx;
debug3("connectex - io:%p", pio);
debug5("connectex - io:%p", pio);
if (name->sa_family == AF_INET6) {
ZeroMemory(&tmp_addr6, sizeof(tmp_addr6));
tmp_addr6.sin6_family = AF_INET6;
@ -750,13 +751,13 @@ socketio_connectex(struct w32_io* pio, const struct sockaddr* name, int namelen)
tmp_addr_len = sizeof(tmp_addr4);
} else {
errno = ENOTSUP;
debug("connectex - ERROR: unsuppored address family:%d, io:%p", name->sa_family, pio);
debug3("connectex - ERROR: unsuppored address family:%d, io:%p", name->sa_family, pio);
return -1;
}
if (SOCKET_ERROR == bind(pio->sock, tmp_addr, (int)tmp_addr_len)) {
errno = errno_from_WSALastError();
debug("connectex - ERROR: bind failed :%d, io:%p", WSAGetLastError(), pio);
debug3("connectex - ERROR: bind failed :%d, io:%p", WSAGetLastError(), pio);
return -1;
}
@ -765,14 +766,14 @@ socketio_connectex(struct w32_io* pio, const struct sockaddr* name, int namelen)
&ConnectEx, sizeof(ConnectEx),
&tmp_bytes, NULL, NULL)) {
errno = errno_from_WSALastError();
debug("connectex - ioctl ERROR:%d, io:%p", WSAGetLastError(), pio);
debug3("connectex - ioctl ERROR:%d, io:%p", WSAGetLastError(), pio);
return -1;
}
if ((!pio->write_overlapped.hEvent)
&& ((pio->write_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL)) {
errno = ENOMEM;
debug("connectex - ERROR CreateEvent failed:%d, io:%p", errno, pio);
debug3("connectex - ERROR CreateEvent failed:%d, io:%p", errno, pio);
return -1;
}
@ -786,7 +787,7 @@ socketio_connectex(struct w32_io* pio, const struct sockaddr* name, int namelen)
CloseHandle(pio->write_overlapped.hEvent);
pio->write_overlapped.hEvent = 0;
errno = errno_from_WSALastError();
debug("connectex - ERROR ConnectEx() :%d, io:%p", errno, pio);
debug3("connectex - ERROR ConnectEx() :%d, io:%p", errno, pio);
return -1;
}
}
@ -801,7 +802,7 @@ int
socketio_connect(struct w32_io* pio, const struct sockaddr* name, int namelen)
{
debug3("connect - io:%p", pio);
debug5("connect - io:%p", pio);
if (pio->write_details.pending == FALSE) {
if (-1 == socketio_connectex(pio, name, namelen))
return -1;
@ -817,7 +818,7 @@ socketio_connect(struct w32_io* pio, const struct sockaddr* name, int namelen)
/* if i/o is not ready */
if (FALSE == socketio_is_io_available(pio, TRUE)) {
errno = EINPROGRESS;
debug2("connect - in progress, io:%p", pio);
debug4("connect - in progress, io:%p", pio);
return -1;
}
}
@ -828,16 +829,16 @@ socketio_connect(struct w32_io* pio, const struct sockaddr* name, int namelen)
int
socketio_finish_connect(struct w32_io* pio)
{
debug3("finish_connect, io:%p", pio);
debug5("finish_connect, io:%p", pio);
if (pio->write_details.error) {
errno = errno_from_WSAError(pio->write_details.error);
debug("finish_connect - ERROR: async io completed with error: %d, io:%p", errno, pio);
debug3("finish_connect - ERROR: async io completed with error: %d, io:%p", errno, pio);
return -1;
}
if (0 != setsockopt(pio->sock, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0)) {
errno = errno_from_WSALastError();
debug("finish_connect - ERROR: setsockopt failed:%d, io:%p", errno, pio);
debug3("finish_connect - ERROR: setsockopt failed:%d, io:%p", errno, pio);
return -1;
}
@ -896,7 +897,7 @@ void
socketio_on_select(struct w32_io* pio, BOOL rd)
{
enum w32_io_sock_state sock_state = pio->internal.state;
debug2("on_select - io:%p type:%d rd:%d", pio, pio->type, rd);
debug4("on_select - io:%p type:%d rd:%d", pio, pio->type, rd);
/* nothing to do for writes (that includes connect) */
if (!rd)

View File

@ -63,6 +63,12 @@ mm_is_monitor(void) {
return 0;
}
int
mm_user_key_allowed(struct passwd *pw, Key *k, int i)
{
return 0;
}
int kexgex_server(struct ssh * sh) {
return -1;
}

View File

@ -39,6 +39,7 @@
#include "w32fd.h"
#include "tncon.h"
#include "inc\utf.h"
#include "debug.h"
#include "tnnet.h"
#define TERM_IO_BUF_SIZE 2048
@ -57,7 +58,7 @@ static VOID CALLBACK
ReadAPCProc(_In_ ULONG_PTR dwParam)
{
struct w32_io* pio = (struct w32_io*)dwParam;
debug3("TermRead CB - io:%p, bytes: %d, pending: %d, error: %d", pio, read_status.transferred,
debug5("TermRead CB - io:%p, bytes: %d, pending: %d, error: %d", pio, read_status.transferred,
pio->read_details.pending, read_status.error);
pio->read_details.error = read_status.error;
pio->read_details.remaining = read_status.transferred;
@ -75,7 +76,7 @@ ReadConsoleThread(_In_ LPVOID lpParameter)
int nBytesReturned = 0;
struct w32_io* pio = (struct w32_io*)lpParameter;
debug3("TermRead thread, io:%p", pio);
debug5("TermRead thread, io:%p", pio);
memset(&read_status, 0, sizeof(read_status));
while (nBytesReturned == 0) {
nBytesReturned = ReadConsoleForTermEmul(WINHANDLE(pio),
@ -83,7 +84,7 @@ ReadConsoleThread(_In_ LPVOID lpParameter)
}
read_status.transferred = nBytesReturned;
if (0 == QueueUserAPC(ReadAPCProc, main_thread, (ULONG_PTR)pio)) {
debug("TermRead thread - ERROR QueueUserAPC failed %d, io:%p", GetLastError(), pio);
debug3("TermRead thread - ERROR QueueUserAPC failed %d, io:%p", GetLastError(), pio);
pio->read_details.pending = FALSE;
pio->read_details.error = GetLastError();
DebugBreak();
@ -98,7 +99,7 @@ termio_initiate_read(struct w32_io* pio)
{
HANDLE read_thread;
debug3("TermRead initiate io:%p", pio);
debug5("TermRead initiate io:%p", pio);
if (pio->read_details.buf_size == 0) {
pio->read_details.buf = malloc(TERM_IO_BUF_SIZE);
if (pio->read_details.buf == NULL) {
@ -111,7 +112,7 @@ termio_initiate_read(struct w32_io* pio)
read_thread = CreateThread(NULL, 0, ReadConsoleThread, pio, 0, NULL);
if (read_thread == NULL) {
errno = errno_from_Win32Error(GetLastError());
debug("TermRead initiate - ERROR CreateThread %d, io:%p", GetLastError(), pio);
debug3("TermRead initiate - ERROR CreateThread %d, io:%p", GetLastError(), pio);
return -1;
}
@ -125,7 +126,7 @@ static VOID CALLBACK
WriteAPCProc(_In_ ULONG_PTR dwParam)
{
struct w32_io* pio = (struct w32_io*)dwParam;
debug3("TermWrite CB - io:%p, bytes: %d, pending: %d, error: %d", pio, write_status.transferred,
debug5("TermWrite CB - io:%p, bytes: %d, pending: %d, error: %d", pio, write_status.transferred,
pio->write_details.pending, write_status.error);
pio->write_details.error = write_status.error;
pio->write_details.remaining -= write_status.transferred;
@ -146,8 +147,8 @@ WriteThread(_In_ LPVOID lpParameter)
char *respbuf = NULL;
size_t resplen = 0;
DWORD dwSavedAttributes = ENABLE_PROCESSED_INPUT;
debug3("TermWrite thread, io:%p", pio);
debug5("TermWrite thread, io:%p", pio);
pio->write_details.buf[write_status.to_transfer] = '\0';
if (0 == in_raw_mode) {
@ -162,7 +163,7 @@ WriteThread(_In_ LPVOID lpParameter)
write_status.transferred = write_status.to_transfer;
if (0 == QueueUserAPC(WriteAPCProc, main_thread, (ULONG_PTR)pio)) {
debug("TermWrite thread - ERROR QueueUserAPC failed %d, io:%p", GetLastError(), pio);
debug3("TermWrite thread - ERROR QueueUserAPC failed %d, io:%p", GetLastError(), pio);
pio->write_details.pending = FALSE;
pio->write_details.error = GetLastError();
DebugBreak();
@ -176,13 +177,13 @@ int
termio_initiate_write(struct w32_io* pio, DWORD num_bytes)
{
HANDLE write_thread;
debug3("TermWrite initiate io:%p", pio);
debug5("TermWrite initiate io:%p", pio);
memset(&write_status, 0, sizeof(write_status));
write_status.to_transfer = num_bytes;
write_thread = CreateThread(NULL, 0, WriteThread, pio, 0, NULL);
if (write_thread == NULL) {
errno = errno_from_Win32Error(GetLastError());
debug("TermWrite initiate - ERROR CreateThread %d, io:%p", GetLastError(), pio);
debug3("TermWrite initiate - ERROR CreateThread %d, io:%p", GetLastError(), pio);
return -1;
}
@ -195,7 +196,7 @@ termio_initiate_write(struct w32_io* pio, DWORD num_bytes)
int
termio_close(struct w32_io* pio)
{
debug2("termio_close - pio:%p", pio);
debug4("termio_close - pio:%p", pio);
HANDLE h;
CancelIoEx(WINHANDLE(pio), NULL);
/* If io is pending, let write worker threads exit. The read thread is blocked so terminate it.*/

View File

@ -48,6 +48,7 @@
#include "Shlwapi.h"
#include <sys\utime.h>
#include "misc_internal.h"
#include "debug.h"
/* internal table that stores the fd to w32_io mapping*/
struct w32fd_table {
@ -99,7 +100,7 @@ fd_table_get_min_index()
min_index += 8;
if (min_index >= MAX_FDS) {
errno = EMFILE;
debug("ERROR: MAX_FDS limit reached");
debug3("ERROR: MAX_FDS limit reached");
return -1;
}
}
@ -180,11 +181,10 @@ w32_io_on_select(struct w32_io* pio, BOOL rd)
}
#define CHECK_FD(fd) do { \
debug3("%s fd:%d", __FUNCTION__, fd); \
errno = 0; \
if ((fd < 0) || (fd > MAX_FDS - 1) || fd_table.w32_ios[fd] == NULL) { \
errno = EBADF; \
debug("%s ERROR: bad fd: %d", __FUNCTION__, fd); \
debug3("%s ERROR: bad fd: %d", __FUNCTION__, fd); \
return -1; \
} \
} while (0)
@ -193,7 +193,7 @@ w32_io_on_select(struct w32_io* pio, BOOL rd)
errno = 0; \
if (pio->type != SOCK_FD) { \
errno = ENOTSOCK; \
debug("%s ERROR: not sock :%d", __FUNCTION__, pio->type); \
debug3("%s ERROR: not sock :%d", __FUNCTION__, pio->type); \
return -1; \
} \
} while (0)
@ -221,7 +221,7 @@ w32_socket(int domain, int type, int protocol)
}
fd_table_set(pio, min_index);
debug("socket:%d, socktype:%d, io:%p, fd:%d ", pio->sock, type, pio, min_index);
debug3("socket:%d, socktype:%d, io:%p, fd:%d ", pio->sock, type, pio, min_index);
return min_index;
}
@ -242,7 +242,7 @@ w32_accept(int fd, struct sockaddr* addr, int* addrlen)
pio->type = SOCK_FD;
fd_table_set(pio, min_index);
debug("socket:%d, io:%p, fd:%d ", pio->sock, pio, min_index);
debug3("socket:%d, io:%p, fd:%d ", pio->sock, pio, min_index);
return min_index;
}
@ -329,7 +329,7 @@ w32_send(int fd, const void *buf, size_t len, int flags)
int
w32_shutdown(int fd, int how)
{
debug2("shutdown - fd:%d how:%d", fd, how);
debug4("shutdown - fd:%d how:%d", fd, how);
CHECK_FD(fd);
CHECK_SOCK_IO(fd_table.w32_ios[fd]);
return socketio_shutdown(fd_table.w32_ios[fd], how);
@ -339,7 +339,7 @@ int
w32_socketpair(int domain, int type, int protocol, int sv[2])
{
errno = ENOTSUP;
debug("socketpair - ERROR not supported");
debug3("socketpair - ERROR not supported");
return -1;
}
@ -371,7 +371,7 @@ w32_pipe(int *pfds)
fd_table_set(pio[1], write_index);
pfds[0] = read_index;
pfds[1] = write_index;
debug("pipe - r-h:%d,io:%p,fd:%d w-h:%d,io:%p,fd:%d",
debug3("pipe - r-h:%d,io:%p,fd:%d w-h:%d,io:%p,fd:%d",
pio[0]->handle, pio[0], read_index, pio[1]->handle, pio[1], write_index);
return 0;
@ -393,8 +393,8 @@ w32_open(const char *pathname, int flags, ...)
pio->type = NONSOCK_FD;
fd_table_set(pio, min_index);
debug("open - handle:%p, io:%p, fd:%d", pio->handle, pio, min_index);
debug3("open - path:%s", pathname);
debug3("open - handle:%p, io:%p, fd:%d", pio->handle, pio, min_index);
debug5("open - path:%s", pathname);
return min_index;
}
@ -473,7 +473,7 @@ w32_fdopen(int fd, const char *mode)
errno = 0;
if ((fd < 0) || (fd > MAX_FDS - 1) || fd_table.w32_ios[fd] == NULL) {
errno = EBADF;
debug("fdopen - ERROR bad fd: %d", fd);
debug3("fdopen - ERROR bad fd: %d", fd);
return NULL;
}
return fileio_fdopen(fd_table.w32_ios[fd], mode);
@ -490,7 +490,7 @@ w32_close(int fd)
pio = fd_table.w32_ios[fd];
debug("close - io:%p, type:%d, fd:%d, table_index:%d", pio, pio->type, fd,
debug3("close - io:%p, type:%d, fd:%d, table_index:%d", pio, pio->type, fd,
pio->table_index);
fd_table_clear(pio->table_index);
@ -510,7 +510,7 @@ w32_io_process_fd_flags(struct w32_io* pio, int flags)
{
DWORD shi_flags;
if (flags & ~FD_CLOEXEC) {
debug("fcntl - ERROR unsupported flags %d, io:%p", flags, pio);
debug3("fcntl - ERROR unsupported flags %d, io:%p", flags, pio);
errno = ENOTSUP;
return -1;
}
@ -523,7 +523,7 @@ w32_io_process_fd_flags(struct w32_io* pio, int flags)
* UF_UNIX sockets that are not connected yet
*/
if (GetLastError() != ERROR_INVALID_HANDLE) {
debug("fcntl - SetHandleInformation failed %d, io:%p",
debug3("fcntl - SetHandleInformation failed %d, io:%p",
GetLastError(), pio);
errno = EOTHER;
return -1;
@ -559,7 +559,7 @@ w32_fcntl(int fd, int cmd, ... /* arg */)
break;
default:
errno = EINVAL;
debug("fcntl - ERROR not supported cmd:%d", cmd);
debug3("fcntl - ERROR not supported cmd:%d", cmd);
ret = -1;
break;
}
@ -589,20 +589,20 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
if (fds > MAX_FDS) {
errno = EINVAL;
debug("select - ERROR: invalid fds: %d", fds);
debug3("select - ERROR: invalid fds: %d", fds);
return -1;
}
if (!readfds && !writefds) {
errno = EINVAL;
debug("select - ERROR: null fd_sets");
debug3("select - ERROR: null fd_sets");
return -1;
}
/* TODO - see if this needs to be supported */
/* if (exceptfds) {
errno = EOPNOTSUPP;
debug("select - ERROR: exceptfds not supported");
debug3("select - ERROR: exceptfds not supported");
DebugBreak();
return -1;
} */
@ -626,11 +626,11 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
/* if none of input fds are set return error */
if (in_set_fds == 0) {
errno = EINVAL;
debug("select - ERROR: empty fd_sets");
debug3("select - ERROR: empty fd_sets");
return -1;
}
debug3("Total in fds:%d", in_set_fds);
debug5("Total in fds:%d", in_set_fds);
/*
* start async io on selected fds if needed and pick up any events
* that select needs to listen on
@ -641,7 +641,7 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
if ((fd_table.w32_ios[i]->type == SOCK_FD) &&
(fd_table.w32_ios[i]->internal.state == SOCK_LISTENING)) {
if (num_events == SELECT_EVENT_LIMIT) {
debug("select - ERROR: max #events breach");
debug3("select - ERROR: max #events breach");
errno = ENOMEM;
return -1;
}
@ -654,7 +654,7 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
if ((fd_table.w32_ios[i]->type == SOCK_FD) &&
(fd_table.w32_ios[i]->internal.state == SOCK_CONNECTING)) {
if (num_events == SELECT_EVENT_LIMIT) {
debug("select - ERROR: max #events reached for select");
debug3("select - ERROR: max #events reached for select");
errno = ENOMEM;
return -1;
}
@ -695,7 +695,7 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
if (timeout != NULL) {
if (timeout_ms < ticks_spent) {
debug("select - timing out");
debug3("select - timing out");
break;
}
time_rem = timeout_ms - (ticks_spent & 0xffffffff);
@ -725,7 +725,7 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
}
if (out_ready_fds == 0)
debug3("select - wait ended without any IO completion, looping again");
debug5("select - wait ended without any IO completion, looping again");
}
/* clear out fds that are not ready yet */
@ -754,7 +754,7 @@ w32_select(int fds, w32_fd_set* readfds, w32_fd_set* writefds, w32_fd_set* excep
FD_CLR(i, writefds);
}
debug3("select - returning %d", out_ready_fds);
debug5("select - returning %d", out_ready_fds);
return out_ready_fds;
}
@ -768,7 +768,7 @@ w32_dup(int oldfd)
CHECK_FD(oldfd);
if (oldfd > STDERR_FILENO) {
errno = EOPNOTSUPP;
debug("dup - ERROR: supports only std io, fd:%d", oldfd);
debug3("dup - ERROR: supports only std io, fd:%d", oldfd);
return -1;
}
@ -778,13 +778,13 @@ w32_dup(int oldfd)
src = GetStdHandle(fd_table.w32_ios[oldfd]->std_handle);
if (src == INVALID_HANDLE_VALUE) {
errno = EINVAL;
debug("dup - ERROR: unable to get underlying handle for std fd:%d", oldfd);
debug3("dup - ERROR: unable to get underlying handle for std fd:%d", oldfd);
return -1;
}
if (!DuplicateHandle(GetCurrentProcess(), src, GetCurrentProcess(), &target, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
errno = EOTHER;
debug("dup - ERROR: DuplicatedHandle() :%d", GetLastError());
debug3("dup - ERROR: DuplicatedHandle() :%d", GetLastError());
return -1;
}
@ -792,7 +792,7 @@ w32_dup(int oldfd)
if (pio == NULL) {
CloseHandle(target);
errno = ENOMEM;
debug("dup - ERROR: %d", errno);
debug3("dup - ERROR: %d", errno);
return -1;
}
@ -808,7 +808,7 @@ w32_dup2(int oldfd, int newfd)
{
CHECK_FD(oldfd);
errno = EOPNOTSUPP;
debug("dup2 - ERROR: not implemented yet");
debug3("dup2 - ERROR: not implemented yet");
return -1;
}

View File

@ -0,0 +1,58 @@
/*
* Windows version of sshpty* routines in sshpty.c
*/
#include <Windows.h>
#include "..\..\..\sshpty.h"
/*
* Windows versions of pty_*. Some of them are NO-OPs and should go
* away when pty logic is refactored and abstracted out
*
*/
int
pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
{
/*
* Simple console screen implementation in Win32 to give a
* Unix like pty for interactive sessions
*/
*ttyfd = 0;
*ptyfd = 0;
strlcpy(namebuf, "console", namebuflen);
return 1;
}
void
pty_release(const char *tty) {
/* NO-OP */
}
void
pty_make_controlling_tty(int *ttyfd, const char *tty) {
/* NO-OP */
}
void
pty_change_window_size(int ptyfd, u_int row, u_int col,
u_int xpixel, u_int ypixel) {
COORD coord;
coord.X = col;
coord.Y = 9999;
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
void
pty_setowner(struct passwd *pw, const char *tty) {
/* NO-OP */
}
void
disconnect_controlling_tty(void) {
/* NO-OP */
}

View File

@ -0,0 +1,40 @@
/*
* Windows version of sshtty* routines implemented in sshtty.c
*/
#include <Windows.h>
#include "..\..\..\sshpty.h"
static struct termios _saved_tio;
static int _in_raw_mode = 0;
/*
* TTY raw mode routines for Windows
*/
int ConEnterRawMode(DWORD OutputHandle, BOOL fSmartInit);
int ConExitRawMode(void);
struct termios term_settings;
/*
* TODO - clean this up for Windows, ConInit should return previous terminal
* settings that need to be stored in term_settings
*/
struct termios *
get_saved_tio(void) {
memset(&term_settings, 0, sizeof(term_settings));
return &term_settings;
}
void
leave_raw_mode(int quiet) {
ConExitRawMode();
}
void
enter_raw_mode(int quiet) {
ConEnterRawMode(STD_OUTPUT_HANDLE, TRUE);
}

View File

@ -53,21 +53,21 @@ int
ga_init(const char *user, gid_t base)
{
#ifdef WINDOWS
DWORD i = 0, j = 0;
LPLOCALGROUP_USERS_INFO_0 local_groups_info = NULL, tmp_groups_info;
wchar_t *user_utf16 = NULL, *full_name_utf16 = NULL, *udom_utf16 = NULL, *tmp;
char *group_utf8 = NULL;
DWORD i = 0, j = 0;
DWORD entries_read = 0, total_entries = 0, full_name_len = 0, index = 0;
NET_API_STATUS nStatus;
if (ngroups > 0)
ga_free();
user_utf16 = utf8_to_utf16(user);
if ((user_utf16 = utf8_to_utf16(user)) == NULL) {
errno = ENOMEM;
goto done;
}
full_name_len = wcslen(user_utf16) + 1;
if ((full_name_utf16 = malloc(full_name_len * sizeof(wchar_t))) == NULL) {
errno = ENOMEM;
@ -151,7 +151,6 @@ done:
free(groups_bygid);
#endif /* !WINDOWS */
return (ngroups = j);
}
/*

8
log.c
View File

@ -455,15 +455,7 @@ do_log(LogLevel level, const char *fmt, va_list args)
} else if (log_on_stderr) {
snprintf(msgbuf, sizeof msgbuf, "%.*s\r\n",
(int)sizeof msgbuf - 3, fmtbuf);
#ifdef WINDOWS
/*
* In Windows, write is implemented as part of POSIX compat layer
* that itself may "log" resulting in a infinite recursion loop
*/
_write(STDERR_FILENO, msgbuf, strlen(msgbuf));
#else /* !WINDOWS */
(void)write(log_stderr_fd, msgbuf, strlen(msgbuf));
#endif /* !WINDOWS */
} else {
#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata);

View File

@ -69,7 +69,7 @@ ssh_askpass(char *askpass, const char *msg)
#ifdef WINDOWS
/* spawd child for Windows */
fcntl(p[0], F_SETFD, FD_CLOEXEC);
pid = spawn_child(askpass, p[1], p[1], STDERR_FILENO, 0);
pid = spawn_child(askpass, NULL, p[1], p[1], STDERR_FILENO, 0);
if (pid < 0) {
#else /* !WINDOWS */
if ((pid = fork()) < 0) {
@ -125,71 +125,6 @@ ssh_askpass(char *askpass, const char *msg)
char *
read_passphrase(const char *prompt, int flags)
{
#ifdef WINDOWS
/* TODO - do flags apply on Windows? */
char *askpass = NULL;
char *ret = NULL;
char buf[1024] = { 0 };
DWORD mode;
size_t len = 0;
int retr = 0;
if (getenv(SSH_ASKPASS_ENV)) {
askpass = getenv(SSH_ASKPASS_ENV);
if ((ret = ssh_askpass(askpass, prompt)) == NULL)
return xstrdup("");
return ret;
}
/* prompt user */
wchar_t* wtmp = utf8_to_utf16(prompt);
if (wtmp == NULL)
fatal("unable to alloc memory");
_cputws(wtmp);
free(wtmp);
len = retr = 0;
int bufsize = sizeof(buf);
while (_kbhit())
_getch();
while (len < bufsize) {
buf[len] = (unsigned char)_getch();
if (buf[len] == '\r') {
if (_kbhit()) /* read linefeed if its there */
_getch();
break;
}
else if (buf[len] == '\n') {
break;
}
else if (buf[len] == '\b') { /* backspace */
if (len > 0)
len--; /* overwrite last character */
}
else if (buf[len] == '\003') {
/* exit on Ctrl+C */
fatal("");
}
else {
len++; /* keep reading in the loop */
}
}
buf[len] = '\0'; /* get rid of the cr/lf */
_cputs("\n"); /*show a newline as we do not echo password or the line */
ret = xstrdup(buf);
memset(buf, 'x', sizeof(buf));
return ret;
#else /* !WINDOWS */
char *askpass = NULL, *ret, buf[1024];
int rppflags, use_askpass = 0, ttyfd;
@ -236,7 +171,6 @@ read_passphrase(const char *prompt, int flags)
ret = xstrdup(buf);
explicit_bzero(buf, sizeof(buf));
return ret;
#endif /* !WINDOWS */
}
int

View File

@ -0,0 +1,385 @@

# test environment parametes initialized with defaults
$script:OpenSSHDir = "$env:SystemDrive\OpenSSH"
$script:OpenSSHTestDir = "$env:SystemDrive\OpenSSHTests"
$script:PesterTestResultsFile = Join-Path $script:OpenSSHTestDir "PesterTestResults.xml"
$script:UnitTestResultsFile = Join-Path $script:OpenSSHTestDir "UnitTestResults.txt"
$script:TestSetupLogFile = Join-Path $script:OpenSSHTestDir "TestSetupLog.txt"
function Set-OpenSSHTestParams
{
param
(
[string] $OpenSSHDir = $script:OpenSSHDir,
[string] $OpenSSHTestDir = $script:OpenSSHTestDir,
[string] $PesterTestResultsFile = $script:PesterTestResultsFile,
[string] $UnitTestResultsFile = $script:UnitTestResultsFile,
[string] $TestSetupLogFile = $script:TestSetupLogFile
)
$script:OpenSSHDir = $OpenSSHDir
$script:OpenSSHTestDir = $OpenSSHTestDir
$script:PesterTestResultsFile = $PesterTestResultsFile
$script:UnitTestResultsFile = $UnitTestResultsFile
$script:TestSetupLogFile = $TestSetupLogFile
}
function Dump-OpenSSHTestParams
{
Write-Host "OpenSSHDir: " $script:OpenSSHDir
Write-Host "OpenSSHTestDir: " $script:OpenSSHTestDir
Write-Host "PesterTestResultsFile: " $script:PesterTestResultsFile
Write-Host "UnitTestResultsFile: " $script:UnitTestResultsFile
Write-Host "TestSetupLogFile: " $script:TestSetupLogFile
}
<#
.SYNOPSIS
This function installs the tools required by our tests
1) Pester for running the tests
2) sysinternals required by the tests on windows.
#>
function Install-OpenSSHTestDependencies
{
[CmdletBinding()]
param ()
# Install chocolatey
if(-not (Get-Command "choco" -ErrorAction SilentlyContinue))
{
Write-Log -Message "Chocolatey not present. Installing chocolatey."
Invoke-Expression ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1')) 2>&1 >> $script:TestSetupLogFile
}
$isModuleAvailable = Get-Module 'Pester' -ListAvailable
if (-not ($isModuleAvailable))
{
Write-Log -Message "Installing Pester..."
choco install Pester -y --force --limitoutput 2>&1 >> $script:TestSetupLogFile
}
if ( -not (Test-Path "$env:ProgramData\chocolatey\lib\sysinternals\tools" ) ) {
Write-Log -Message "sysinternals not present. Installing sysinternals."
choco install sysinternals -y --force --limitoutput 2>&1 >> $script:TestSetupLogFile
}
<#if ( (-not (Test-Path "${env:ProgramFiles(x86)}\Windows Kits\8.1\Debuggers\" )) -and (-not (Test-Path "${env:ProgramFiles(x86)}\Windows Kits\10\Debuggers\" ))) {
Write-Log -Message "debugger not present. Installing windbg."
choco install windbg --force --limitoutput -y 2>&1 >> $script:TestSetupLogFile
}
Install-PSCoreFromGithub
$psCorePath = GetLocalPSCorePath
Set-BuildVariable -Name psPath -Value $psCorePath
#>
Write-BuildMessage -Message "All testDependencies installed!" -Category Information
}
$testaccounts = "sshtest_ssouser", "sshtest_pubkeyuser", "sshtest_passwduser"
$testaccountPassword = "P@ssw0rd_1" | ConvertTo-SecureString -AsPlainText -Force
<#
.Synopsis
Setup-OpenSSHTestEnvironment
#>
function Setup-OpenSSHTestEnvironment
{
[CmdletBinding()]
param
(
[bool] $Quiet = $false
)
if ($Quiet -eq $false) {
Write-Host 'WARNING: Following changes will be made to OpenSSH configuration'
Write-Host ' - sshd_config will be backed up as sshd_config.ori'
Write-Host ' - will be replaced with a test sshd_config'
Write-Host ' - %user%\.ssh\known_hosts will be backed up as known_hosts.ori'
Write-Host ' - will be replaced with a test known_hosts'
Write-Host ' - sshd test listener will be on port 47002'
Write-Host ' - %userprofile%\.ssh\known_hosts will be modified with test host key entry'
Write-Host ' - test accounts - ssouser, pubkeyuser and passwduser will be added'
Write-Host 'To cleanup - Run Cleanup-OpenSSHTestEnvironment'
}
if (-not(Test-Path(Join-Path $OpenSSHDir ssh.exe)))
{
Throw 'cannot find OpenSSH binaries under ' + $OpenSSHDir + '. Try -OpenSSHDir parameter'
}
try
{
$sshcmd = get-command ssh.exe
}
catch [System.Exception]
{
Throw 'Cannot find ssh.exe. Make sure OpenSSH binary path is in %PATH%'
}
# TODO - ensure ssh.exe is being picked from $OpenSSHDir. Multiple versions may exist
if (-not(Test-Path($OpenSSHTestDir))) {
Throw $OpenSSHTestDir +' does not exist. Try setting -OpenSSHTestDir parameter'
}
if ((Get-ChildItem $OpenSSHTestDir).Count -eq 0) {
Throw 'Nothing found in ' + $OpenSSHTestDir
}
#Backup existing OpenSSH configuration
if (-not(Test-Path (Join-Path $OpenSSHDir sshd_config.ori))) {
Copy-Item (Join-Path $OpenSSHDir sshd_config) (Join-Path $OpenSSHDir sshd_config.ori)
}
# copy new sshd_config
Stop-Service sshd
Stop-Service ssh-agent
Copy-Item (Join-Path $OpenSSHTestDir sshd_config) (Join-Path $OpenSSHDir sshd_config)
Copy-Item $OpenSSHTestDir\sshtest*hostkey* $OpenSSHDir
Start-Service sshd
#Backup existing known_hosts and replace with test version
#TODO - account for custom known_hosts locations
if (Test-Path (Join-Path $home .ssh\known_hosts)) {
Copy-Item (Join-Path $home .ssh\known_hosts) (Join-Path $home .ssh\known_hosts.ori)
}
Copy-Item (Join-Path $OpenSSHTestDir known_hosts) (Join-Path $home .ssh\known_hosts)
# create test accounts
foreach ($user in $testaccounts) {
New-LocalUser -Name $user -Password $testaccountPassword -ErrorAction SilentlyContinue
}
#setup single sign on for ssouser
#TODO - this is Windows specific. Need to be in PAL
$ssouser = Get-LocalUser sshtest_ssouser
$ssouserProfileRegistry = Join-Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList' $ssouser.SID
if (-not(Test-Path $ssouserProfileRegistry)) {
#create profile
if (-not($env:DISPLAY)) {$env:DISPLAY=1}
$env:SSH_ASKPASS="$($env:ComSpec) /c echo P@ssw0rd_1"
ssh -p 47002 sshtest_ssouser@localhost whoami
if ($env:DISPLAY -eq 1) {Remove-Item env:\DISPLAY}
remove-item "env:SSH_ASKPASS" -ErrorAction SilentlyContinue
}
$ssouserProfile = (Get-ItemProperty -Path $ssouserProfileRegistry -Name 'ProfileImagePath').ProfileImagePath
mkdir -Path (Join-Path $ssouserProfile .ssh) -ErrorAction SilentlyContinue
Copy-Item (Join-Path $OpenSSHTestDir sshtest_userssokey_ed25519.pub) (Join-Path $ssouserProfile .ssh\authorized_keys)
$acl = get-acl (Join-Path $ssouserProfile .ssh\authorized_keys)
$ar = New-Object System.Security.AccessControl.FileSystemAccessRule("NT Service\sshd", "Read", "Allow")
$acl.SetAccessRule($ar)
Set-Acl (Join-Path $ssouserProfile .ssh\authorized_keys) $acl
$ssouserpubkey = Join-Path $OpenSSHTestDir sshtest_userssokey_ed25519
ssh-add $ssouserpubkey
#TODO - scp tests need an admin user. This restriction should be removed
net localgroup Administrators sshtest_ssouser /add
}
<#
.Synopsis
Cleanup-OpenSSHTestEnvironment
#>
function Cleanup-OpenSSHTestEnvironment
{
[CmdletBinding()]
param
()
# .exe - Windows specific. TODO - PAL
if (-not(Test-Path(Join-Path $OpenSSHDir ssh.exe)))
{
Throw 'cannot find OpenSSH binaries under ' + $OpenSSHDir + '. Try -OpenSSHDir parameter'
}
#Restore sshd_config
if (Test-Path (Join-Path $OpenSSHDir sshd_config.ori)) {
Stop-Service sshd
Stop-Service ssh-agent
Copy-Item (Join-Path $OpenSSHDir sshd_config.ori) (Join-Path $OpenSSHDir sshd_config)
Remove-Item (Join-Path $OpenSSHDir sshd_config.ori) -Force
Remove-Item $OpenSSHDir\sshtest*hostkey* -Force
Start-Service sshd
}
#Restore known_hosts
if (Test-Path (Join-Path $home .ssh\known_hosts.ori)) {
Copy-Item (Join-Path $home .ssh\known_hosts.ori) (Join-Path $home .ssh\known_hosts)
Remove-Item (Join-Path $home .ssh\known_hosts.ori) -Force
}
# delete accounts
foreach ($user in $testaccounts) {
Remove-LocalUser -Name $user -ErrorAction SilentlyContinue
}
# remove registered keys
$ssouserpubkey = Join-Path $OpenSSHTestDir sshtest_userssokey_ed25519
ssh-add -d $ssouserpubkey
}
<#
.Synopsis
After build and test run completes, upload all artifacts from the build machine.
#>
function Deploy-OpenSSHTests
{
[CmdletBinding()]
param
(
[ValidateSet('Debug', 'Release', '')]
[string]$Configuration = "",
[ValidateSet('x86', 'x64', '')]
[string]$NativeHostArch = ""
)
if (-not (Test-Path -Path $OpenSSHTestDir -PathType Container))
{
$null = New-Item -Path $OpenSSHTestDir -ItemType Directory -Force -ErrorAction Stop
}
[string] $platform = $env:PROCESSOR_ARCHITECTURE
if(-not [String]::IsNullOrEmpty($NativeHostArch))
{
$folderName = $NativeHostArch
if($NativeHostArch -eq 'x86')
{
$folderName = "Win32"
}
}
else
{
if($platform -ieq "AMD64")
{
$folderName = "x64"
}
else
{
$folderName = "Win32"
}
}
if([String]::IsNullOrEmpty($Configuration))
{
if( $folderName -ieq "Win32" )
{
$RealConfiguration = "Debug"
}
else
{
$RealConfiguration = "Release"
}
}
else
{
$RealConfiguration = $Configuration
}
[System.IO.DirectoryInfo] $repositoryRoot = Get-RepositoryRoot
#copy all pester tests
$sourceDir = Join-Path $repositoryRoot.FullName -ChildPath "regress\pesterTests"
Copy-Item -Path "$sourceDir\*" -Destination $OpenSSHTestDir -Include *.ps1,*.psm1, sshd_config, known_hosts, sshtest_* -Force -ErrorAction Stop
#copy all unit tests.
$sourceDir = Join-Path $repositoryRoot.FullName -ChildPath "bin\$folderName\$RealConfiguration"
Copy-Item -Path "$sourceDir\*" -Destination "$OpenSSHTestDir\" -Container -Include unittest-* -Recurse -Force -ErrorAction Stop
#restart the service to use the test copy of sshd_config
Restart-Service sshd
}
<#
.Synopsis
Run OpenSSH pester tests.
#>
function Run-OpenSSHPesterTest
{
# Discover all CI tests and run them.
Push-Location $OpenSSHTestDir
Write-Log -Message "Running OpenSSH Pester tests..."
$testFolders = Get-ChildItem *.tests.ps1 -Recurse -Exclude SSHDConfig.tests.ps1, SSH.Tests.ps1 | ForEach-Object{ Split-Path $_.FullName} | Sort-Object -Unique
Invoke-Pester $testFolders -OutputFormat NUnitXml -OutputFile $PesterTestResultsFile -Tag 'CI'
Pop-Location
}
function Check-OpenSSHPesterTestResult
{
if (-not (Test-Path $PesterTestResultsFile))
{
Write-Warning "$($xml.'test-results'.failures) tests in regress\pesterTests failed"
Write-BuildMessage -Message "Test result file $PesterTestResultsFile not found after tests." -Category Error
Set-BuildVariable TestPassed False
}
$xml = [xml](Get-Content -raw $PesterTestResultsFile)
if ([int]$xml.'test-results'.failures -gt 0)
{
$errorMessage = "$($xml.'test-results'.failures) tests in regress\pesterTests failed. Detail test log is at TestResults.xml."
Write-Warning $errorMessage
Write-BuildMessage -Message $errorMessage -Category Error
Set-BuildVariable TestPassed False
}
# Writing out warning when the $Error.Count is non-zero. Tests Should clean $Error after success.
if ($Error.Count -gt 0)
{
Write-BuildMessage -Message "Tests Should clean $Error after success." -Category Warning
$Error| Out-File "$testInstallFolder\TestError.txt" -Append
}
}
<#
.Synopsis
Run unit tests.
#>
function Run-OpenSSHUnitTest
{
# Discover all CI tests and run them.
Push-Location $OpenSSHTestDir
Write-Log -Message "Running OpenSSH unit tests..."
if (Test-Path $unitTestOutputFile)
{
Remove-Item -Path $UnitTestResultsFile -Force -ErrorAction SilentlyContinue
}
$testFolders = Get-ChildItem unittest-*.exe -Recurse -Exclude unittest-sshkey.exe,unittest-kex.exe |
ForEach-Object{ Split-Path $_.FullName} |
Sort-Object -Unique
$testfailed = $false
if ($testFolders -ne $null)
{
$testFolders | % {
Push-Location $_
$unittestFile = "$(Split-Path $_ -Leaf).exe"
Write-Output "Running OpenSSH unit $unittestFile ..."
& .\$unittestFile >> $UnitTestResultsFile
$errorCode = $LASTEXITCODE
if ($errorCode -ne 0)
{
$testfailed = $true
$errorMessage = "$($_.FullName) test failed for OpenSSH.`nExitCode: $errorCode. Detail test log is at UnitTestResults.txt."
Write-Warning $errorMessage
Write-BuildMessage -Message $errorMessage -Category Error
Set-BuildVariable TestPassed False
}
Pop-Location
}
if(-not $testfailed)
{
Write-BuildMessage -Message "All Unit tests passed!" -Category Information
}
}
Pop-Location
}
Export-ModuleMember -Function Set-OpenSSHTestParams, Dump-OpenSSHTestParams, Install-OpenSSHTestDependencies, Setup-OpenSSHTestEnvironment, Cleanup-OpenSSHTestEnvironment, Deploy-OpenSSHTests, Run-OpenSSHUnitTest, Run-OpenSSHPesterTest, Check-OpenSSHPesterTestResult

View File

@ -64,7 +64,7 @@ function Is-CoreCLR {
Class Machine
{
[string] $MachineName = $env:COMPUTERNAME
[string] $MachineName = "localhost"
[MachineRole] $Role = [MachineRole]::Client
[PlatformType] $Platform
[boolean] $IsCoreCLR
@ -72,8 +72,9 @@ Class Machine
#Members on server role
[string []] $PublicHostKeyPaths
[string []] $PrivateHostKeyPaths
[string] $localAdminUserName = "localadmin"
[string] $localAdminPassword = "Bull_dog1"
[string] $ssouser = "sshtest_ssouser"
[string] $passwduser = "sshtest_passwduser"
[string] $passwduser_pw = "P@ssw0rd_1"
[string] $localAdminAuthorizedKeyPath
[string] $sshdConfigFile = (join-path $PSScriptRoot "sshd_config")
[string] $backupFileName = (join-path $PSScriptRoot "sshd_backup")
@ -92,19 +93,19 @@ Class Machine
Machine() {
$this.Platform = Set-Platform
$this.IsCoreCLR = Is-CoreCLR
$this.InitializeClient()
$this.InitializeServer()
#$this.InitializeClient()
#$this.InitializeServer()
}
Machine ([MachineRole] $r) {
$this.Platform = Set-Platform
$this.IsCoreCLR = Is-CoreCLR
$this.Role = $r
if($this.Role -eq [MachineRole]::Client) {
$this.InitializeClient()
} else {
$this.InitializeServer()
}
#if($this.Role -eq [MachineRole]::Client) {
# $this.InitializeClient()
#} else {
# $this.InitializeServer()
#}
}
[void] InitializeClient() {
@ -127,14 +128,6 @@ Class Machine
}
}
foreach($key in @("ed25519")) #@("rsa","dsa","ecdsa","ed25519")
{
$keyPath = "$($this.ClientKeyDirectory)\id_$key"
$this.clientPrivateKeyPaths += $keyPath
$this.clientPublicKeyPaths += "$keyPath.pub"
$str = ".\ssh-keygen -t $key -P """" -f $keyPath"
$this.RunCmd($str)
}
}
[void] InitializeServer() {
@ -157,13 +150,6 @@ Class Machine
}
$this.localAdminAuthorizedKeyPath = join-path $($this.localUserprofilePath) ".ssh/authorized_keys"
Remove-Item -Path $($this.localAdminAuthorizedKeyPath) -Force -ea silentlycontinue
#Generate all host keys
.\ssh-keygen -A
$this.PublicHostKeyPaths = @("$psscriptroot\ssh_host_ed25519_key.pub")
# @("$psscriptroot\ssh_host_rsa_key.pub","$psscriptroot\ssh_host_dsa_key.pub","$psscriptroot\ssh_host_ecdsa_key.pub","$psscriptroot\ssh_host_ed25519_key.pub")
$this.PrivateHostKeyPaths = @("$psscriptroot\ssh_host_ed25519_key")
# @("$psscriptroot\ssh_host_rsa_key","$psscriptroot\ssh_host_dsa_key","$psscriptroot\ssh_host_ecdsa_key","$psscriptroot\ssh_host_ed25519_key")
}
[void] SetupClient([Machine] $server) {
@ -251,6 +237,11 @@ Class Machine
{
$this.SetKeys($null, $publicKeyPath, $($this.localAdminAuthorizedKeyPath))
}
# Provide Read Access to NT Service\sshd
$acl = get-acl $($this.localAdminAuthorizedKeyPath)
$ar = New-Object System.Security.AccessControl.FileSystemAccessRule("NT Service\sshd", "Read", "Allow")
$acl.SetAccessRule($ar)
Set-Acl $($this.localAdminAuthorizedKeyPath) $acl
}
[void] CleanupServer() {
@ -351,7 +342,8 @@ Class Machine
}
[void] AddPasswordSetting([string] $pass) {
if ($this.Platform -eq [PlatformType]::Windows) {
if ($this.Platform -eq [PlatformType]::Windows) {
if (-not($env:DISPLAY)) {$env:DISPLAY=1}
$env:SSH_ASKPASS="$($env:ComSpec) /c echo $pass"
}
}
@ -359,6 +351,7 @@ Class Machine
[void] CleanupPasswordSetting() {
if ($this.Platform -eq [PlatformType]::Windows -and (Test-Path env:SSH_ASKPASS))
{
if ($env:DISPLAY -eq 1) {Remove-Item env:\DISPLAY}
remove-item "env:SSH_ASKPASS" -ErrorAction SilentlyContinue
}
}

View File

@ -1,53 +1,43 @@
using module .\PlatformAbstractLayer.psm1

Describe "Tests for portforwarding" -Tags "CI" {
BeforeAll {
$fileName = "test.txt"
$filePath = Join-Path ${TestDrive} $fileName
[Machine] $client = [Machine]::new([MachineRole]::Client)
[Machine] $server = [Machine]::new([MachineRole]::Server)
$client.SetupClient($server)
$server.SetupServer($client)
$server.SecureHostKeys($server.PrivateHostKeyPaths)
$server.SetupServerRemoting([Protocol]::WSMAN)
#setup single signon
.\ssh-add.exe $client.clientPrivateKeyPaths[0]
Remove-Item -Path $filePath -Force -ea silentlycontinue
$logName = "log.txt"
$logPath = Join-Path ${TestDrive} $logName
$server = $OpenSSHTestInfo["Target"]
$port = $OpenSSHTestInfo["Port"]
$ssouser = $OpenSSHTestInfo["SSOUser"]
$testData = @(
@{
Title = "Local port forwarding"
Options = "-L 5432:127.0.0.1:47001"
Port = 5432
FwdedPort = 5432
},
@{
Title = "Remote port forwarding"
Options = "-R 5432:127.0.0.1:47001"
Port = 5432
FwdedPort = 5432
}
)
}
AfterAll {
#cleanup single signon
.\ssh-add.exe -D
$Server.CleanupHostKeys()
$client.CleanupClient()
$server.CleanupServer()
}
AfterEach {
Remove-Item -Path $filePath -Force -ea silentlycontinue
Remove-Item -Path $logPath -Force -ea silentlycontinue
}
It '<Title>' -TestCases:$testData {
param([string]$Title, $Options, $port)
$str = ".\ssh $($Options) $($server.localAdminUserName)@$($server.MachineName) powershell.exe Test-WSMan -computer 127.0.0.1 -port $port > $filePath"
$client.RunCmd($str)
param([string]$Title, $Options, $FwdedPort)
$str = "ssh -p $($port) -E $logPath $($Options) $($ssouser)@$($server) powershell.exe Test-WSMan -computer 127.0.0.1 -port $FwdedPort > $filePath"
# TODO - move this to PAL
cmd /c $str
#validate file content.
$content = Get-Content $filePath
$content -like "wsmid*" | Should Not Be $null

View File

@ -1,5 +1,4 @@
using module .\PlatformAbstractLayer.psm1

#covered -i -p -q -r -v -c -S -C
#todo: -F, -l and -P should be tested over the network
Describe "Tests for scp command" -Tags "CI" {
@ -21,10 +20,9 @@ Describe "Tests for scp command" -Tags "CI" {
"Test content in nested dir" | Set-content -Path $NestedSourceFilePath
$null = New-Item $DestinationDir -ItemType directory -Force
[Machine] $client = [Machine]::new([MachineRole]::Client)
[Machine] $server = [Machine]::new([MachineRole]::Server)
$client.SetupClient($server)
$server.SetupServer($client)
$server = $OpenSSHTestInfo["Target"]
$port = $OpenSSHTestInfo["Port"]
$ssouser = $OpenSSHTestInfo["SSOUser"]
$script:logNum = 0
$testData = @(
@ -36,11 +34,11 @@ Describe "Tests for scp command" -Tags "CI" {
@{
Title = 'Simple copy local file to remote file'
Source = $SourceFilePath
Destination = "$($server.localAdminUserName)@$($server.MachineName):$DestinationFilePath"
Destination = "$($ssouser)@$($server):$DestinationFilePath"
},
@{
Title = 'Simple copy remote file to local file'
Source = "$($server.localAdminUserName)@$($server.MachineName):$SourceFilePath"
Source = "$($ssouser)@$($server):$SourceFilePath"
Destination = $DestinationFilePath
},
@{
@ -51,11 +49,11 @@ Describe "Tests for scp command" -Tags "CI" {
@{
Title = 'simple copy local file to remote dir'
Source = $SourceFilePath
Destination = "$($server.localAdminUserName)@$($server.MachineName):$DestinationDir"
Destination = "$($ssouser)@$($server):$DestinationDir"
},
@{
Title = 'simple copy remote file to local dir'
Source = "$($server.localAdminUserName)@$($server.MachineName):$SourceFilePath"
Source = "$($ssouser)@$($server):$SourceFilePath"
Destination = $DestinationDir
}
)
@ -64,7 +62,7 @@ Describe "Tests for scp command" -Tags "CI" {
@{
Title = 'copy from local dir to remote dir'
Source = $sourceDir
Destination = "$($server.localAdminUserName)@$($server.MachineName):$DestinationDir"
Destination = "$($ssouser)@$($server):$DestinationDir"
},
<# @{
Title = 'copy from local dir to local dir'
@ -73,7 +71,7 @@ Describe "Tests for scp command" -Tags "CI" {
},#>
@{
Title = 'copy from remote dir to local dir'
Source = "$($server.localAdminUserName)@$($server.MachineName):$sourceDir"
Source = "$($ssouser)@$($server):$sourceDir"
Destination = $DestinationDir
}
)
@ -93,9 +91,6 @@ Describe "Tests for scp command" -Tags "CI" {
}
AfterAll {
$client.CleanupClient()
$server.CleanupServer()
Get-Item $SourceDir | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
Get-Item $DestinationDir | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
}
@ -114,16 +109,15 @@ Describe "Tests for scp command" -Tags "CI" {
}
}#>
Context "Key is Secured in ssh-agent on server" {
BeforeAll {
$Server.SecureHostKeys($server.PrivateHostKeyPaths)
$privateKeyFile = $client.clientPrivateKeyPaths[0]
Context "SCP -i option" {
BeforeAll {
}
BeforeEach {
if ($env:DebugMode)
{
Stop-Service ssh-agent -Force
Start-Sleep 2
# Fix this - pick up logs from ssh installation dir, not test directory
Remove-Item .\logs\ssh-agent.log -Force -ErrorAction ignore
Remove-Item .\logs\sshd.log -Force -ErrorAction ignore
Start-Service sshd
@ -131,12 +125,11 @@ Describe "Tests for scp command" -Tags "CI" {
}
AfterAll {
$Server.CleanupHostKeys()
}
It 'File copy with -i option and private key: <Title> ' -TestCases:$testData {
It 'File copy with -i option: <Title> ' -TestCases:$testData {
param([string]$Title, $Source, $Destination)
.\scp -i $privateKeyFile $Source $Destination
scp -P $port $Source $Destination
$LASTEXITCODE | Should Be 0
#validate file content. DestPath is the path to the file.
@ -148,7 +141,7 @@ Describe "Tests for scp command" -Tags "CI" {
It 'Directory recursive copy with -i option and private key: <Title> ' -TestCases:$testData1 {
param([string]$Title, $Source, $Destination)
.\scp -r -i $privateKeyFile $Source $Destination
scp -P $port -r $Source $Destination
$LASTEXITCODE | Should Be 0
CheckTarget -target (join-path $DestinationDir $SourceDirName) | Should Be $true
@ -160,23 +153,16 @@ Describe "Tests for scp command" -Tags "CI" {
}
}
Context "Single signon with keys -p -v -c option Secured in ssh-agent" {
Context "SCP -p -v -c options" {
BeforeAll {
$Server.SecureHostKeys($server.PrivateHostKeyPaths)
$identifyFile = $client.clientPrivateKeyPaths[0]
#setup single signon
.\ssh-add.exe $identifyFile
}
AfterAll {
$Server.CleanupHostKeys()
#cleanup single signon
.\ssh-add.exe -D
}
It 'File copy with -S -v option (positive)' {
.\scp -S .\ssh.exe -v $SourceFilePath "$($server.localAdminUserName)@$($server.MachineName):$DestinationFilePath"
It 'File copy with -S option (positive)' {
$sshcmd = (get-command ssh).Path
scp -P $port -S $sshcmd $SourceFilePath "$($ssouser)@$($server):$DestinationFilePath"
$LASTEXITCODE | Should Be 0
#validate file content. DestPath is the path to the file.
CheckTarget -target $DestinationFilePath | Should Be $true
@ -184,10 +170,11 @@ Describe "Tests for scp command" -Tags "CI" {
$equal | Should Be $true
}
It 'File copy with -p -c option: <Title> ' -TestCases:$testData {
param([string]$Title, $Source, $Destination)
.\scp -p -c aes128-ctr -C $Source $Destination
scp -P $port -p -c aes128-ctr -C $Source $Destination
$LASTEXITCODE | Should Be 0
#validate file content. DestPath is the path to the file.
CheckTarget -target $DestinationFilePath | Should Be $true
@ -198,7 +185,7 @@ Describe "Tests for scp command" -Tags "CI" {
It 'Directory recursive copy with -r -p -c option: <Title> ' -TestCases:$testData1 {
param([string]$Title, $Source, $Destination)
.\scp -r -p -c aes128-ctr $Source $Destination
scp -P $port -r -p -c aes128-ctr $Source $Destination
$LASTEXITCODE | Should Be 0
CheckTarget -target (join-path $DestinationDir $SourceDirName) | Should Be $true
$equal = @(Compare-Object (Get-Item -path $SourceDir ) (Get-Item -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length, LastWriteTime.DateTime).Length -eq 0
@ -209,15 +196,14 @@ Describe "Tests for scp command" -Tags "CI" {
}
}
Context "Private key authentication with -i -C -q options. host keys are not secured on server" {
Context "SCP -i -C -q options" {
BeforeAll {
$identifyFile = $client.clientPrivateKeyPaths[0]
}
It 'File copy with -i -C -q options: <Title> ' -TestCases:$testData{
param([string]$Title, $Source, $Destination)
.\scp -i $identifyFile -C -q $Source $Destination
scp -P $port -C -q $Source $Destination
$LASTEXITCODE | Should Be 0
#validate file content. DestPath is the path to the file.
CheckTarget -target $DestinationFilePath | Should Be $true
@ -228,7 +214,7 @@ Describe "Tests for scp command" -Tags "CI" {
It 'Directory recursive copy with -i -C -r and -q options: <Title> ' -TestCases:$testData1 {
param([string]$Title, $Source, $Destination)
.\scp -i $identifyFile -C -r -q $Source $Destination
scp -P $port -C -r -q $Source $Destination
$LASTEXITCODE | Should Be 0
CheckTarget -target (join-path $DestinationDir $SourceDirName) | Should Be $true
$equal = @(Compare-Object (Get-Item -path $SourceDir ) (Get-Item -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length).Length -eq 0
@ -239,6 +225,7 @@ Describe "Tests for scp command" -Tags "CI" {
}
}
<# No need to test Password auth for scp. Remove these if they are not adding any value from scp side
Context "Password authentication" {
BeforeAll {
$client.AddPasswordSetting($server.localAdminPassword)
@ -271,5 +258,6 @@ Describe "Tests for scp command" -Tags "CI" {
$equal = @(Compare-Object (Get-ChildItem -Recurse -path $SourceDir) (Get-ChildItem -Recurse -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length, LastWriteTime.DateTime).Length -eq 0
$equal | Should Be $true
}
}
}
#>
}

View File

@ -29,14 +29,12 @@ Describe "SFTP Testcases" -Tags "CI" {
[Machine] $client = [Machine]::new([MachineRole]::Client)
[Machine] $server = [Machine]::new([MachineRole]::Server)
$client.SetupClient($server)
$server.SetupServer($client)
$testData1 = @(
@{
title = "put, ls for non-unicode file names"
logonstr = "$($server.localadminusername)@$($server.machinename)"
options = '-i $identifyfile'
logonstr = "$($server.ssouser)@$($server.machinename)"
options = ''
commands = "put $tempFilePath $serverDirectory
ls $serverDirectory"
expectedoutput = (join-path $serverdirectory $tempFileName)
@ -44,32 +42,32 @@ Describe "SFTP Testcases" -Tags "CI" {
},
@{
title = "get, ls for non-unicode file names"
logonstr = "$($server.localadminusername)@$($server.machinename)"
options = '-i $identifyfile'
logonstr = "$($server.ssouser)@$($server.machinename)"
options = ''
commands = "get $tempFilePath $clientDirectory
ls $clientDirectory"
expectedoutput = (join-path $clientDirectory $tempFileName)
},
@{
title = "mput, ls for non-unicode file names"
logonstr = "$($server.localadminusername)@$($server.machinename)"
options = '-i $identifyfile'
logonstr = "$($server.ssouser)@$($server.machinename)"
options = ''
commands = "mput $tempFilePath $serverDirectory
ls $serverDirectory"
expectedoutput = (join-path $serverdirectory $tempFileName)
},
@{
title = "mget, ls for non-unicode file names"
logonstr = "$($server.localadminusername)@$($server.machinename)"
options = '-i $identifyfile'
logonstr = "$($server.ssouser)@$($server.machinename)"
options = ''
commands = "mget $tempFilePath $clientDirectory
ls $clientDirectory"
expectedoutput = (join-path $clientDirectory $tempFileName)
},
@{
title = "mkdir, cd, pwd for non-unicode directory names"
logonstr = "$($server.localadminusername)@$($server.machinename)"
options = '-i $identifyfile'
logonstr = "$($server.ssouser)@$($server.machinename)"
options = ''
commands = "cd $serverdirectory
mkdir server_test_dir
cd server_test_dir
@ -78,8 +76,8 @@ Describe "SFTP Testcases" -Tags "CI" {
},
@{
Title = "lmkdir, lcd, lpwd for non-unicode directory names"
LogonStr = "$($server.localAdminUserName)@$($server.MachineName)"
Options = '-i $identifyFile'
LogonStr = "$($server.ssouser)@$($server.MachineName)"
Options = ''
Commands = "lcd $clientDirectory
lmkdir client_test_dir
lcd client_test_dir
@ -88,40 +86,40 @@ Describe "SFTP Testcases" -Tags "CI" {
},
@{
title = "put, ls for unicode file names"
logonstr = "$($server.localadminusername)@$($server.machinename)"
options = '-i $identifyfile'
logonstr = "$($server.ssouser)@$($server.machinename)"
options = ''
commands = "put $tempUnicodeFilePath $serverDirectory
ls $serverDirectory"
expectedoutput = (join-path $serverdirectory $tempUnicodeFileName)
},
@{
title = "get, ls for unicode file names"
logonstr = "$($server.localadminusername)@$($server.machinename)"
options = '-i $identifyfile'
logonstr = "$($server.ssouser)@$($server.machinename)"
options = ''
commands = "get $tempUnicodeFilePath $clientDirectory
ls $clientDirectory"
expectedoutput = (join-path $clientDirectory $tempUnicodeFileName)
},
@{
title = "mput, ls for unicode file names"
logonstr = "$($server.localadminusername)@$($server.machinename)"
options = '-i $identifyfile'
logonstr = "$($server.ssouser)@$($server.machinename)"
options = ''
commands = "mput $tempUnicodeFilePath $serverDirectory
ls $serverDirectory"
expectedoutput = (join-path $serverdirectory $tempUnicodeFileName)
},
@{
title = "mget, ls for unicode file names"
logonstr = "$($server.localadminusername)@$($server.machinename)"
options = '-i $identifyfile'
logonstr = "$($server.ssouser)@$($server.machinename)"
options = ''
commands = "mget $tempUnicodeFilePath $clientDirectory
ls $clientDirectory"
expectedoutput = (join-path $clientDirectory $tempUnicodeFileName)
},
@{
title = "mkdir, cd, pwd for unicode directory names"
logonstr = "$($server.localadminusername)@$($server.machinename)"
options = '-i $identifyfile'
logonstr = "$($server.ssouser)@$($server.machinename)"
options = ''
commands = "cd $serverdirectory
mkdir server_test_dir_язык
cd server_test_dir_язык
@ -130,8 +128,8 @@ Describe "SFTP Testcases" -Tags "CI" {
},
@{
Title = "lmkdir, lcd, lpwd for unicode directory names"
LogonStr = "$($server.localAdminUserName)@$($server.MachineName)"
Options = '-i $identifyFile'
LogonStr = "$($server.ssouser)@$($server.MachineName)"
Options = ''
Commands = "lcd $clientDirectory
lmkdir client_test_dir_язык
lcd client_test_dir_язык
@ -144,8 +142,8 @@ Describe "SFTP Testcases" -Tags "CI" {
$testData2 = @(
@{
title = "rm, rmdir, rename for unicode file, directory"
logonstr = "$($server.localadminusername)@$($server.machinename)"
options = '-i $identifyfile -b $batchFilePath'
logonstr = "$($server.ssouser)@$($server.machinename)"
options = 'b $batchFilePath'
tmpFileName1 = $tempUnicodeFileName
tmpFilePath1 = $tempUnicodeFilePath
@ -159,8 +157,8 @@ Describe "SFTP Testcases" -Tags "CI" {
},
@{
title = "rm, rmdir, rename for non-unicode file, directory"
logonstr = "$($server.localadminusername)@$($server.machinename)"
options = '-i $identifyfile -b $batchFilePath'
logonstr = "$($server.ssouser)@$($server.machinename)"
options = '-b $batchFilePath'
tmpFileName1 = $tempFileName
tmpFilePath1 = $tempFilePath
@ -176,20 +174,12 @@ Describe "SFTP Testcases" -Tags "CI" {
}
AfterAll {
$client.CleanupClient()
$server.CleanupServer()
}
Context "Single signon" {
BeforeAll {
$Server.SecureHostKeys($server.PrivateHostKeyPaths)
$identifyFile = $client.clientPrivateKeyPaths[0]
.\ssh-add.exe $identifyFile #setup single signon
Context "SFTP Test Cases" {
BeforeAll {
}
AfterAll {
$Server.CleanupHostKeys()
.\ssh-add.exe -D #cleanup single signon
Get-Item $rootDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
}
@ -204,7 +194,8 @@ Describe "SFTP Testcases" -Tags "CI" {
param([string]$Title, $LogonStr, $Options, $Commands, $ExpectedOutput, $SkipVerification = $false)
Set-Content $batchFilePath -Encoding UTF8 -value $Commands
$str = $ExecutionContext.InvokeCommand.ExpandString(".\sftp $($Options) -b $batchFilePath $($LogonStr) > $outputFilePath")
Write-Host "sftp -P 47002 $($Options) -b $batchFilePath $($LogonStr) > $outputFilePath"
$str = $ExecutionContext.InvokeCommand.ExpandString("sftp -P 47002 $($Options) -b $batchFilePath $($LogonStr) > $outputFilePath")
$client.RunCmd($str)
#validate file content.
@ -221,7 +212,7 @@ Describe "SFTP Testcases" -Tags "CI" {
put $tmpFilePath1 $tmpDirectoryPath1
ls $tmpDirectoryPath1"
Set-Content $batchFilePath -Encoding UTF8 -value $commands
$str = $ExecutionContext.InvokeCommand.ExpandString(".\sftp $($Options) $($LogonStr) > $outputFilePath")
$str = $ExecutionContext.InvokeCommand.ExpandString("sftp -P 47002 $($Options) $($LogonStr) > $outputFilePath")
$client.RunCmd($str)
Test-Path (join-path $tmpDirectoryPath1 $tmpFileName1) | Should be $true
@ -230,7 +221,7 @@ Describe "SFTP Testcases" -Tags "CI" {
pwd
"
Set-Content $batchFilePath -Encoding UTF8 -value $commands
$str = $ExecutionContext.InvokeCommand.ExpandString(".\sftp $($Options) $($LogonStr) > $outputFilePath")
$str = $ExecutionContext.InvokeCommand.ExpandString("sftp -P 47002 $($Options) $($LogonStr) > $outputFilePath")
$client.RunCmd($str)
Test-Path (join-path $tmpDirectoryPath1 $tmpFileName1) | Should be $false
@ -241,7 +232,7 @@ Describe "SFTP Testcases" -Tags "CI" {
ls $tmpDirectoryPath1
pwd"
Set-Content $batchFilePath -Encoding UTF8 -value $commands
$str = $ExecutionContext.InvokeCommand.ExpandString(".\sftp $($Options) $($LogonStr) > $outputFilePath")
$str = $ExecutionContext.InvokeCommand.ExpandString("sftp -P 47002 $($Options) $($LogonStr) > $outputFilePath")
$client.RunCmd($str)
Test-Path (join-path $tmpDirectoryPath1 $tmpFileName2) | Should be $true
@ -251,7 +242,7 @@ Describe "SFTP Testcases" -Tags "CI" {
rename $tmpDirectoryPath1 $tmpDirectoryPath2
ls $serverDirectory"
Set-Content $batchFilePath -Encoding UTF8 -value $commands
$str = $ExecutionContext.InvokeCommand.ExpandString(".\sftp $($Options) $($LogonStr) > $outputFilePath")
$str = $ExecutionContext.InvokeCommand.ExpandString("sftp -P 47002 $($Options) $($LogonStr) > $outputFilePath")
$client.RunCmd($str)
Test-Path $tmpDirectoryPath2 | Should be $true
@ -260,7 +251,7 @@ Describe "SFTP Testcases" -Tags "CI" {
$commands = "rmdir $tmpDirectoryPath2
ls $serverDirectory"
Set-Content $batchFilePath -Encoding UTF8 -value $commands
$str = $ExecutionContext.InvokeCommand.ExpandString(".\sftp $($Options) $($LogonStr) > $outputFilePath")
$str = $ExecutionContext.InvokeCommand.ExpandString("sftp -P 47002 $($Options) $($LogonStr) > $outputFilePath")
$client.RunCmd($str)
Test-Path $tmpDirectoryPath2 | Should be $false
}

View File

@ -10,7 +10,7 @@
# possible, but leave them commented. Uncommented options override the
# default value.
#Port 22
Port 47002
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
@ -21,9 +21,10 @@
# HostKey for protocol version 1
#HostKey /etc/ssh/ssh_host_key
# HostKeys for protocol version 2
#HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_dsa_key
#HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey sshtest_hostkey_rsa
HostKey sshtest_hostkey_dsa
HostKey sshtest_hostkey_ecdsa
HostKey sshtest_hostkey_ed25519
# Lifetime and size of ephemeral version 1 server key
#KeyRegenerationInterval 1h
@ -121,7 +122,7 @@ Subsystem sftp sftp-server.exe
# ForceCommand cvs server
PubkeyAcceptedKeyTypes ssh-ed25519*
DenyUsers denyuser1 deny*2 denyuse?3,
AllowUsers allowuser1 allowu*r2 allow?se?3 allowuser4 localuser1 localu*r2 loc?lu?er3 localadmin
DenyGroups denygroup1 denygr*p2 deny?rou?3
AllowGroups allowgroup1 allowg*2 allowg?ou?3 Adm*
#DenyUsers denyuser1 deny*2 denyuse?3,
#AllowUsers allowuser1 allowu*r2 allow?se?3 allowuser4 localuser1 localu*r2 loc?lu?er3 localadmin
#DenyGroups denygroup1 denygr*p2 deny?rou?3
#AllowGroups allowgroup1 allowg*2 allowg?ou?3 Adm*

View File

@ -0,0 +1,4 @@
[localhost]:47002 ssh-dss AAAAB3NzaC1kc3MAAACBAIyVGPwSzaCedtroufmFrwXGVPzYUMHPePvlduORG2+1VmLkP2Yw+U6MHRnaDyDriCulhnmwIueGxhH+t0HKbGK0j7XpGnwgmFOBIg5gJwQTDJ+gX+qC2ju55WB0Gkkwl+xktnAFSqmj8ttSzUBhh1ksh5A6oW+NKjwEVH8tQExFAAAAFQC0YldxCDQbTuDO04EVgA0OMpDIvwAAAIBXWRzpoyQWNoB18DGbY9zupGhfwuKGmnlj2mY0aYxY3qu1+9ciQOBrwYJlf4dEJbirwp2XmKzHZ6LFrkLQptVcD1wDkG/a/wMRvh+tbxlq45S3Eh0oNj1cobhUlFm9m5PM2HW1LccbOAEBUG/L4Vcj1Ag4n639H0fwDRL+rwOpjgAAAIBh/fSBidBGsQITgg45wwDszk7AAhngNm+jbiea8dbgYP6wpT6dJdg3pYwKT0V/PdXTSDi16kkoMkbUsMZyxyFJf/TtmCtBnon55yL9+H5dtcOBF8BXR7KzQX1E1n0eIL9jZ0Q4BspkB4LKQXhxRnrNJlv/oopxXua/GCMW17xxuA== sshtest_hostkey_dsa
[localhost]:47002 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHF2eWwgnaUSLNNN0ilxiT916uMa6lusMB31AxfkDGArh4xCWL0e3F/gRifRephM0cD2dSh8Ji6VnjkhvZptjEw= sshtest_hostkey_ecdsa
[localhost]:47002 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMtJMxwn+iJU0X4+EC7PSj/cfcMbdP6ahhodtXx+6RHv sshtest_hostkey_ed25519
[localhost]:47002 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDU+NcQ5NuRutQJoZVjDmP/vE6IYZOaE59FTUjaoZkuPl4prdOPgqAnCwSy9XtnfzPm/oe62SyYIHgj8wRzhqjMU8g8aGqfv9ryF+hpNXZrFYXIdkdxnubzfb4e70RRRoTH8P5vuY8sAn0FIRlV/3EDkSKBFy2W3InMTO6l8gbkzzkgbn1GLvH06QJVdb2PcHksSn7dJBVHWASYi3TJWWu4muI+ZNfothujxAHqjKTJuJ9apDZIc0tnkPmlifRmolSUS4OAH2KWZ+5Gwaj7gsB8bk4QuA+QCT60OCcuzCcy4FBuXvvXkM9MBe/P2KZjVLAn86SriRtoE4RI+9R9S7DV sshtest_hostkey_rsa

View File

@ -0,0 +1,12 @@
-----BEGIN DSA PRIVATE KEY-----
MIIBuwIBAAKBgQCMlRj8Es2gnnba6Ln5ha8FxlT82FDBz3j75XbjkRtvtVZi5D9m
MPlOjB0Z2g8g64grpYZ5sCLnhsYR/rdBymxitI+16Rp8IJhTgSIOYCcEEwyfoF/q
gto7ueVgdBpJMJfsZLZwBUqpo/LbUs1AYYdZLIeQOqFvjSo8BFR/LUBMRQIVALRi
V3EINBtO4M7TgRWADQ4ykMi/AoGAV1kc6aMkFjaAdfAxm2Pc7qRoX8Lihpp5Y9pm
NGmMWN6rtfvXIkDga8GCZX+HRCW4q8Kdl5isx2eixa5C0KbVXA9cA5Bv2v8DEb4f
rW8ZauOUtxIdKDY9XKG4VJRZvZuTzNh1tS3HGzgBAVBvy+FXI9QIOJ+t/R9H8A0S
/q8DqY4CgYBh/fSBidBGsQITgg45wwDszk7AAhngNm+jbiea8dbgYP6wpT6dJdg3
pYwKT0V/PdXTSDi16kkoMkbUsMZyxyFJf/TtmCtBnon55yL9+H5dtcOBF8BXR7Kz
QX1E1n0eIL9jZ0Q4BspkB4LKQXhxRnrNJlv/oopxXua/GCMW17xxuAIVAIy08ce7
877PESiaI4iDWj36uuWV
-----END DSA PRIVATE KEY-----

View File

@ -0,0 +1 @@
ssh-dss AAAAB3NzaC1kc3MAAACBAIyVGPwSzaCedtroufmFrwXGVPzYUMHPePvlduORG2+1VmLkP2Yw+U6MHRnaDyDriCulhnmwIueGxhH+t0HKbGK0j7XpGnwgmFOBIg5gJwQTDJ+gX+qC2ju55WB0Gkkwl+xktnAFSqmj8ttSzUBhh1ksh5A6oW+NKjwEVH8tQExFAAAAFQC0YldxCDQbTuDO04EVgA0OMpDIvwAAAIBXWRzpoyQWNoB18DGbY9zupGhfwuKGmnlj2mY0aYxY3qu1+9ciQOBrwYJlf4dEJbirwp2XmKzHZ6LFrkLQptVcD1wDkG/a/wMRvh+tbxlq45S3Eh0oNj1cobhUlFm9m5PM2HW1LccbOAEBUG/L4Vcj1Ag4n639H0fwDRL+rwOpjgAAAIBh/fSBidBGsQITgg45wwDszk7AAhngNm+jbiea8dbgYP6wpT6dJdg3pYwKT0V/PdXTSDi16kkoMkbUsMZyxyFJf/TtmCtBnon55yL9+H5dtcOBF8BXR7KzQX1E1n0eIL9jZ0Q4BspkB4LKQXhxRnrNJlv/oopxXua/GCMW17xxuA== sshtest_hostkey_dsa

View File

@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEICAT5BC1AJpeOsRQaettNtqw6rzKlHDgtGvqnYZuU8YOoAoGCCqGSM49
AwEHoUQDQgAEcXZ5bCCdpRIs003SKXGJP3Xq4xrqW6wwHfUDF+QMYCuHjEJYvR7c
X+BGJ9F6mEzRwPZ1KHwmLpWeOSG9mm2MTA==
-----END EC PRIVATE KEY-----

View File

@ -0,0 +1 @@
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHF2eWwgnaUSLNNN0ilxiT916uMa6lusMB31AxfkDGArh4xCWL0e3F/gRifRephM0cD2dSh8Ji6VnjkhvZptjEw= sshtest_hostkey_ecdsa

View File

@ -0,0 +1,7 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACDLSTMcJ/oiVNF+PhAuz0o/3H3DG3T+moYaHbV8fukR7wAAAKACW4cWAluH
FgAAAAtzc2gtZWQyNTUxOQAAACDLSTMcJ/oiVNF+PhAuz0o/3H3DG3T+moYaHbV8fukR7w
AAAEDIU6PKvxw+6hgpQmTOOFeUasWnsYU3gricJCNrEHu2FstJMxwn+iJU0X4+EC7PSj/c
fcMbdP6ahhodtXx+6RHvAAAAF3NzaHRlc3RfaG9zdGtleV9lZDI1NTE5AQIDBAUG
-----END OPENSSH PRIVATE KEY-----

View File

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMtJMxwn+iJU0X4+EC7PSj/cfcMbdP6ahhodtXx+6RHv sshtest_hostkey_ed25519

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEA1PjXEOTbkbrUCaGVYw5j/7xOiGGTmhOfRU1I2qGZLj5eKa3T
j4KgJwsEsvV7Z38z5v6HutksmCB4I/MEc4aozFPIPGhqn7/a8hfoaTV2axWFyHZH
cZ7m832+Hu9EUUaEx/D+b7mPLAJ9BSEZVf9xA5EigRctltyJzEzupfIG5M85IG59
Ri7x9OkCVXW9j3B5LEp+3SQVR1gEmIt0yVlruJriPmTX6LYbo8QB6oykybifWqQ2
SHNLZ5D5pYn0ZqJUlEuDgB9ilmfuRsGo+4LAfG5OELgPkAk+tDgnLswnMuBQbl77
15DPTAXvz9imY1SwJ/Okq4kbaBOESPvUfUuw1QIDAQABAoIBAGdEafRVJGqbbulk
om0vsyl0A5h5x/pz/Uy7VtI8fWxA7aPEF8uEiWelHhgwlC/xLBeb3/CoEcmKJPc5
hTUHXJ4HGhbAgsMHYoD1OsqZE9yEySQUxju/0zjKBgA2AKhwSz4wCw/dqCCs7DYq
gICEpiYWn+Z8eKyoL2ETBL0OiG01c4oZ8Qd1WrNPNAOA8uX2avCIawiGqfI5hRR2
UIpmTNsh8SbA7hMqI47JlLvmfAdKOvug09f36Yhx63RuXWy0AHqz3HcTe4K4tzlP
M+DnKDgHQkx8R5j/Q9Dv6ZlKn85FatIWftjd9e4Zsjx2lCKXBFIyn3EM1aiCaRAS
iIFJh4ECgYEA6nBShG3z6bLbBNEWPq2xqmq6uJDD7dg6glK5alDDKwCmurfQYxyY
HD/1YcIlf+kC4qUCrREgYlheH3xRbzT0yomtci015iC8R8ZZgGNqZO52HxhQVWdN
i08vsJmUnrq0WFyXS0OysnPCEPLbHBoFVbJWEDTgKxLOwbYMEyp7IHECgYEA6I8Z
tRE3AMbdYvN8+hjq5fcrsRZvkbddYa3DLYImii09s84p82MEskFd+dcTs6ViX2Qn
wFgdASCi0FBblKca6ZxgwMHoEEiWgx6zndayeU2wDGWCbHlVXkpnCPb7O+YoMKhy
XtDDfVZ0n0Cu+W6dlbVxWyP0uQ8RrE25Po/QSKUCgYAGCrkFsrO7jSF54U2ade2D
P9bqFMkH4y+21hzzMXumKxEg9MXJGB6Pc9KGH3PJ9R5e6vPDtBJKlo5ub0zF+e5p
Hd07eRDPin5vtxvtZCKE0WR37q97U/s6oOLQwVSENrmZIWHAzdDYKoWQ3EFrWvxS
NhNjvYkdcxGjCmcLQ2gC8QKBgD4IFZpXmi1J3jmLqxVm2hk3Id9dlarvlyf72mjk
I3WN9bxlTIlQKyuFBhUjSm0Luz6oj3XdyvbHBsa7+IGhRSt0+9XOoyDcy9DzuoNq
hjaXA1N7LBvVDXFWNT+N6Zujm6rG86LY2pwvGHJ2JXYBDGWnfTILWDaYj2U/Yh8O
60bFAoGAVnm3EVlak5mbDpSpyzqnglVKgZ+mz+4ODcF+qK4415QtAua8Je8Frcje
3dYJtP5c5Xm+wE5Lmr+yZUAxup5oC5NAmtvLwK8DLPjfZIBtF7qBf08am8e8HnZw
PzFks7iwv86eqgvTwBdE6QmaBzvEPLSmSI93uRz3q/S+16j50Pk=
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDU+NcQ5NuRutQJoZVjDmP/vE6IYZOaE59FTUjaoZkuPl4prdOPgqAnCwSy9XtnfzPm/oe62SyYIHgj8wRzhqjMU8g8aGqfv9ryF+hpNXZrFYXIdkdxnubzfb4e70RRRoTH8P5vuY8sAn0FIRlV/3EDkSKBFy2W3InMTO6l8gbkzzkgbn1GLvH06QJVdb2PcHksSn7dJBVHWASYi3TJWWu4muI+ZNfothujxAHqjKTJuJ9apDZIc0tnkPmlifRmolSUS4OAH2KWZ+5Gwaj7gsB8bk4QuA+QCT60OCcuzCcy4FBuXvvXkM9MBe/P2KZjVLAn86SriRtoE4RI+9R9S7DV sshtest_hostkey_rsa

View File

@ -0,0 +1,7 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACArxdmtP2DtTFvNp+4N4vlEP2tBmG7QtG4qfNUKlYmxRQAAAKAX+9lZF/vZ
WQAAAAtzc2gtZWQyNTUxOQAAACArxdmtP2DtTFvNp+4N4vlEP2tBmG7QtG4qfNUKlYmxRQ
AAAEBkZYPXRU9wu7OCcBia+eKvWOtDKpZRibjGQMTdBlCn5CvF2a0/YO1MW82n7g3i+UQ/
a0GYbtC0bip81QqVibFFAAAAGnNzaHRlc3RfdXNlcnNzb2tleV9lZDI1NTE5AQID
-----END OPENSSH PRIVATE KEY-----

View File

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICvF2a0/YO1MW82n7g3i+UQ/a0GYbtC0bip81QqVibFF sshtest_userssokey_ed25519

View File

@ -56,11 +56,6 @@ tests(void)
{
char *loc;
#ifdef WINDOWS
TEST_START("not applicable to Windows yet");
TEST_DONE();
return;
#endif
TEST_START("utf8_setlocale");
loc = setlocale(LC_CTYPE, "en_US.UTF-8");
ASSERT_PTR_NE(loc, NULL);

47
scp.c
View File

@ -292,29 +292,11 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
addargs(&args, "%s", host);
addargs(&args, "%s", cmd);
{
char* full_cmd;
size_t cmdlen = 0;
char** list = args.list;
fcntl(pout[0], F_SETFD, FD_CLOEXEC);
fcntl(pin[1], F_SETFD, FD_CLOEXEC);
cmdlen = 1; /* null term */
while (*list)
cmdlen += strlen(*list++) + 1;
do_cmd_pid = spawn_child(args.list[0], args.list + 1, pin[0], pout[1], STDERR_FILENO, 0);
full_cmd = xmalloc(cmdlen);
full_cmd[0] = '\0';
list = args.list;
while (*list) {
strcat(full_cmd, *list++);
strcat(full_cmd, " ");
}
fcntl(pout[0], F_SETFD, FD_CLOEXEC);
fcntl(pin[1], F_SETFD, FD_CLOEXEC);
do_cmd_pid = spawn_child(full_cmd, pin[0], pout[1], STDERR_FILENO, 0);
free(full_cmd);
}
#else /* !WINDOWS */
do_cmd_pid = fork();
#endif /* !WINDOWS */
@ -382,26 +364,8 @@ do_cmd2(char *host, char *remuser, char *cmd, int fdin, int fdout)
addargs(&args, "%s", host);
addargs(&args, "%s", cmd);
{
char* full_cmd;
size_t cmdlen = 0;
char** list = args.list;
cmdlen = 1; /* null term */
while (*list)
cmdlen += strlen(*list++) + 1;
full_cmd = xmalloc(cmdlen);
full_cmd[0] = '\0';
list = args.list;
while (*list) {
strcat(full_cmd, *list++);
strcat(full_cmd, " ");
}
pid = spawn_child(full_cmd, fdin, fdout, STDERR_FILENO, 0);
free(full_cmd);
}
pid = spawn_child(args.list[0], args.list + 1, fdin, fdout, STDERR_FILENO, 0);
#else /* !WINDOWS */
pid = fork();
#endif /* !WINDOWS */
@ -1512,4 +1476,3 @@ lostconn(int signo)
else
exit(1);
}

View File

@ -183,7 +183,7 @@ static int
auth_input_request_forwarding(struct passwd * pw)
{
#ifdef WINDOWS
packet_send_debug("Agent forwarding not supported yet in Windows");
packet_send_debug("Agent forwarding not supported in Windows yet");
return 0;
#else /* !WINDOWS */
Channel *nc;
@ -2377,9 +2377,9 @@ static int
session_env_req(Session *s)
{
char *name, *val;
u_int name_chars, val_len, i;
u_int name_len, val_len, i;
name = packet_get_cstring(&name_chars);
name = packet_get_cstring(&name_len);
val = packet_get_cstring(&val_len);
packet_check_eom();

34
sftp.c
View File

@ -2163,12 +2163,11 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
free(dir);
}
interactive = !batchmode && isatty(STDIN_FILENO);
err = 0;
setvbuf(stdout, NULL, _IOLBF, 0);
setvbuf(infile, NULL, _IOLBF, 0);
interactive = !batchmode && isatty(STDIN_FILENO);
err = 0;
for (;;) {
char *cp;
@ -2256,32 +2255,11 @@ connect_to_server(char *path, char **args, int *in, int *out)
#ifdef WINDOWS
/* fork replacement on Windows */
{
size_t cmdlen = 0;
int i = 0;
char* full_cmd;
cmdlen = strlen(path) + 1;
for (i = 1; args[i]; i++)
cmdlen += strlen(args[i]) + 1 + 2;
full_cmd = xmalloc(cmdlen);
full_cmd[0] = '\0';
strcat(full_cmd, path);
for (i = 1; args[i]; i++) {
strcat(full_cmd, " \"");
strcat(full_cmd, args[i]);
strcat(full_cmd, "\"");
}
/* disable inheritance on local pipe ends*/
fcntl(pout[1], F_SETFD, FD_CLOEXEC);
fcntl(pin[0], F_SETFD, FD_CLOEXEC);
sshpid = spawn_child(full_cmd, c_in, c_out, STDERR_FILENO, 0);
free(full_cmd);
}
/* disable inheritance on local pipe ends*/
fcntl(pout[1], F_SETFD, FD_CLOEXEC);
fcntl(pin[0], F_SETFD, FD_CLOEXEC);
sshpid = spawn_child(path, args + 1, c_in, c_out, STDERR_FILENO, 0);
if (sshpid == -1)
#else /* !WINDOWS */
if ((sshpid = fork()) == -1)

View File

@ -492,12 +492,7 @@ main(int argc, char **argv)
OpenSSL_add_all_algorithms();
#endif
#ifdef WINDOWS
/* Min buffer size allowed in Windows is 2*/
setvbuf(stdout, NULL, _IOLBF, 2);
#else
setvbuf(stdout, NULL, _IOLBF, 0);
#endif
/* First, get a connection to the authentication agent. */
switch (r = ssh_get_authentication_socket(&agent_fd)) {

6
sshd.c
View File

@ -1317,7 +1317,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
continue;
}
pid = spawn_child(path_utf8, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, CREATE_NEW_PROCESS_GROUP);
pid = spawn_child(path_utf8, NULL, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, CREATE_NEW_PROCESS_GROUP);
free(path_utf8);
close(*newsock);
}
@ -1747,9 +1747,9 @@ main(int ac, char **av)
error("Could not connect to agent \"%s\": %s",
options.host_key_agent, ssh_err(r));
}
#ifdef WINDOWS /* Windows version always needs and has agent running */
#ifdef WINDOWS /* Windows version always needs and has agent running */
have_agent = 1;
#endif
#endif
for (i = 0; i < options.num_host_key_files; i++) {
if (options.host_key_files[i] == NULL)
continue;

View File

@ -53,57 +53,6 @@
# endif
#endif
#ifdef WINDOWS
/*
* Windows versions of pty_*. Some of them are NO-OPs and should go
* away when pty logic is refactored and abstracted out
*
*/
int
pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
{
/*
* Simple console screen implementation in Win32 to give a
* Unix like pty for interactive sessions
*/
*ttyfd = 0;
*ptyfd = 0;
strlcpy(namebuf, "console", namebuflen);
return 1;
}
void
pty_release(const char *tty) {
/* NO-OP */
}
void
pty_make_controlling_tty(int *ttyfd, const char *tty) {
/* NO-OP */
}
void
pty_change_window_size(int ptyfd, u_int row, u_int col,
u_int xpixel, u_int ypixel) {
COORD coord;
coord.X = col;
coord.Y = 9999;
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
void
pty_setowner(struct passwd *pw, const char *tty) {
/* NO-OP */
}
void
disconnect_controlling_tty(void) {
/* NO-OP */
}
#else
/*
* Allocates and opens a pty. Returns 0 if no pty could be allocated, or
* nonzero if a pty was successfully allocated. On success, open file
@ -303,4 +252,3 @@ disconnect_controlling_tty(void)
}
#endif /* TIOCNOTTY */
}
#endif

View File

@ -47,37 +47,6 @@
static struct termios _saved_tio;
static int _in_raw_mode = 0;
#ifdef WINDOWS
/*
* TTY raw mode routines for Windows
*/
int ConEnterRawMode(DWORD OutputHandle, BOOL fSmartInit);
int ConExitRawMode(void);
struct termios term_settings;
/*
* TODO - clean this up for Windows, ConInit should return previous terminal
* settings that need to be stored in term_settings
*/
struct termios *
get_saved_tio(void) {
memset(&term_settings, 0, sizeof(term_settings));
return &term_settings;
}
void
leave_raw_mode(int quiet) {
ConExitRawMode();
}
void
enter_raw_mode(int quiet) {
ConEnterRawMode(STD_OUTPUT_HANDLE, TRUE);
}
#else /* !WINDOWS */
struct termios *
get_saved_tio(void)
{
@ -125,4 +94,3 @@ enter_raw_mode(int quiet)
} else
_in_raw_mode = 1;
}
#endif /* !WINDOWS */

1
utf8.c
View File

@ -332,4 +332,3 @@ msetlocale(void)
/* We can handle this locale */
setlocale(LC_CTYPE, "");
}