Source snapshot from Powershell/openssh-portable:latestw_all

This commit is contained in:
Yanbing Wang 2017-06-30 18:36:09 -07:00
parent 944505e199
commit 7580216f04
49 changed files with 1521 additions and 1315 deletions

View File

@ -1,40 +1,39 @@
version: 0.0.16.0.{build} version: 0.0.17.0.{build}
image: Visual Studio 2015 image: Visual Studio 2015
branches: branches:
only: only:
- latestw_all - latestw_all
- latestw_all_openssl
init: init:
- ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
build_script: build_script:
- ps: | - ps: |
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1
Invoke-AppVeyorBuild Invoke-AppVeyorBuild
after_build: after_build:
- ps: | - ps: |
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1
Install-OpenSSH Install-OpenSSH
before_test: before_test:
- ps: | - ps: |
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1
Setup-OpenSSHTestEnvironment -Quiet Set-OpenSSHTestEnvironment -Confirm:$false
test_script: test_script:
- ps: | - ps: |
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1
Run-OpenSSHTests Invoke-OpenSSHTests
after_test: after_test:
- ps: | - ps: |
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1
Upload-OpenSSHTestResults Publish-OpenSSHTestResults
on_finish: on_finish:
- ps: | - ps: |
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1
Publish-Artifact Publish-Artifact

View File

@ -226,38 +226,45 @@ sys_auth_passwd(Authctxt *authctxt, const char *password)
#elif defined(WINDOWS) #elif defined(WINDOWS)
/* /*
* Authenticate on Windows - Pass credentials to ssh-agent and retrieve token * Authenticate on Windows - Call LogonUser and retrieve user token
* upon successful authentication
* TODO - password is sent in plain text over IPC. Consider implications.
*/ */
int sys_auth_passwd(Authctxt *authctxt, const char *password) int sys_auth_passwd(Authctxt *authctxt, const char *password)
{ {
struct sshbuf *msg = NULL; wchar_t *user_utf16 = NULL, *udom_utf16 = NULL, *pwd_utf16 = NULL, *tmp;
size_t blen = 0; HANDLE token = NULL;
DWORD token = 0;
extern int auth_sock;
int r = 0; int r = 0;
int ssh_request_reply(int, struct sshbuf *, struct sshbuf *);
msg = sshbuf_new(); if ((user_utf16 = utf8_to_utf16(authctxt->pw->pw_name)) == NULL ||
if (!msg) (pwd_utf16 = utf8_to_utf16(password)) == NULL) {
fatal("%s: out of memory", __func__); fatal("out of memory");
if (sshbuf_put_u8(msg, SSH_AGENT_AUTHENTICATE) != 0 ||
sshbuf_put_cstring(msg, PASSWD_AUTH_REQUEST) != 0 ||
sshbuf_put_cstring(msg, authctxt->pw->pw_name) != 0 ||
sshbuf_put_cstring(msg, password) != 0 ||
ssh_request_reply(auth_sock, msg, msg) != 0 ||
sshbuf_get_u32(msg, &token) != 0) {
debug("auth agent did not authorize client %s", authctxt->user);
r = 0;
goto done; goto done;
} }
authctxt->methoddata = (void*)(INT_PTR)token;
if ((tmp = wcschr(user_utf16, L'@')) != NULL) {
udom_utf16 = tmp + 1;
*tmp = L'\0';
}
if (LogonUserW(user_utf16, udom_utf16, pwd_utf16, LOGON32_LOGON_NETWORK_CLEARTEXT,
LOGON32_PROVIDER_DEFAULT, &token) == FALSE) {
if (GetLastError() == ERROR_PASSWORD_MUST_CHANGE)
/*
* TODO - need to add support to force password change
* by sending back SSH_MSG_USERAUTH_PASSWD_CHANGEREQ
*/
error("password for user %s has expired", authctxt->pw->pw_name);
else
debug("failed to logon user: %ls domain: %ls error:%d", user_utf16, udom_utf16, GetLastError());
goto done;
}
authctxt->auth_token = (void*)(INT_PTR)token;
r = 1; r = 1;
done: done:
if (msg) if (user_utf16)
sshbuf_free(msg); free(user_utf16);
if (pwd_utf16)
SecureZeroMemory(pwd_utf16, sizeof(wchar_t) * wcslen(pwd_utf16));
return r; return r;
} }
#endif /* WINDOWS */ #endif /* WINDOWS */

9
auth.c
View File

@ -405,6 +405,13 @@ expand_authorized_keys(const char *filename, struct passwd *pw)
file = percent_expand(filename, "h", pw->pw_dir, file = percent_expand(filename, "h", pw->pw_dir,
"u", pw->pw_name, (char *)NULL); "u", pw->pw_name, (char *)NULL);
#ifdef WINDOWS
/* Return if the path is absolute. If not, prepend the '%h\\' */
if ((strlen(file) > 1) && (file[1] == ':'))
return (file);
i = snprintf(ret, sizeof(ret), "%s\\%s", pw->pw_dir, file);
#else
/* /*
* Ensure that filename starts anchored. If not, be backward * Ensure that filename starts anchored. If not, be backward
* compatible and prepend the '%h/' * compatible and prepend the '%h/'
@ -413,6 +420,8 @@ expand_authorized_keys(const char *filename, struct passwd *pw)
return (file); return (file);
i = snprintf(ret, sizeof(ret), "%s/%s", pw->pw_dir, file); i = snprintf(ret, sizeof(ret), "%s/%s", pw->pw_dir, file);
#endif // WINDOWS
if (i < 0 || (size_t)i >= sizeof(ret)) if (i < 0 || (size_t)i >= sizeof(ret))
fatal("expand_authorized_keys: path too long"); fatal("expand_authorized_keys: path too long");
free(file); free(file);

4
auth.h
View File

@ -78,7 +78,9 @@ struct Authctxt {
#endif #endif
Buffer *loginmsg; Buffer *loginmsg;
void *methoddata; void *methoddata;
#ifdef WINDOWS
void *auth_token;
#endif
struct sshkey **prev_userkeys; struct sshkey **prev_userkeys;
u_int nprev_userkeys; u_int nprev_userkeys;
}; };

View File

@ -200,54 +200,14 @@ userauth_pubkey(struct ssh *ssh)
/* test for correct signature */ /* test for correct signature */
authenticated = 0; authenticated = 0;
#ifdef WINDOWS
/* Pass key challenge material to ssh-agent to retrieve token upon successful authentication */
{
struct sshbuf *msg = NULL;
u_char *blob = NULL;
size_t blen = 0;
DWORD token = 0;
extern int auth_sock;
int r = 0;
int ssh_request_reply(int , struct sshbuf *, struct sshbuf *);
while (1) {
msg = sshbuf_new();
if (!msg)
fatal("%s: out of memory", __func__);
if ((r = sshbuf_put_u8(msg, SSH_AGENT_AUTHENTICATE)) != 0 ||
(r = sshbuf_put_cstring(msg, PUBKEY_AUTH_REQUEST)) != 0 ||
(r = sshkey_to_blob(key, &blob, &blen)) != 0 ||
(r = sshbuf_put_string(msg, blob, blen)) != 0 ||
(r = sshbuf_put_cstring(msg, authctxt->pw->pw_name)) != 0 ||
(r = sshbuf_put_string(msg, sig, slen)) != 0 ||
(r = sshbuf_put_string(msg, sshbuf_ptr(b), sshbuf_len(b))) != 0 ||
(r = ssh_request_reply(auth_sock, msg, msg)) != 0 ||
(r = sshbuf_get_u32(msg, &token)) != 0) {
debug("auth agent did not authorize client %s", authctxt->user);
break;
}
debug3("auth agent authenticated %s", authctxt->user);
break;
}
if (blob)
free(blob);
if (msg)
sshbuf_free(msg);
if (token) {
authenticated = 1;
authctxt->methoddata = (void*)(INT_PTR)token;
}
}
#else /* !WINDOWS */
if (PRIVSEP(user_key_allowed(authctxt->pw, key, 1)) && if (PRIVSEP(user_key_allowed(authctxt->pw, key, 1)) &&
#ifdef WINDOWS
(authctxt->auth_token = mm_auth_pubkey(authctxt->pw->pw_name,
key, sig, slen, b)) != NULL) {
#else
PRIVSEP(sshkey_verify(key, sig, slen, sshbuf_ptr(b), PRIVSEP(sshkey_verify(key, sig, slen, sshbuf_ptr(b),
sshbuf_len(b), ssh->compat)) == 0) { sshbuf_len(b), ssh->compat)) == 0) {
#endif
authenticated = 1; authenticated = 1;
/* Record the successful key to prevent reuse */ /* Record the successful key to prevent reuse */
auth2_record_userkey(authctxt, key); auth2_record_userkey(authctxt, key);
@ -255,7 +215,6 @@ userauth_pubkey(struct ssh *ssh)
} }
sshbuf_free(b); sshbuf_free(b);
free(sig); free(sig);
#endif /* !WINDOWS */
} else { } else {
debug("%s: test whether pkalg/pkblob are acceptable for %s %s", debug("%s: test whether pkalg/pkblob are acceptable for %s %s",

View File

@ -43,6 +43,7 @@ int ssh_agent_sign(int sock, struct sshkey *key,
const u_char *data, size_t datalen, const char *alg, u_int compat); const u_char *data, size_t datalen, const char *alg, u_int compat);
/* Messages for the authentication agent connection. */ /* Messages for the authentication agent connection. */
/* Message Id 0 is reserved */
#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1 #define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
#define SSH_AGENT_RSA_IDENTITIES_ANSWER 2 #define SSH_AGENT_RSA_IDENTITIES_ANSWER 2
#define SSH_AGENTC_RSA_CHALLENGE 3 #define SSH_AGENTC_RSA_CHALLENGE 3
@ -88,12 +89,4 @@ int ssh_agent_sign(int sock, struct sshkey *key,
#define SSH_AGENT_RSA_SHA2_256 0x02 #define SSH_AGENT_RSA_SHA2_256 0x02
#define SSH_AGENT_RSA_SHA2_512 0x04 #define SSH_AGENT_RSA_SHA2_512 0x04
/*
* Following are used in Windows implementation
* ssh-agent in Windows also serves user authentication
*/
#define SSH_AGENT_AUTHENTICATE 200
#define PUBKEY_AUTH_REQUEST "pubkey"
#define PASSWD_AUTH_REQUEST "password"
#endif /* AUTHFD_H */ #endif /* AUTHFD_H */

View File

@ -1,12 +1,14 @@
$ErrorActionPreference = 'Stop' $ErrorActionPreference = 'Stop'
Import-Module $PSScriptRoot\OpenSSHCommonUtils.psm1 -Force -DisableNameChecking Set-StrictMode -Version 2.0
Import-Module $PSScriptRoot\OpenSSHBuildHelper.psm1 -Force -DisableNameChecking If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
Import-Module $PSScriptRoot\OpenSSHTestHelper.psm1 -Force -DisableNameChecking Import-Module $PSScriptRoot\OpenSSHCommonUtils.psm1 -Force
Import-Module $PSScriptRoot\OpenSSHBuildHelper.psm1 -Force
Import-Module $PSScriptRoot\OpenSSHTestHelper.psm1 -Force
$repoRoot = Get-RepositoryRoot $repoRoot = Get-RepositoryRoot
$script:messageFile = join-path $repoRoot.FullName "BuildMessage.log" $script:messageFile = join-path $repoRoot.FullName "BuildMessage.log"
# Sets a build variable # Write the build message
Function Write-BuildMessage Function Write-BuildMessage
{ {
param( param(
@ -78,11 +80,10 @@ function Invoke-AppVeyorFull
$env:APPVEYOR_SCHEDULED_BUILD = 'True' $env:APPVEYOR_SCHEDULED_BUILD = 'True'
} }
try { try {
Set-OpenSSHTestParams
Invoke-AppVeyorBuild Invoke-AppVeyorBuild
Install-OpenSSH Install-OpenSSH
Setup-OpenSSHTestEnvironment Set-OpenSSHTestEnvironment -confirm:$false
Run-OpenSSHTests Invoke-OpenSSHTests
Publish-Artifact Publish-Artifact
} }
finally { finally {
@ -97,8 +98,8 @@ function Invoke-AppVeyorFull
function Invoke-AppVeyorBuild function Invoke-AppVeyorBuild
{ {
Set-BuildVariable TestPassed True Set-BuildVariable TestPassed True
Build-OpenSSH -Configuration Release -NativeHostArch x64 Start-OpenSSHBuild -Configuration Release -NativeHostArch x64
Build-OpenSSH -Configuration Debug -NativeHostArch x86 Start-OpenSSHBuild -Configuration Release -NativeHostArch x86
Write-BuildMessage -Message "OpenSSH binaries build success!" -Category Information Write-BuildMessage -Message "OpenSSH binaries build success!" -Category Information
} }
@ -136,6 +137,100 @@ function Add-BuildLog
} }
} }
<#
.Synopsis
Deploy all required files to a location and install the binaries
#>
function Install-OpenSSH
{
[CmdletBinding()]
param
(
[ValidateSet('Debug', 'Release')]
[string]$Configuration = "Release",
[ValidateSet('x86', 'x64', '')]
[string]$NativeHostArch = "",
[string]$OpenSSHDir = "$env:SystemDrive\OpenSSH"
)
if ($NativeHostArch -eq "")
{
$NativeHostArch = 'x64'
if ($env:PROCESSOR_ARCHITECTURE -eq 'x86') {
$NativeHostArch = 'x86'
}
}
Start-OpenSSHPackage -NativeHostArch $NativeHostArch -Configuration $Configuration -DestinationPath $OpenSSHDir
Push-Location $OpenSSHDir
& "$OpenSSHDir\install-sshd.ps1"
& "$OpenSSHDir\ssh-keygen.exe" -A
& "$OpenSSHDir\FixHostFilePermissions.ps1" -Confirm:$false
#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
Pop-Location
Write-BuildMessage -Message "OpenSSH installed!" -Category Information
}
<#
.Synopsis
uninstalled sshd
#>
function UnInstall-OpenSSH
{
[CmdletBinding()]
param
(
[string]$OpenSSHDir = "$env:SystemDrive\OpenSSH"
)
if (-not (Test-Path $OpenSSHDir -PathType Container))
{
return
}
Push-Location $OpenSSHDir
if((Get-Service ssh-agent -ErrorAction SilentlyContinue) -ne $null) {
Stop-Service ssh-agent -Force
}
& "$OpenSSHDir\uninstall-sshd.ps1"
$machinePath = [Environment]::GetEnvironmentVariable('Path', 'MACHINE')
$newMachineEnvironmentPath = $machinePath
if ($machinePath.ToLower().Contains($OpenSSHDir.ToLower()))
{
$newMachineEnvironmentPath = $newMachineEnvironmentPath.Replace("$OpenSSHDir;", '')
$env:Path = $env:Path.Replace("$OpenSSHDir;", '')
}
if ($newMachineEnvironmentPath -ne $machinePath)
{
[Environment]::SetEnvironmentVariable('Path', $newMachineEnvironmentPath, 'MACHINE')
}
Pop-Location
Remove-Item -Path $OpenSSHDir -Recurse -Force -ErrorAction SilentlyContinue
}
<# <#
.Synopsis .Synopsis
Publishes package build artifacts. Publishes package build artifacts.
@ -170,11 +265,11 @@ function Add-Artifact
function Publish-Artifact function Publish-Artifact
{ {
Write-Host -ForegroundColor Yellow "Publishing project artifacts" Write-Host -ForegroundColor Yellow "Publishing project artifacts"
[System.Collections.ArrayList] $artifacts = [System.Collections.ArrayList]::new() [System.Collections.ArrayList] $artifacts = new-object System.Collections.ArrayList
# Get the build.log file for each build configuration # Get the build.log file for each build configuration
Add-BuildLog -artifacts $artifacts -buildLog (Get-BuildLogFile -root $repoRoot.FullName -Configuration Release -NativeHostArch x64) Add-BuildLog -artifacts $artifacts -buildLog (Get-BuildLogFile -root $repoRoot.FullName -Configuration Release -NativeHostArch x64)
Add-BuildLog -artifacts $artifacts -buildLog (Get-BuildLogFile -root $repoRoot.FullName -Configuration Debug -NativeHostArch x86) Add-BuildLog -artifacts $artifacts -buildLog (Get-BuildLogFile -root $repoRoot.FullName -Configuration Release -NativeHostArch x86)
if($Global:OpenSSHTestInfo) if($Global:OpenSSHTestInfo)
{ {
@ -186,7 +281,6 @@ function Publish-Artifact
foreach ($artifact in $artifacts) foreach ($artifact in $artifacts)
{ {
Write-Host "Publishing $artifact as Appveyor artifact" Write-Host "Publishing $artifact as Appveyor artifact"
# NOTE: attempt to publish subsequent artifacts even if the current one fails
Push-AppveyorArtifact $artifact -ErrorAction Continue Push-AppveyorArtifact $artifact -ErrorAction Continue
} }
} }
@ -195,10 +289,10 @@ function Publish-Artifact
.Synopsis .Synopsis
Runs the tests for this repo Runs the tests for this repo
#> #>
function Run-OpenSSHTests function Invoke-OpenSSHTests
{ {
Write-Host "Start running unit tests" Write-Host "Start running unit tests"
$unitTestFailed = Run-OpenSSHUnitTest $unitTestFailed = Invoke-OpenSSHUnitTest
if($unitTestFailed) if($unitTestFailed)
{ {
@ -212,14 +306,14 @@ function Run-OpenSSHTests
Write-BuildMessage -Message "All Unit tests passed!" -Category Information Write-BuildMessage -Message "All Unit tests passed!" -Category Information
} }
# Run all E2E tests. # Run all E2E tests.
Run-OpenSSHE2ETest Invoke-OpenSSHE2ETest
if (($OpenSSHTestInfo -eq $null) -or (-not (Test-Path $OpenSSHTestInfo["E2ETestResultsFile"]))) if (($OpenSSHTestInfo -eq $null) -or (-not (Test-Path $OpenSSHTestInfo["E2ETestResultsFile"])))
{ {
Write-Warning "Test result file $OpenSSHTestInfo["E2ETestResultsFile"] not found after tests." Write-Warning "Test result file $OpenSSHTestInfo["E2ETestResultsFile"] not found after tests."
Write-BuildMessage -Message "Test result file $OpenSSHTestInfo["E2ETestResultsFile"] not found after tests." -Category Error Write-BuildMessage -Message "Test result file $OpenSSHTestInfo["E2ETestResultsFile"] not found after tests." -Category Error
Set-BuildVariable TestPassed False Set-BuildVariable TestPassed False
} }
$xml = [xml](Get-Content -raw $OpenSSHTestInfo["E2ETestResultsFile"]) $xml = [xml](Get-Content $OpenSSHTestInfo["E2ETestResultsFile"] | out-string)
if ([int]$xml.'test-results'.failures -gt 0) if ([int]$xml.'test-results'.failures -gt 0)
{ {
$errorMessage = "$($xml.'test-results'.failures) tests in regress\pesterTests failed. Detail test log is at $($OpenSSHTestInfo["E2ETestResultsFile"])." $errorMessage = "$($xml.'test-results'.failures) tests in regress\pesterTests failed. Detail test log is at $($OpenSSHTestInfo["E2ETestResultsFile"])."
@ -239,7 +333,7 @@ function Run-OpenSSHTests
.Synopsis .Synopsis
upload OpenSSH pester test results. upload OpenSSH pester test results.
#> #>
function Upload-OpenSSHTestResults function Publish-OpenSSHTestResults
{ {
if ($env:APPVEYOR_JOB_ID) if ($env:APPVEYOR_JOB_ID)
{ {

View File

@ -1,7 +1,7 @@
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")] [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
param () param ()
Set-StrictMode -Version 2.0 Set-StrictMode -Version 2.0
If (!(Test-Path variable:PSScriptRoot)) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Definition} If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
Import-Module $PSScriptRoot\OpenSSHUtils -Force Import-Module $PSScriptRoot\OpenSSHUtils -Force
#check sshd config file #check sshd config file

View File

@ -1,7 +1,7 @@
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")] [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
param () param ()
Set-StrictMode -Version 2.0 Set-StrictMode -Version 2.0
If (!(Test-Path variable:PSScriptRoot)) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Definition} If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
Import-Module $PSScriptRoot\OpenSSHUtils -Force Import-Module $PSScriptRoot\OpenSSHUtils -Force

View File

@ -1,7 +1,7 @@
Set-StrictMode -Version Latest Set-StrictMode -Version 2.0
If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
Import-Module $PSScriptRoot\OpenSSHCommonUtils.psm1 -Force
Import-Module $PSScriptRoot\OpenSSHCommonUtils.psm1 -force -DisableNameChecking
[string] $script:platform = $env:PROCESSOR_ARCHITECTURE
[string] $script:vcPath = $null [string] $script:vcPath = $null
[System.IO.DirectoryInfo] $script:OpenSSHRoot = $null [System.IO.DirectoryInfo] $script:OpenSSHRoot = $null
[System.IO.DirectoryInfo] $script:gitRoot = $null [System.IO.DirectoryInfo] $script:gitRoot = $null
@ -83,7 +83,7 @@ function Write-BuildMsg
[switch] $Silent [switch] $Silent
) )
if ($AsVerbose) if($PSBoundParameters.ContainsKey("AsVerbose"))
{ {
if ($script:Verbose) if ($script:Verbose)
{ {
@ -96,17 +96,24 @@ function Write-BuildMsg
return return
} }
if ($AsInfo) if($PSBoundParameters.ContainsKey("AsInfo"))
{ {
Write-Log -Message "INFO: $message" Write-Log -Message "INFO: $message"
if (-not $Silent) if (-not $Silent)
{ {
Write-Information -MessageData $message -InformationAction Continue if(Get-Command "Write-Information" -ErrorAction SilentlyContinue )
{
Write-Information -MessageData $message -InformationAction Continue
}
else
{
Write-Verbose -Message $message -Verbose
}
} }
return return
} }
if ($AsWarning) if($PSBoundParameters.ContainsKey("AsWarning"))
{ {
Write-Log -Message "WARNING: $message" Write-Log -Message "WARNING: $message"
if (-not $Silent) if (-not $Silent)
@ -116,7 +123,7 @@ function Write-BuildMsg
return return
} }
if ($AsError) if($PSBoundParameters.ContainsKey("AsError"))
{ {
Write-Log -Message "ERROR: $message" Write-Log -Message "ERROR: $message"
if (-not $Silent) if (-not $Silent)
@ -137,8 +144,6 @@ function Write-BuildMsg
function Start-OpenSSHBootstrap function Start-OpenSSHBootstrap
{ {
[bool] $silent = -not $script:Verbose [bool] $silent = -not $script:Verbose
Set-StrictMode -Version Latest
Write-BuildMsg -AsInfo -Message "Checking tools and dependencies" -Silent:$silent Write-BuildMsg -AsInfo -Message "Checking tools and dependencies" -Silent:$silent
$machinePath = [Environment]::GetEnvironmentVariable('Path', 'MACHINE') $machinePath = [Environment]::GetEnvironmentVariable('Path', 'MACHINE')
@ -146,7 +151,7 @@ function Start-OpenSSHBootstrap
# Install chocolatey # Install chocolatey
$chocolateyPath = "$env:AllUsersProfile\chocolatey\bin" $chocolateyPath = "$env:AllUsersProfile\chocolatey\bin"
if(Get-Command "choco" -ErrorAction SilentlyContinue) if(Get-Command choco -ErrorAction SilentlyContinue)
{ {
Write-BuildMsg -AsVerbose -Message "Chocolatey is already installed. Skipping installation." -Silent:$silent Write-BuildMsg -AsVerbose -Message "Chocolatey is already installed. Skipping installation." -Silent:$silent
} }
@ -156,12 +161,30 @@ function Start-OpenSSHBootstrap
Invoke-Expression ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1')) 2>&1 >> $script:BuildLogFile Invoke-Expression ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1')) 2>&1 >> $script:BuildLogFile
} }
if (-not ($machinePath.ToLower().Contains($chocolateyPath.ToLower())))
{
Write-BuildMsg -AsVerbose -Message "Adding $chocolateyPath to Path environment variable" -Silent:$silent
$newMachineEnvironmentPath = "$chocolateyPath;$newMachineEnvironmentPath"
if(-not ($env:Path.ToLower().Contains($chocolateyPath.ToLower())))
{
$env:Path = "$chocolateyPath;$env:Path"
}
}
else
{
Write-BuildMsg -AsVerbose -Message "$chocolateyPath already present in Path environment variable" -Silent:$silent
}
# Add git\cmd to the path # Add git\cmd to the path
$gitCmdPath = "$env:ProgramFiles\git\cmd" $gitCmdPath = "$env:ProgramFiles\git\cmd"
if (-not ($machinePath.ToLower().Contains($gitCmdPath.ToLower()))) if (-not ($machinePath.ToLower().Contains($gitCmdPath.ToLower())))
{ {
Write-BuildMsg -AsVerbose -Message "Adding $gitCmdPath to Path environment variable" -Silent:$silent Write-BuildMsg -AsVerbose -Message "Adding $gitCmdPath to Path environment variable" -Silent:$silent
$newMachineEnvironmentPath = "$gitCmdPath;$newMachineEnvironmentPath" $newMachineEnvironmentPath = "$gitCmdPath;$newMachineEnvironmentPath"
if(-not ($env:Path.ToLower().Contains($gitCmdPath.ToLower())))
{
$env:Path = "$gitCmdPath;$env:Path"
}
} }
else else
{ {
@ -169,7 +192,7 @@ function Start-OpenSSHBootstrap
} }
$nativeMSBuildPath = "${env:ProgramFiles(x86)}\MSBuild\14.0\bin" $nativeMSBuildPath = "${env:ProgramFiles(x86)}\MSBuild\14.0\bin"
if($script:platform -ieq "AMD64") if($env:PROCESSOR_ARCHITECTURE -ieq "AMD64")
{ {
$nativeMSBuildPath += "\amd64" $nativeMSBuildPath += "\amd64"
} }
@ -178,7 +201,10 @@ function Start-OpenSSHBootstrap
{ {
Write-BuildMsg -AsVerbose -Message "Adding $nativeMSBuildPath to Path environment variable" -Silent:$silent Write-BuildMsg -AsVerbose -Message "Adding $nativeMSBuildPath to Path environment variable" -Silent:$silent
$newMachineEnvironmentPath += ";$nativeMSBuildPath" $newMachineEnvironmentPath += ";$nativeMSBuildPath"
$env:Path += ";$nativeMSBuildPath" if(-not ($env:Path.ToLower().Contains($nativeMSBuildPath.ToLower())))
{
$env:Path += ";$nativeMSBuildPath"
}
} }
else else
{ {
@ -191,42 +217,53 @@ function Start-OpenSSHBootstrap
[Environment]::SetEnvironmentVariable('Path', $newMachineEnvironmentPath, 'MACHINE') [Environment]::SetEnvironmentVariable('Path', $newMachineEnvironmentPath, 'MACHINE')
} }
# Install Visual Studio 2015 Community $VCTargetsPath = "${env:ProgramFiles(x86)}\MSBuild\Microsoft.Cpp\v4.0\V140"
$packageName = "VisualStudio2015Community" if([Environment]::GetEnvironmentVariable('VCTargetsPath', 'MACHINE') -eq $null)
$VSPackageInstalled = Get-ItemProperty "HKLM:\software\WOW6432Node\Microsoft\VisualStudio\14.0\setup\vs" -ErrorAction SilentlyContinue
if ($null -eq $VSPackageInstalled)
{ {
Write-BuildMsg -AsInfo -Message "$packageName not present. Installing $packageName." [Environment]::SetEnvironmentVariable('VCTargetsPath', $VCTargetsPath, 'MACHINE')
$adminFilePath = "$script:OpenSSHRoot\contrib\win32\openssh\VSWithBuildTools.xml"
choco install $packageName -packageParameters "--AdminFile $adminFilePath" -y --force --limitoutput --execution-timeout 10000 2>&1 >> $script:BuildLogFile
} }
else if ($env:VCTargetsPath -eq $null)
{ {
Write-BuildMsg -AsVerbose -Message "$packageName present. Skipping installation." -Silent:$silent $env:VCTargetsPath = $VCTargetsPath
} }
# Install Windows 8.1 SDK $vcVars = "${env:ProgramFiles(x86)}\Microsoft Visual Studio 14.0\Common7\Tools\vsvars32.bat"
$packageName = "windows-sdk-8.1"
$sdkPath = "${env:ProgramFiles(x86)}\Windows Kits\8.1\bin\x86\register_app.vbs" $sdkPath = "${env:ProgramFiles(x86)}\Windows Kits\8.1\bin\x86\register_app.vbs"
$packageName = "vcbuildtools"
if (-not (Test-Path -Path $sdkPath)) If ((-not (Test-Path $nativeMSBuildPath)) -or (-not (Test-Path $VcVars)) -or (-not (Test-Path $sdkPath))) {
{ Write-BuildMsg -AsInfo -Message "$packageName not present. Installing $packageName ..."
Write-BuildMsg -AsInfo -Message "Windows 8.1 SDK not present. Installing $packageName." choco install $packageName -ia "/InstallSelectableItems VisualCppBuildTools_ATLMFC_SDK;VisualCppBuildTools_NETFX_SDK;Win81SDK_CppBuildSKUV1" -y --force --limitoutput --execution-timeout 10000 2>&1 >> $script:BuildLogFile
choco install $packageName -y --limitoutput --force 2>&1 >> $script:BuildLogFile $errorCode = $LASTEXITCODE
if ($errorCode -eq 3010)
{
Write-Host "The recent package changes indicate a reboot is necessary. please reboot the machine, open a new powershell window and call Start-SSHBuild or Start-OpenSSHBootstrap again." -ForegroundColor Black -BackgroundColor Yellow
Do {
$input = Read-Host -Prompt "Reboot the machine? [Yes] Y; [No] N (default is `"Y`")"
if([string]::IsNullOrEmpty($input))
{
$input = 'Y'
}
} until ($input -match "^(y(es)?|N(o)?)$")
[string]$ret = $Matches[0]
if ($ret.ToLower().Startswith('y'))
{
Write-BuildMsg -AsWarning -Message "restarting machine ..."
Restart-Computer -Force
exit
}
else
{
Write-BuildMsg -AsError -ErrorAction Stop -Message "User choose not to restart the machine to apply the changes."
}
}
else
{
Write-BuildMsg -AsError -ErrorAction Stop -Message "$packageName installation failed with error code $errorCode"
}
} }
else else
{ {
Write-BuildMsg -AsInfo -Message "$packageName present. Skipping installation." -Silent:$silent Write-BuildMsg -AsVerbose -Message 'VC++ 2015 Build Tools already present.'
}
# Require restarting PowerShell session
if ($null -eq $VSPackageInstalled)
{
Write-Host "To apply changes, please close this PowerShell window, open a new one and call Start-SSHBuild or Start-DscBootstrap again." -ForegroundColor Black -BackgroundColor Yellow
Write-Host -NoNewLine 'Press any key to close this PowerShell window...' -ForegroundColor Black -BackgroundColor Yellow
$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
exit
} }
# Ensure the VS C toolset is installed # Ensure the VS C toolset is installed
@ -241,11 +278,11 @@ function Start-OpenSSHBootstrap
Write-BuildMsg -AsVerbose -Message "vcPath: $script:vcPath" -Silent:$silent Write-BuildMsg -AsVerbose -Message "vcPath: $script:vcPath" -Silent:$silent
if ((Test-Path -Path "$script:vcPath\vcvarsall.bat") -eq $false) if ((Test-Path -Path "$script:vcPath\vcvarsall.bat") -eq $false)
{ {
Write-BuildMsg -AsError -ErrorAction Stop -Message "Could not find Visual Studio vcvarsall.bat at$script:vcPath, which means some required develop kits are missing on the machine." Write-BuildMsg -AsError -ErrorAction Stop -Message "Could not find Visual Studio vcvarsall.bat at $script:vcPath, which means some required develop kits are missing on the machine."
} }
} }
function Clone-Win32OpenSSH function Get-Win32OpenSSHRepo
{ {
[bool] $silent = -not $script:Verbose [bool] $silent = -not $script:Verbose
@ -264,7 +301,7 @@ function Clone-Win32OpenSSH
Pop-Location Pop-Location
} }
function Delete-Win32OpenSSH function Remove-Win32OpenSSHRepo
{ {
Remove-Item -Path $script:win32OpenSSHPath -Recurse -Force -ErrorAction SilentlyContinue Remove-Item -Path $script:win32OpenSSHPath -Recurse -Force -ErrorAction SilentlyContinue
} }
@ -282,7 +319,7 @@ function Copy-LibreSSLSDK
} }
} }
function Package-OpenSSH function Start-OpenSSHPackage
{ {
[CmdletBinding(SupportsShouldProcess=$false)] [CmdletBinding(SupportsShouldProcess=$false)]
param param
@ -290,7 +327,7 @@ function Package-OpenSSH
[ValidateSet('x86', 'x64')] [ValidateSet('x86', 'x64')]
[string]$NativeHostArch = "x64", [string]$NativeHostArch = "x64",
[ValidateSet('Debug', 'Release', '')] [ValidateSet('Debug', 'Release')]
[string]$Configuration = "Release", [string]$Configuration = "Release",
# Copy payload to DestinationPath instead of packaging # Copy payload to DestinationPath instead of packaging
@ -315,7 +352,7 @@ function Package-OpenSSH
if ($NativeHostArch -ieq 'x86') { if ($NativeHostArch -ieq 'x86') {
$packageName = "OpenSSH-Win32" $packageName = "OpenSSH-Win32"
} }
while((($service = Get-Service ssh-agent -ErrorAction Ignore) -ne $null) -and ($service.Status -ine 'Stopped')) while((($service = Get-Service ssh-agent -ErrorAction SilentlyContinue) -ne $null) -and ($service.Status -ine 'Stopped'))
{ {
Stop-Service ssh-agent -Force Stop-Service ssh-agent -Force
#sleep to wait the servicelog file write #sleep to wait the servicelog file write
@ -361,25 +398,38 @@ function Package-OpenSSH
} }
else { else {
Remove-Item ($packageDir + '.zip') -Force -ErrorAction SilentlyContinue Remove-Item ($packageDir + '.zip') -Force -ErrorAction SilentlyContinue
Compress-Archive -Path $packageDir -DestinationPath ($packageDir + '.zip') if(get-command Compress-Archive -ErrorAction SilentlyContinue)
Write-BuildMsg -AsInfo -Message "Packaged Payload - '$packageDir'.zip" {
Compress-Archive -Path $packageDir -DestinationPath ($packageDir + '.zip')
Write-BuildMsg -AsInfo -Message "Packaged Payload - '$packageDir.zip'"
}
else
{
Write-BuildMsg -AsInfo -Message "Packaged Payload not compressed."
}
} }
Remove-Item $packageDir -Recurse -Force -ErrorAction SilentlyContinue Remove-Item $packageDir -Recurse -Force -ErrorAction SilentlyContinue
if ($DestinationPath -ne "") { if ($DestinationPath -ne "") {
Copy-Item -Path $symbolsDir\* -Destination $DestinationPath -Force -Recurse Copy-Item -Path $symbolsDir\* -Destination $DestinationPath -Force -Recurse
Write-BuildMsg -AsInfo -Message "Copied symbols to $DestinationPath" Write-BuildMsg -AsInfo -Message "Copied symbols to $DestinationPath"
} }
else { else {
Remove-Item ($symbolsDir + '.zip') -Force -ErrorAction SilentlyContinue Remove-Item ($symbolsDir + '.zip') -Force -ErrorAction SilentlyContinue
Compress-Archive -Path $symbolsDir -DestinationPath ($symbolsDir + '.zip') if(get-command Compress-Archive -ErrorAction SilentlyContinue)
Write-BuildMsg -AsInfo -Message "Packaged Symbols - '$symbolsDir'.zip" {
Compress-Archive -Path $symbolsDir -DestinationPath ($symbolsDir + '.zip')
Write-BuildMsg -AsInfo -Message "Packaged Symbols - '$symbolsDir.zip'"
}
else
{
Write-BuildMsg -AsInfo -Message "Packaged Symbols not compressed."
}
} }
Remove-Item $symbolsDir -Recurse -Force -ErrorAction SilentlyContinue Remove-Item $symbolsDir -Recurse -Force -ErrorAction SilentlyContinue
} }
function Build-OpenSSH function Start-OpenSSHBuild
{ {
[CmdletBinding(SupportsShouldProcess=$false)] [CmdletBinding(SupportsShouldProcess=$false)]
param param
@ -387,12 +437,11 @@ function Build-OpenSSH
[ValidateSet('x86', 'x64')] [ValidateSet('x86', 'x64')]
[string]$NativeHostArch = "x64", [string]$NativeHostArch = "x64",
[ValidateSet('Debug', 'Release', '')] [ValidateSet('Debug', 'Release')]
[string]$Configuration = "Release", [string]$Configuration = "Release",
[switch]$NoOpenSSL [switch]$NoOpenSSL
) )
Set-StrictMode -Version Latest
$script:BuildLogFile = $null $script:BuildLogFile = $null
[System.IO.DirectoryInfo] $repositoryRoot = Get-RepositoryRoot [System.IO.DirectoryInfo] $repositoryRoot = Get-RepositoryRoot
@ -420,9 +469,9 @@ function Build-OpenSSH
$script:win32OpenSSHPath = join-path $script:gitRoot "Win32-OpenSSH" $script:win32OpenSSHPath = join-path $script:gitRoot "Win32-OpenSSH"
if (-not (Test-Path (Join-Path $PSScriptRoot LibreSSLSDK))) if (-not (Test-Path (Join-Path $PSScriptRoot LibreSSLSDK)))
{ {
Clone-Win32OpenSSH Get-Win32OpenSSHRepo
Copy-LibreSSLSDK Copy-LibreSSLSDK
Delete-Win32OpenSSH Remove-Win32OpenSSHRepo
} }
if ($NoOpenSSL) if ($NoOpenSSL)
@ -465,7 +514,7 @@ function Get-BuildLogFile
[ValidateSet('x86', 'x64')] [ValidateSet('x86', 'x64')]
[string]$NativeHostArch = "x64", [string]$NativeHostArch = "x64",
[ValidateSet('Debug', 'Release', '')] [ValidateSet('Debug', 'Release')]
[string]$Configuration = "Release" [string]$Configuration = "Release"
) )
@ -483,122 +532,6 @@ function Get-SolutionFile
return Join-Path -Path $root -ChildPath "contrib\win32\openssh\Win32-OpenSSH.sln" return Join-Path -Path $root -ChildPath "contrib\win32\openssh\Win32-OpenSSH.sln"
} }
<#
.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" Export-ModuleMember -Function Start-OpenSSHBuild, Get-BuildLogFile, Start-OpenSSHPackage
)
if ($Configuration -eq "")
{
$Configuration = 'Release'
}
if ($NativeHostArch -eq "")
{
$NativeHostArch = 'x64'
if ($env:PROCESSOR_ARCHITECTURE -eq 'x86') {
$NativeHostArch = 'x86'
}
}
Package-OpenSSH -NativeHostArch $NativeHostArch -Configuration $Configuration -DestinationPath $OpenSSHDir
Push-Location $OpenSSHDir
& "$OpenSSHDir\install-sshd.ps1"
& "$OpenSSHDir\ssh-keygen.exe" -A
$keyFiles = Get-ChildItem "$OpenSSHDir\ssh_host_*_key*" | % {
Adjust-HostKeyFileACL -FilePath $_.FullName
}
#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
Pop-Location
Write-Log -Message "OpenSSH installed!"
}
<#
.Synopsis
uninstalled sshd and sshla
#>
function UnInstall-OpenSSH
{
[CmdletBinding()]
param
(
[string]$OpenSSHDir = "$env:SystemDrive\OpenSSH"
)
if (-not (Test-Path $OpenSSHDir))
{
return
}
Push-Location $OpenSSHDir
if((Get-Service ssh-agent -ErrorAction Ignore) -ne $null) {
Stop-Service ssh-agent -Force
}
&( "$OpenSSHDir\uninstall-sshd.ps1")
$machinePath = [Environment]::GetEnvironmentVariable('Path', 'MACHINE')
$newMachineEnvironmentPath = $machinePath
if ($machinePath.ToLower().Contains($OpenSSHDir.ToLower()))
{
$newMachineEnvironmentPath = $newMachineEnvironmentPath.Replace("$OpenSSHDir;", '')
$env:Path = $env:Path.Replace("$OpenSSHDir;", '')
}
if(Test-Path -Path $OpenSSHDir)
{
Push-Location $OpenSSHDir
&( "$OpenSSHDir\uninstall-sshd.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
Remove-Item -Path $OpenSSHDir -Recurse -Force -ErrorAction SilentlyContinue
}
}
Export-ModuleMember -Function Build-OpenSSH, Get-BuildLogFile, Install-OpenSSH, UnInstall-OpenSSH, Package-OpenSSH

View File

@ -1,20 +1,18 @@
<# If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
Import-Module $PSScriptRoot\OpenSSHUtils -Force
<#
.Synopsis .Synopsis
Finds the root of the git repository Finds the root of the git repository
.Outputs .Outputs
A System.IO.DirectoryInfo for the location of the root. A System.IO.DirectoryInfo for the location of the root if root is found; otherwise, script root.
.Inputs .Inputs
None None
.Notes
FileNotFoundException is thrown if the current directory does not contain a CMakeLists.txt file.
#> #>
function Get-RepositoryRoot function Get-RepositoryRoot
{ {
$currentDir = (Get-Item -Path $PSCommandPath).Directory $start = $currentDir = (Get-Item -Path $PSScriptRoot)
while ($null -ne $currentDir.Parent) while ($null -ne $currentDir.Parent)
{ {
$path = Join-Path -Path $currentDir.FullName -ChildPath '.git' $path = Join-Path -Path $currentDir.FullName -ChildPath '.git'
@ -24,147 +22,7 @@ function Get-RepositoryRoot
} }
$currentDir = $currentDir.Parent $currentDir = $currentDir.Parent
} }
return $start
throw new-object System.IO.DirectoryNotFoundException("Could not find the root of the GIT repository")
}
<#
.Synopsis
Set owner of the file to by LOCALSYSTEM account
Set private host key be fully controlled by LOCALSYSTEM and Administrators
Set public host key be fully controlled by LOCALSYSTEM and Administrators, read access by everyone
.Outputs
N/A
.Inputs
FilePath - The path to the file
#>
function Adjust-HostKeyFileACL
{
param (
[parameter(Mandatory=$true)]
[string]$FilePath
)
$myACL = Get-ACL $FilePath
$myACL.SetAccessRuleProtection($True, $FALSE)
Set-Acl -Path $FilePath -AclObject $myACL
$systemAccount = New-Object System.Security.Principal.NTAccount("NT AUTHORITY", "SYSTEM")
$adminAccount = New-Object System.Security.Principal.NTAccount("BUILTIN","Administrators")
$everyoneAccount = New-Object System.Security.Principal.NTAccount("EveryOne")
$myACL = Get-ACL $FilePath
$myACL.SetOwner($systemAccount)
if($myACL.Access)
{
$myACL.Access | % {
if(-not ($myACL.RemoveAccessRule($_)))
{
throw "failed to remove access of $($_.IdentityReference.Value) rule in setup "
}
}
}
$adminACE = New-Object System.Security.AccessControl.FileSystemAccessRule `
($adminAccount, "FullControl", "None", "None", "Allow")
$myACL.AddAccessRule($adminACE)
$systemACE = New-Object System.Security.AccessControl.FileSystemAccessRule `
($systemAccount, "FullControl", "None", "None", "Allow")
$myACL.AddAccessRule($systemACE)
if($FilePath.EndsWith(".pub"))
{
$everyoneAce = New-Object System.Security.AccessControl.FileSystemAccessRule `
("Everyone", "Read", "None", "None", "Allow")
$myACL.AddAccessRule($everyoneAce)
}
Set-Acl -Path $FilePath -AclObject $myACL
}
<#
.Synopsis
Set owner of the user key file
Set ACL to have private user key be fully controlled by LOCALSYSTEM and Administrators, Read, write access by owner
Set public user key be fully controlled by LOCALSYSTEM and Administrators, Read, write access by owner, read access by everyone
.Outputs
N/A
.Inputs
FilePath - The path to the file
Owner - owner of the file
OwnerPerms - the permissions grant to the owner
#>
function Adjust-UserKeyFileACL
{
param (
[parameter(Mandatory=$true)]
[string]$FilePath,
[System.Security.Principal.NTAccount] $Owner = $null,
[System.Security.AccessControl.FileSystemRights[]] $OwnerPerms = $null
)
$myACL = Get-ACL $FilePath
$myACL.SetAccessRuleProtection($True, $FALSE)
Set-Acl -Path $FilePath -AclObject $myACL
$systemAccount = New-Object System.Security.Principal.NTAccount("NT AUTHORITY", "SYSTEM")
$adminAccount = New-Object System.Security.Principal.NTAccount("BUILTIN","Administrators")
$everyoneAccount = New-Object System.Security.Principal.NTAccount("EveryOne")
$myACL = Get-ACL $FilePath
$actualOwner = $null
if($Owner -eq $null)
{
$actualOwner = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME))
}
else
{
$actualOwner = $Owner
}
$myACL.SetOwner($actualOwner)
if($myACL.Access)
{
$myACL.Access | % {
if(-not ($myACL.RemoveAccessRule($_)))
{
throw "failed to remove access of $($_.IdentityReference.Value) rule in setup "
}
}
}
$adminACE = New-Object System.Security.AccessControl.FileSystemAccessRule `
($adminAccount, "FullControl", "None", "None", "Allow")
$myACL.AddAccessRule($adminACE)
$systemACE = New-Object System.Security.AccessControl.FileSystemAccessRule `
($systemAccount, "FullControl", "None", "None", "Allow")
$myACL.AddAccessRule($systemACE)
if($OwnerPerms)
{
$OwnerPerms | % {
$ownerACE = New-Object System.Security.AccessControl.FileSystemAccessRule `
($actualOwner, $_, "None", "None", "Allow")
$myACL.AddAccessRule($ownerACE)
}
}
if($FilePath.EndsWith(".pub"))
{
$everyoneAce = New-Object System.Security.AccessControl.FileSystemAccessRule `
("Everyone", "Read", "None", "None", "Allow")
$myACL.AddAccessRule($everyoneAce)
}
Set-Acl -Path $FilePath -AclObject $myACL
} }
<# <#
@ -177,7 +35,7 @@ function Adjust-UserKeyFileACL
.Inputs .Inputs
FilePath - The path to the file FilePath - The path to the file
User - account name User - account name
Perm - The permission to grant. Perms - The permission to grant.
#> #>
function Add-PermissionToFileACL function Add-PermissionToFileACL
{ {
@ -200,8 +58,8 @@ function Add-PermissionToFileACL
$myACL.AddAccessRule($userACE) $myACL.AddAccessRule($userACE)
} }
} }
Enable-Privilege SeRestorePrivilege | out-null
Set-Acl -Path $FilePath -AclObject $myACL Set-Acl -Path $FilePath -AclObject $myACL
} }
Export-ModuleMember -Function Get-RepositoryRoot, Add-PermissionToFileACL, Adjust-HostKeyFileACL, Adjust-UserKeyFileACL Export-ModuleMember -Function Get-RepositoryRoot, Add-PermissionToFileACL

View File

@ -1,5 +1,7 @@
$ErrorActionPreference = 'Stop' $ErrorActionPreference = 'Stop'
Import-Module $PSScriptRoot\OpenSSHCommonUtils.psm1 -DisableNameChecking -Force If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
Import-Module $PSScriptRoot\OpenSSHCommonUtils.psm1 -Force
Import-Module $PSScriptRoot\OpenSSHUtils -Force
[System.IO.DirectoryInfo] $repositoryRoot = Get-RepositoryRoot [System.IO.DirectoryInfo] $repositoryRoot = Get-RepositoryRoot
# test environment parameters initialized with defaults # test environment parameters initialized with defaults
@ -17,23 +19,28 @@ $Script:E2ETestResultsFile = Join-Path $TestDataPath $E2ETestResultsFileName
$Script:UnitTestResultsFile = Join-Path $TestDataPath $UnitTestResultsFileName $Script:UnitTestResultsFile = Join-Path $TestDataPath $UnitTestResultsFileName
$Script:TestSetupLogFile = Join-Path $TestDataPath $TestSetupLogFileName $Script:TestSetupLogFile = Join-Path $TestDataPath $TestSetupLogFileName
$Script:E2ETestDirectory = Join-Path $repositoryRoot.FullName -ChildPath "regress\pesterTests" $Script:E2ETestDirectory = Join-Path $repositoryRoot.FullName -ChildPath "regress\pesterTests"
$Script:WindowsInBox = $false
<# <#
.Synopsis .Synopsis
Setup-OpenSSHTestEnvironment Set-OpenSSHTestEnvironment
TODO - split these steps into client and server side TODO - split these steps into client and server side
#> #>
function Setup-OpenSSHTestEnvironment function Set-OpenSSHTestEnvironment
{ {
[CmdletBinding()] [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
param param
( (
[switch] $Quiet,
[string] $OpenSSHBinPath, [string] $OpenSSHBinPath,
[string] $TestDataPath = "$env:SystemDrive\OpenSSHTests", [string] $TestDataPath = "$env:SystemDrive\OpenSSHTests",
[Boolean] $DebugMode = $false [Boolean] $DebugMode = $false
) )
if($PSBoundParameters.ContainsKey("Verbose"))
{
$verboseInfo = ($PSBoundParameters['Verbose']).IsPresent
}
if($Global:OpenSSHTestInfo -ne $null) if($Global:OpenSSHTestInfo -ne $null)
{ {
$Global:OpenSSHTestInfo.Clear() $Global:OpenSSHTestInfo.Clear()
@ -65,41 +72,30 @@ function Setup-OpenSSHTestEnvironment
#if user does not set path, pick it up #if user does not set path, pick it up
if([string]::IsNullOrEmpty($OpenSSHBinPath)) if([string]::IsNullOrEmpty($OpenSSHBinPath))
{ {
$sshcmd = get-command ssh.exe -ErrorAction Ignore $sshcmd = get-command ssh.exe -ErrorAction SilentlyContinue
if($sshcmd -eq $null) if($sshcmd -eq $null)
{ {
Throw "Cannot find ssh.exe. Please specify -OpenSSHBinPath to the OpenSSH installed location." Throw "Cannot find ssh.exe. Please specify -OpenSSHBinPath to the OpenSSH installed location."
} }
elseif($Quiet)
{
$dirToCheck = split-path $sshcmd.Path
$script:OpenSSHBinPath = $dirToCheck
}
else else
{ {
$dirToCheck = split-path $sshcmd.Path $dirToCheck = split-path $sshcmd.Path
$message = "Do you want to test openssh installed at $($dirToCheck)? [Yes] Y; [No] N (default is `"Y`")" $description = "Pick up ssh.exe from $dirToCheck."
$response = Read-Host -Prompt $message $prompt = "Are you sure you want to pick up ssh.exe from $($dirToCheck)?"
if( ($response -eq "") -or ($response -ieq "Y") -or ($response -ieq "Yes") ) $caption = "Found ssh.exe from $dirToCheck"
{ if(-not $pscmdlet.ShouldProcess($description, $prompt, $caption))
$script:OpenSSHBinPath = $dirToCheck
}
elseif( ($response -ieq "N") -or ($response -ieq "No") )
{ {
Write-Host "User decided not to pick up ssh.exe from $dirToCheck. Please specify -OpenSSHBinPath to the OpenSSH installed location." Write-Host "User decided not to pick up ssh.exe from $dirToCheck. Please specify -OpenSSHBinPath to the OpenSSH installed location."
return return
} }
else $script:OpenSSHBinPath = $dirToCheck
{
Throw "User entered invalid option ($response). Please specify -OpenSSHBinPath to the OpenSSH installed location"
}
} }
} }
else else
{ {
if (-not (Test-Path (Join-Path $OpenSSHBinPath ssh.exe) -PathType Leaf)) if (-not (Test-Path (Join-Path $OpenSSHBinPath ssh.exe) -PathType Leaf))
{ {
Throw "Cannot find OpenSSH binaries under $OpenSSHBinPath. Please specify -OpenSSHBinPathto the OpenSSH installed location" Throw "Cannot find OpenSSH binaries under $OpenSSHBinPath. Please specify -OpenSSHBinPath to the OpenSSH installed location"
} }
else else
{ {
@ -113,7 +109,15 @@ function Setup-OpenSSHTestEnvironment
$env:Path = "$($script:OpenSSHBinPath);$($env:path)" $env:Path = "$($script:OpenSSHBinPath);$($env:path)"
} }
$warning = @" $acl = get-acl (join-path $script:OpenSSHBinPath "ssh.exe")
if($acl.Owner -ieq "NT SERVICE\TrustedInstaller")
{
$Script:WindowsInBox = $true
$Global:OpenSSHTestInfo.Add("WindowsInBox", $true)
}
$description = @"
WARNING: Following changes will be made to OpenSSH configuration WARNING: Following changes will be made to OpenSSH configuration
- sshd_config will be backed up as sshd_config.ori - sshd_config will be backed up as sshd_config.ori
- will be replaced with a test sshd_config - will be replaced with a test sshd_config
@ -125,21 +129,15 @@ WARNING: Following changes will be made to OpenSSH configuration
- $HOME\.ssh\known_hosts will be modified with test host key entry - $HOME\.ssh\known_hosts will be modified with test host key entry
- test accounts - ssouser, pubkeyuser, and passwduser will be added - test accounts - ssouser, pubkeyuser, and passwduser will be added
- Setup single signon for ssouser - Setup single signon for ssouser
- To cleanup - Run Cleanup-OpenSSHTestEnvironment - To cleanup - Run Clear-OpenSSHTestEnvironment
"@ "@
if (-not $Quiet) { $prompt = "Are you sure you want to perform the above operations?"
Write-Warning $warning $caption = $description
$continue = Read-Host -Prompt "Do you want to continue with the above changes? [Yes] Y; [No] N (default is `"Y`")" if(-not $pscmdlet.ShouldProcess($description, $prompt, $caption))
if( ($continue -ieq "N") -or ($continue -ieq "No") ) {
{ Write-Host "User decided not to make the changes."
Write-Host "User decided not to make the changes." return
return
}
elseif(($continue -ne "") -and ($continue -ine "Y") -and ($continue -ine "Yes"))
{
Throw "User entered invalid option ($continue). Exit now."
}
} }
Install-OpenSSHTestDependencies Install-OpenSSHTestDependencies
@ -154,9 +152,15 @@ WARNING: Following changes will be made to OpenSSH configuration
if (-not (Test-Path $backupConfigPath -PathType Leaf)) { if (-not (Test-Path $backupConfigPath -PathType Leaf)) {
Copy-Item (Join-Path $script:OpenSSHBinPath sshd_config) $backupConfigPath -Force Copy-Item (Join-Path $script:OpenSSHBinPath sshd_config) $backupConfigPath -Force
} }
$targetsshdConfig = Join-Path $script:OpenSSHBinPath sshd_config
# copy new sshd_config # copy new sshd_config
Copy-Item (Join-Path $Script:E2ETestDirectory sshd_config) (Join-Path $script:OpenSSHBinPath sshd_config) -Force if($Script:WindowsInBox -and (Test-Path $targetsshdConfig))
{
$currentUser = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME))
Add-PermissionToFileACL -FilePath $targetsshdConfig -User $currentUser -Perm "Read,Write"
}
Copy-Item (Join-Path $Script:E2ETestDirectory sshd_config) $targetsshdConfig -Force
Start-Service ssh-agent Start-Service ssh-agent
@ -164,11 +168,17 @@ WARNING: Following changes will be made to OpenSSH configuration
Copy-Item "$($Script:E2ETestDirectory)\sshtest*hostkey*" $script:OpenSSHBinPath -Force Copy-Item "$($Script:E2ETestDirectory)\sshtest*hostkey*" $script:OpenSSHBinPath -Force
Get-ChildItem "$($script:OpenSSHBinPath)\sshtest*hostkey*"| % { Get-ChildItem "$($script:OpenSSHBinPath)\sshtest*hostkey*"| % {
#workaround for the cariggage new line added by git before copy them #workaround for the cariggage new line added by git before copy them
(Get-Content $_.FullName -Raw).Replace("`r`n","`n") | Set-Content $_.FullName -Force $filePath = "$($_.FullName)"
Adjust-HostKeyFileACL -FilePath $_.FullName $con = (Get-Content $filePath | Out-String).Replace("`r`n","`n")
if (-not ($_.Name.EndsWith(".pub"))) { Set-Content -Path $filePath -Value "$con"
#register private key with agent if (-not ($_.Name.EndsWith(".pub")))
ssh-add-hostkey.ps1 $_.FullName {
Repair-SshdHostKeyPermission -FilePath $_.FullName -confirm:$false
if($psversiontable.BuildVersion.Major -gt 6)
{
#register private key with agent
ssh-add-hostkey.ps1 $_.FullName
}
} }
} }
@ -192,7 +202,7 @@ WARNING: Following changes will be made to OpenSSH configuration
Copy-Item $sshConfigFilePath (Join-Path $dotSshDirectoryPath config.ori) -Force Copy-Item $sshConfigFilePath (Join-Path $dotSshDirectoryPath config.ori) -Force
} }
Copy-Item (Join-Path $Script:E2ETestDirectory ssh_config) $sshConfigFilePath -Force Copy-Item (Join-Path $Script:E2ETestDirectory ssh_config) $sshConfigFilePath -Force
Adjust-UserKeyFileACL -FilePath $sshConfigFilePath -OwnerPerms "Read,Write" Repair-UserSshConfigPermission -FilePath $sshConfigFilePath -confirm:$false
# create test accounts # create test accounts
#TODO - this is Windows specific. Need to be in PAL #TODO - this is Windows specific. Need to be in PAL
@ -219,12 +229,13 @@ WARNING: Following changes will be made to OpenSSH configuration
$authorizedKeyPath = Join-Path $ssouserProfile .ssh\authorized_keys $authorizedKeyPath = Join-Path $ssouserProfile .ssh\authorized_keys
$testPubKeyPath = Join-Path $Script:E2ETestDirectory sshtest_userssokey_ed25519.pub $testPubKeyPath = Join-Path $Script:E2ETestDirectory sshtest_userssokey_ed25519.pub
Copy-Item $testPubKeyPath $authorizedKeyPath -Force -ErrorAction SilentlyContinue Copy-Item $testPubKeyPath $authorizedKeyPath -Force -ErrorAction SilentlyContinue
$owner = New-Object System.Security.Principal.NTAccount($SSOUser) Repair-AuthorizedKeyPermission -FilePath $authorizedKeyPath -confirm:$false
Adjust-UserKeyFileACL -FilePath $authorizedKeyPath -Owner $owner -OwnerPerms "Read","Write"
Add-PermissionToFileACL -FilePath $authorizedKeyPath -User "NT Service\sshd" -Perm "Read"
$testPriKeypath = Join-Path $Script:E2ETestDirectory sshtest_userssokey_ed25519 $testPriKeypath = Join-Path $Script:E2ETestDirectory sshtest_userssokey_ed25519
(Get-Content $testPriKeypath -Raw).Replace("`r`n","`n") | Set-Content $testPriKeypath -Force $con = (Get-Content $testPriKeypath | Out-String).Replace("`r`n","`n")
Adjust-UserKeyFileACL -FilePath $testPriKeypath -OwnerPerms "Read, Write" Set-Content -Path $testPriKeypath -Value "$con"
cmd /c "ssh-add -D 2>&1 >> $Script:TestSetupLogFile"
Repair-UserKeyPermission -FilePath $testPriKeypath -confirm:$false
cmd /c "ssh-add $testPriKeypath 2>&1 >> $Script:TestSetupLogFile" cmd /c "ssh-add $testPriKeypath 2>&1 >> $Script:TestSetupLogFile"
Backup-OpenSSHTestInfo Backup-OpenSSHTestInfo
} }
@ -257,6 +268,19 @@ function Install-OpenSSHTestDependencies
[CmdletBinding()] [CmdletBinding()]
param () param ()
#$isOpenSSHUtilsAvailable = Get-Module 'OpenSSHUtils' -ListAvailable
#if (-not ($isOpenSSHUtilsAvailable))
#{
Write-Log -Message "Installing Module OpenSSHUtils..."
Install-OpenSSHUtilsModule -SourceDir $PSScriptRoot
#}
Import-Module OpensshUtils -Force
if($Script:WindowsInBox)
{
return
}
# Install chocolatey # Install chocolatey
if(-not (Get-Command "choco" -ErrorAction SilentlyContinue)) if(-not (Get-Command "choco" -ErrorAction SilentlyContinue))
{ {
@ -267,10 +291,66 @@ function Install-OpenSSHTestDependencies
$isModuleAvailable = Get-Module 'Pester' -ListAvailable $isModuleAvailable = Get-Module 'Pester' -ListAvailable
if (-not ($isModuleAvailable)) if (-not ($isModuleAvailable))
{ {
Write-Log -Message "Installing Pester..." Write-Log -Message "Installing Pester..."
choco install Pester -y --force --limitoutput 2>&1 >> $Script:TestSetupLogFile choco install Pester -y --force --limitoutput 2>&1 >> $Script:TestSetupLogFile
} }
} }
function Install-OpenSSHUtilsModule
{
[CmdletBinding()]
param(
[string]$TargetDir = (Join-Path -Path $env:ProgramFiles -ChildPath "WindowsPowerShell\Modules\OpenSSHUtils"),
[string]$SourceDir)
$manifestFile = Join-Path -Path $SourceDir -ChildPath OpenSSHUtils.psd1
$moduleFile = Join-Path -Path $SourceDir -ChildPath OpenSSHUtils.psm1
$targetDirectory = $TargetDir
$manifest = Test-ModuleManifest -Path $manifestFile -WarningAction SilentlyContinue -ErrorAction Stop
if ($PSVersionTable.PSVersion.Major -ge 5)
{
$targetDirectory = Join-Path -Path $targetDir -ChildPath $manifest.Version.ToString()
}
$modulePath = Join-Path -Path $env:ProgramFiles -ChildPath WindowsPowerShell\Modules
if(-not (Test-Path $targetDirectory -PathType Container))
{
New-Item -ItemType Directory -Path $targetDirectory -Force -ErrorAction SilentlyContinue | out-null
}
Copy-item $manifestFile -Destination $targetDirectory -Force -ErrorAction SilentlyContinue | out-null
Copy-item $moduleFile -Destination $targetDirectory -Force -ErrorAction SilentlyContinue | out-null
if ($PSVersionTable.PSVersion.Major -lt 4)
{
$modulePaths = [Environment]::GetEnvironmentVariable('PSModulePath', 'Machine') -split ';'
if ($modulePaths -notcontains $modulePath)
{
Write-Verbose -Message "Adding '$modulePath' to PSModulePath."
$modulePaths = @(
$modulePath
$modulePaths
)
$newModulePath = $modulePaths -join ';'
[Environment]::SetEnvironmentVariable('PSModulePath', $newModulePath, 'Machine')
$env:PSModulePath += ";$modulePath"
}
}
}
function Uninstall-OpenSSHUtilsModule
{
[CmdletBinding()]
param([string]$TargetDir = (Join-Path -Path $env:ProgramFiles -ChildPath "WindowsPowerShell\Modules\OpenSSHUtils"))
if(Test-Path $TargetDir -PathType Container)
{
Remove-item $TargetDir -Recurse -Force -ErrorAction SilentlyContinue | out-null
}
}
<# <#
.Synopsis .Synopsis
Get-UserSID Get-UserSID
@ -296,12 +376,12 @@ function Get-UserSID
<# <#
.Synopsis .Synopsis
Cleanup-OpenSSHTestEnvironment Clear-OpenSSHTestEnvironment
#> #>
function Cleanup-OpenSSHTestEnvironment function Clear-OpenSSHTestEnvironment
{ {
if($Global:OpenSSHTestInfo -eq $null) { if($Global:OpenSSHTestInfo -eq $null) {
throw "OpenSSHTestInfo is not set. Did you run Setup-OpenSShTestEnvironment?" throw "OpenSSHTestInfo is not set. Did you run Set-OpenSShTestEnvironment?"
} }
$sshBinPath = $Global:OpenSSHTestInfo["OpenSSHBinPath"] $sshBinPath = $Global:OpenSSHTestInfo["OpenSSHBinPath"]
@ -356,6 +436,13 @@ function Cleanup-OpenSSHTestEnvironment
$Global:OpenSSHTestInfo.Clear() $Global:OpenSSHTestInfo.Clear()
$Global:OpenSSHTestInfo = $null $Global:OpenSSHTestInfo = $null
} }
$isOpenSSHUtilsAvailable = Get-Module 'OpenSSHUtils' -ListAvailable
if ($isOpenSSHUtilsAvailable)
{
Write-Log -Message "Uninstalling Module OpenSSHUtils..."
Uninstall-OpenSSHUtilsModule
}
} }
<# <#
@ -418,12 +505,13 @@ function Get-UnitTestDirectory
.Synopsis .Synopsis
Run OpenSSH pester tests. Run OpenSSH pester tests.
#> #>
function Run-OpenSSHE2ETest function Invoke-OpenSSHE2ETest
{ {
# Discover all CI tests and run them. # Discover all CI tests and run them.
Import-Module pester -force -global
Push-Location $Script:E2ETestDirectory Push-Location $Script:E2ETestDirectory
Write-Log -Message "Running OpenSSH E2E tests..." Write-Log -Message "Running OpenSSH E2E tests..."
$testFolders = Get-ChildItem *.tests.ps1 -Recurse | ForEach-Object{ Split-Path $_.FullName} | Sort-Object -Unique $testFolders = @(Get-ChildItem *.tests.ps1 -Recurse | ForEach-Object{ Split-Path $_.FullName} | Sort-Object -Unique)
Invoke-Pester $testFolders -OutputFormat NUnitXml -OutputFile $Script:E2ETestResultsFile -Tag 'CI' Invoke-Pester $testFolders -OutputFormat NUnitXml -OutputFile $Script:E2ETestResultsFile -Tag 'CI'
Pop-Location Pop-Location
} }
@ -432,35 +520,45 @@ function Run-OpenSSHE2ETest
.Synopsis .Synopsis
Run openssh unit tests. Run openssh unit tests.
#> #>
function Run-OpenSSHUnitTest function Invoke-OpenSSHUnitTest
{ {
# Discover all CI tests and run them. # Discover all CI tests and run them.
if([string]::Isnullorempty($Script:UnitTestDirectory))
{
$Script:UnitTestDirectory = $OpenSSHTestInfo["UnitTestDirectory"]
}
Push-Location $Script:UnitTestDirectory Push-Location $Script:UnitTestDirectory
Write-Log -Message "Running OpenSSH unit tests..." Write-Log -Message "Running OpenSSH unit tests..."
if (Test-Path $Script:UnitTestResultsFile) if (Test-Path $Script:UnitTestResultsFile)
{ {
$null = Remove-Item -Path $Script:UnitTestResultsFile -Force -ErrorAction SilentlyContinue $null = Remove-Item -Path $Script:UnitTestResultsFile -Force -ErrorAction SilentlyContinue
} }
$testFolders = Get-ChildItem unittest-*.exe -Recurse -Exclude unittest-sshkey.exe,unittest-kex.exe | $testFolders = Get-ChildItem -filter unittest-*.exe -Recurse -Exclude unittest-sshkey.exe,unittest-kex.exe |
ForEach-Object{ Split-Path $_.FullName} | ForEach-Object{ Split-Path $_.FullName} |
Sort-Object -Unique Sort-Object -Unique
$testfailed = $false $testfailed = $false
if ($testFolders -ne $null) if ($testFolders -ne $null)
{ {
$testFolders | % { $testFolders | % {
Push-Location $_
$unittestFile = "$(Split-Path $_ -Leaf).exe" $unittestFile = "$(Split-Path $_ -Leaf).exe"
Write-log "Running OpenSSH unit $unittestFile ..." $unittestFilePath = join-path $_ $unittestFile
& .\$unittestFile >> $Script:UnitTestResultsFile $Error.clear()
$LASTEXITCODE=0
if(Test-Path $unittestFilePath -pathtype leaf)
{
Push-Location $_
Write-Log "Running OpenSSH unit $unittestFile ..."
& "$unittestFilePath" >> $Script:UnitTestResultsFile
Pop-Location
}
$errorCode = $LASTEXITCODE $errorCode = $LASTEXITCODE
if ($errorCode -ne 0) if ($errorCode -ne 0)
{ {
$testfailed = $true $testfailed = $true
$errorMessage = "$($_.FullName) test failed for OpenSSH.`nExitCode: $errorCode. Detail test log is at $($Script:UnitTestResultsFile)." $errorMessage = "$_ test failed for OpenSSH.`nExitCode: $errorCode. Detail test log is at $($Script:UnitTestResultsFile)."
Write-Warning $errorMessage Write-Warning $errorMessage
} }
Pop-Location
} }
} }
Pop-Location Pop-Location
@ -475,7 +573,7 @@ function Backup-OpenSSHTestInfo
) )
if ($Global:OpenSSHTestInfo -eq $null) { if ($Global:OpenSSHTestInfo -eq $null) {
Throw "`$OpenSSHTestInfo is null. Did you run Setup-OpenSSHTestEnvironment yet?" Throw "`$OpenSSHTestInfo is null. Did you run Set-OpenSSHTestEnvironment yet?"
} }
$testInfo = $Global:OpenSSHTestInfo $testInfo = $Global:OpenSSHTestInfo
@ -492,7 +590,7 @@ function Backup-OpenSSHTestInfo
} }
} }
function Recover-OpenSSHTestInfo function Restore-OpenSSHTestInfo
{ {
param param
( (
@ -538,4 +636,4 @@ function Write-Log
} }
} }
Export-ModuleMember -Function Setup-OpenSSHTestEnvironment, Cleanup-OpenSSHTestEnvironment, Run-OpenSSHUnitTest, Run-OpenSSHE2ETest, Backup-OpenSSHTestInfo, Recover-OpenSSHTestInfo Export-ModuleMember -Function Set-OpenSSHTestEnvironment, Clear-OpenSSHTestEnvironment, Invoke-OpenSSHUnitTest, Invoke-OpenSSHE2ETest, Backup-OpenSSHTestInfo, Restore-OpenSSHTestInfo

View File

@ -1,9 +1,49 @@
Set-StrictMode -Version 2.0 Set-StrictMode -Version 2.0
$systemAccount = New-Object System.Security.Principal.NTAccount("NT AUTHORITY", "SYSTEM")
$adminsAccount = New-Object System.Security.Principal.NTAccount("BUILTIN","Administrators") <#
$currentUser = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME)) .Synopsis
$everyone = New-Object System.Security.Principal.NTAccount("EveryOne") Get-UserSID
$sshdAccount = New-Object System.Security.Principal.NTAccount("NT SERVICE","sshd") #>
function Get-UserSID
{
[CmdletBinding(DefaultParameterSetName='User')]
param
( [parameter(Mandatory=$true, ParameterSetName="User")]
[ValidateNotNull()]
[System.Security.Principal.NTAccount]$User,
[parameter(Mandatory=$true, ParameterSetName="WellKnownSidType")]
[ValidateNotNull()]
[System.Security.Principal.WellKnownSidType]$WellKnownSidType
)
try
{
if($PSBoundParameters.ContainsKey("User"))
{
$sid = $User.Translate([System.Security.Principal.SecurityIdentifier])
}
elseif($PSBoundParameters.ContainsKey("WellKnownSidType"))
{
$sid = New-Object System.Security.Principal.SecurityIdentifier($WellKnownSidType, $null)
}
$sid
}
catch {
return $null
}
}
# get the local System user
$systemSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::LocalSystemSid)
# get the Administrators group
$adminsSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid)
# get the everyone
$everyoneSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::WorldSid)
$sshdSid = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-80-3847866527-469524349-687026318-516638107-1125189541")
$currentUserSid = Get-UserSID -User "$($env:USERDOMAIN)\$($env:USERNAME)"
#Taken from P/Invoke.NET with minor adjustments. #Taken from P/Invoke.NET with minor adjustments.
$definition = @' $definition = @'
@ -72,7 +112,7 @@ function Repair-SshdConfigPermission
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[string]$FilePath) [string]$FilePath)
Repair-FilePermission -Owners $systemAccount,$adminsAccount -ReadAccessNeeded $sshdAccount @psBoundParameters Repair-FilePermission -Owners $systemSid,$adminsSid -ReadAccessNeeded $sshdSid @psBoundParameters
} }
<# <#
@ -94,10 +134,10 @@ function Repair-SshdHostKeyPermission
$PSBoundParameters["FilePath"] = $PSBoundParameters["FilePath"].Replace(".pub", "") $PSBoundParameters["FilePath"] = $PSBoundParameters["FilePath"].Replace(".pub", "")
} }
Repair-FilePermission -Owners $systemAccount,$adminsAccount -ReadAccessNeeded $sshdAccount @psBoundParameters Repair-FilePermission -Owners $systemSid,$adminsSid -ReadAccessNeeded $sshdSid @psBoundParameters
$PSBoundParameters["FilePath"] += ".pub" $PSBoundParameters["FilePath"] += ".pub"
Repair-FilePermission -Owners $systemAccount,$adminsAccount -ReadAccessOK $everyone -ReadAccessNeeded $sshdAccount @psBoundParameters Repair-FilePermission -Owners $systemSid,$adminsSid -ReadAccessOK $everyoneSid -ReadAccessNeeded $sshdSid @psBoundParameters
} }
<# <#
@ -127,20 +167,14 @@ function Repair-AuthorizedKeyPermission
{ {
$userProfilePath = $properties.ProfileImagePath $userProfilePath = $properties.ProfileImagePath
} }
$fullPath -ieq "$userProfilePath\.ssh\authorized_keys" $userProfilePath = $userProfilePath.Replace("\", "\\")
$fullPath -match "^$userProfilePath[\\|\W|\w]+authorized_keys$"
} }
if($profileItem) if($profileItem)
{ {
$userSid = $profileItem.PSChildName $userSid = $profileItem.PSChildName
$account = Get-UserAccount -UserSid $userSid Repair-FilePermission -Owners $userSid,$adminsSid,$systemSid -AnyAccessOK $userSid -ReadAccessNeeded $sshdSid @psBoundParameters
if($account)
{
Repair-FilePermission -Owners $account,$adminsAccount,$systemAccount -AnyAccessOK $account -ReadAccessNeeded $sshdAccount @psBoundParameters
}
else
{
Write-host "Can't translate $userSid to an account. skip checking $fullPath..." -ForegroundColor Yellow
}
} }
else else
{ {
@ -162,16 +196,16 @@ function Repair-UserKeyPermission
[parameter(Mandatory=$true, Position = 0)] [parameter(Mandatory=$true, Position = 0)]
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[string]$FilePath, [string]$FilePath,
[System.Security.Principal.NTAccount] $User = $currentUser) [System.Security.Principal.SecurityIdentifier] $UserSid = $currentUserSid)
if($PSBoundParameters["FilePath"].EndsWith(".pub")) if($PSBoundParameters["FilePath"].EndsWith(".pub"))
{ {
$PSBoundParameters["FilePath"] = $PSBoundParameters["FilePath"].Replace(".pub", "") $PSBoundParameters["FilePath"] = $PSBoundParameters["FilePath"].Replace(".pub", "")
} }
Repair-FilePermission -Owners $User, $adminsAccount,$systemAccount -AnyAccessOK $User @psBoundParameters Repair-FilePermission -Owners $UserSid, $adminsSid,$systemSid -AnyAccessOK $UserSid @psBoundParameters
$PSBoundParameters["FilePath"] += ".pub" $PSBoundParameters["FilePath"] += ".pub"
Repair-FilePermission -Owners $User, $adminsAccount,$systemAccount -AnyAccessOK $User -ReadAccessOK $everyone @psBoundParameters Repair-FilePermission -Owners $UserSid, $adminsSid,$systemSid -AnyAccessOK $UserSid -ReadAccessOK $everyoneSid @psBoundParameters
} }
<# <#
@ -185,8 +219,9 @@ function Repair-UserSshConfigPermission
param ( param (
[parameter(Mandatory=$true)] [parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[string]$FilePath) [string]$FilePath,
Repair-FilePermission -Owners $currentUser,$adminsAccount,$systemAccount -AnyAccessOK $currentUser @psBoundParameters [System.Security.Principal.SecurityIdentifier] $UserSid = $currentUserSid)
Repair-FilePermission -Owners $UserSid,$adminsSid,$systemSid -AnyAccessOK $UserSid @psBoundParameters
} }
<# <#
@ -202,10 +237,11 @@ function Repair-FilePermission
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[string]$FilePath, [string]$FilePath,
[ValidateNotNull()] [ValidateNotNull()]
[System.Security.Principal.NTAccount[]] $Owners = $currentUser, [System.Security.Principal.SecurityIdentifier[]] $Owners = $currentUserSid,
[System.Security.Principal.NTAccount[]] $AnyAccessOK, [System.Security.Principal.SecurityIdentifier[]] $AnyAccessOK = $null,
[System.Security.Principal.NTAccount[]] $ReadAccessOK, [System.Security.Principal.SecurityIdentifier[]] $FullAccessNeeded = $null,
[System.Security.Principal.NTAccount[]] $ReadAccessNeeded [System.Security.Principal.SecurityIdentifier[]] $ReadAccessOK = $null,
[System.Security.Principal.SecurityIdentifier[]] $ReadAccessNeeded = $null
) )
if(-not (Test-Path $FilePath -PathType Leaf)) if(-not (Test-Path $FilePath -PathType Leaf))
@ -235,10 +271,11 @@ function Repair-FilePermissionInternal {
[ValidateNotNullOrEmpty()] [ValidateNotNullOrEmpty()]
[string]$FilePath, [string]$FilePath,
[ValidateNotNull()] [ValidateNotNull()]
[System.Security.Principal.NTAccount[]] $Owners = $currentUser, [System.Security.Principal.SecurityIdentifier[]] $Owners = $currentUserSid,
[System.Security.Principal.NTAccount[]] $AnyAccessOK, [System.Security.Principal.SecurityIdentifier[]] $AnyAccessOK = $null,
[System.Security.Principal.NTAccount[]] $ReadAccessOK, [System.Security.Principal.SecurityIdentifier[]] $FullAccessNeeded = $null,
[System.Security.Principal.NTAccount[]] $ReadAccessNeeded [System.Security.Principal.SecurityIdentifier[]] $ReadAccessOK = $null,
[System.Security.Principal.SecurityIdentifier[]] $ReadAccessNeeded = $null
) )
$acl = Get-Acl $FilePath $acl = Get-Acl $FilePath
@ -247,25 +284,18 @@ function Repair-FilePermissionInternal {
$paras = @{} $paras = @{}
$PSBoundParameters.GetEnumerator() | % { if((-not $_.key.Contains("Owners")) -and (-not $_.key.Contains("Access"))) { $paras.Add($_.key,$_.Value) } } $PSBoundParameters.GetEnumerator() | % { if((-not $_.key.Contains("Owners")) -and (-not $_.key.Contains("Access"))) { $paras.Add($_.key,$_.Value) } }
$validOwner = $owners | ? { $_.equals([System.Security.Principal.NTAccount]$acl.owner)} $currentOwnerSid = Get-UserSid -User $acl.owner
if($validOwner -eq $null) if($owners -notcontains $currentOwnerSid)
{ {
$caption = "Current owner: '$($acl.Owner)'. '$($Owners[0])' should own '$FilePath'." $newOwner = Get-UserAccount -User $Owners[0]
$caption = "Current owner: '$($acl.Owner)'. '$newOwner' should own '$FilePath'."
$prompt = "Shall I set the file owner?" $prompt = "Shall I set the file owner?"
$description = "Set '$($Owners[0])' as owner of '$FilePath'." $description = "Set '$newOwner' as owner of '$FilePath'."
if($pscmdlet.ShouldProcess($description, $prompt, $caption)) if($pscmdlet.ShouldProcess($description, $prompt, $caption))
{ {
Enable-Privilege SeRestorePrivilege | out-null Enable-Privilege SeRestorePrivilege | out-null
$acl.SetOwner($Owners[0]) $acl.SetOwner($newOwner)
Set-Acl -Path $FilePath -AclObject $acl -ErrorVariable e -Confirm:$false Set-Acl -Path $FilePath -AclObject $acl -Confirm:$false
if($e)
{
Write-Warning "Set owner failed with error: $($e[0].ToString())."
}
else
{
Write-Host "'$($Owners[0])' now owns '$FilePath'. " -ForegroundColor Green
}
} }
else else
{ {
@ -279,38 +309,112 @@ function Repair-FilePermissionInternal {
$ReadAccessPerm = ([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Read.value__) -bor ` $ReadAccessPerm = ([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Read.value__) -bor `
([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Synchronize.value__) ([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Synchronize.value__)
$FullControlPerm = [System.UInt32] [System.Security.AccessControl.FileSystemRights]::FullControl.value__
#system and admin groups can have any access to the file; plus the account in the AnyAccessOK list #system and admin groups can have any access to the file; plus the account in the AnyAccessOK list
$realAnyAccessOKList = $AnyAccessOK + @($systemAccount, $adminsAccount) $realAnyAccessOKList = @($systemSid, $adminsSid)
if($AnyAccessOK)
{
$realAnyAccessOKList += $AnyAccessOK
}
#if accounts in the ReadAccessNeeded already part of dacl, they are okay; need to make sure they have read access only $realFullAccessNeeded = $FullAccessNeeded
$realReadAcessOKList = $ReadAccessOK + $ReadAccessNeeded
#this is orginal list requested by the user, the account will be removed from the list if they already part of the dacl
$realReadAccessNeeded = $ReadAccessNeeded $realReadAccessNeeded = $ReadAccessNeeded
if($realFullAccessNeeded -contains $everyoneSid)
{
$realFullAccessNeeded = @($everyoneSid)
$realReadAccessNeeded = $null
}
#'APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES'- can't translate fully qualified name. it is a win32 API bug. if($realReadAccessNeeded -contains $everyoneSid)
#'ALL APPLICATION PACKAGES' exists only on Win2k12 and Win2k16 and 'ALL RESTRICTED APPLICATION PACKAGES' exists only in Win2k16 {
$specialIdRefs = "ALL APPLICATION PACKAGES","ALL RESTRICTED APPLICATION PACKAGES" $realReadAccessNeeded = @($everyoneSid)
}
#this is orginal list requested by the user, the account will be removed from the list if they already part of the dacl
if($realReadAccessNeeded)
{
$realReadAccessNeeded = $realReadAccessNeeded | ? { ($_ -ne $null) -and ($realFullAccessNeeded -notcontains $_) }
}
#if accounts in the ReadAccessNeeded or $realFullAccessNeeded already part of dacl, they are okay;
#need to make sure they have read access only
$realReadAcessOKList = $ReadAccessOK + $realReadAccessNeeded
foreach($a in $acl.Access) foreach($a in $acl.Access)
{ {
if($realAnyAccessOKList -and (($realAnyAccessOKList | ? { $_.equals($a.IdentityReference)}) -ne $null)) $IdentityReferenceSid = Get-UserSid -User $a.IdentityReference
if($IdentityReferenceSid -eq $null)
{
$idRefShortValue = ($a.IdentityReference.Value).split('\')[-1]
$IdentityReferenceSid = Get-UserSID -User $idRefShortValue
if($IdentityReferenceSid -eq $null)
{
Write-Warning "Can't translate '$idRefShortValue'. "
continue
}
}
if($realFullAccessNeeded -contains ($IdentityReferenceSid))
{
$realFullAccessNeeded = $realFullAccessNeeded | ? { ($_ -ne $null) -and (-not $_.Equals($IdentityReferenceSid)) }
if($realReadAccessNeeded)
{
$realReadAccessNeeded = $realReadAccessNeeded | ? { ($_ -ne $null) -and (-not $_.Equals($IdentityReferenceSid)) }
}
if (($a.AccessControlType.Equals([System.Security.AccessControl.AccessControlType]::Allow)) -and `
((([System.UInt32]$a.FileSystemRights.value__) -band $FullControlPerm) -eq $FullControlPerm))
{
continue;
}
#update the account to full control
if($a.IsInherited)
{
if($needChange)
{
Enable-Privilege SeRestorePrivilege | out-null
Set-Acl -Path $FilePath -AclObject $acl -Confirm:$false
}
return Remove-RuleProtection @paras
}
$caption = "'$($a.IdentityReference)' has the following access to '$FilePath': '$($a.AccessControlType)'-'$($a.FileSystemRights)'."
$prompt = "Shall I make it Allow FullControl?"
$description = "Grant '$($a.IdentityReference)' FullControl access to '$FilePath'. "
if($pscmdlet.ShouldProcess($description, $prompt, $caption))
{
$needChange = $true
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
($IdentityReferenceSid, "FullControl", "None", "None", "Allow")
$acl.SetAccessRule($ace)
Write-Host "'$($a.IdentityReference)' now has FullControl access to '$FilePath'. " -ForegroundColor Green
}
else
{
$health = $false
if(-not $PSBoundParameters.ContainsKey("WhatIf"))
{
Write-Host "'$($a.IdentityReference)' still has these access to '$FilePath': '$($a.AccessControlType)'-'$($a.FileSystemRights)'." -ForegroundColor Yellow
}
}
}
elseif(($realAnyAccessOKList -contains $everyoneSid) -or ($realAnyAccessOKList -contains $IdentityReferenceSid))
{ {
#ignore those accounts listed in the AnyAccessOK list. #ignore those accounts listed in the AnyAccessOK list.
continue;
} }
#If everyone is in the ReadAccessOK list, any user can have read access; #If everyone is in the ReadAccessOK list, any user can have read access;
# below block make sure they are granted Read access only # below block make sure they are granted Read access only
elseif($realReadAcessOKList -and ((($realReadAcessOKList | ? { $_.Equals($everyone)}) -ne $null) -or ` elseif(($realReadAcessOKList -contains $everyoneSid) -or ($realReadAcessOKList -contains $IdentityReferenceSid))
(($realReadAcessOKList | ? { $_.equals($a.IdentityReference)}) -ne $null)))
{ {
if($realReadAccessNeeded -and ($a.IdentityReference.Equals($everyone))) if($realReadAccessNeeded -and ($IdentityReferenceSid.Equals($everyoneSid)))
{ {
$realReadAccessNeeded=@() $realReadAccessNeeded= $null
} }
elseif($realReadAccessNeeded) elseif($realReadAccessNeeded)
{ {
$realReadAccessNeeded = $realReadAccessNeeded | ? { -not $_.Equals($a.IdentityReference) } $realReadAccessNeeded = $realReadAccessNeeded | ? { ($_ -ne $null ) -and (-not $_.Equals($IdentityReferenceSid)) }
} }
if (-not ($a.AccessControlType.Equals([System.Security.AccessControl.AccessControlType]::Allow)) -or ` if (-not ($a.AccessControlType.Equals([System.Security.AccessControl.AccessControlType]::Allow)) -or `
@ -324,11 +428,7 @@ function Repair-FilePermissionInternal {
if($needChange) if($needChange)
{ {
Enable-Privilege SeRestorePrivilege | out-null Enable-Privilege SeRestorePrivilege | out-null
Set-Acl -Path $FilePath -AclObject $acl -ErrorVariable e -Confirm:$false Set-Acl -Path $FilePath -AclObject $acl -Confirm:$false
if($e)
{
Write-Warning "Repair permission failed with error: $($e[0].ToString())."
}
} }
return Remove-RuleProtection @paras return Remove-RuleProtection @paras
@ -340,28 +440,11 @@ function Repair-FilePermissionInternal {
if($pscmdlet.ShouldProcess($description, $prompt, $caption)) if($pscmdlet.ShouldProcess($description, $prompt, $caption))
{ {
$needChange = $true $needChange = $true
$idRefShortValue = ($a.IdentityReference.Value).split('\')[-1] $ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
if ($specialIdRefs -icontains $idRefShortValue ) ($IdentityReferenceSid, "Read", "None", "None", "Allow")
{
$ruleIdentity = Get-UserSID -User (New-Object Security.Principal.NTAccount $idRefShortValue)
if($ruleIdentity)
{
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
($ruleIdentity, "Read", "None", "None", "Allow")
}
else
{
Write-Warning "Can't translate '$idRefShortValue'. "
continue
}
}
else
{
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
($a.IdentityReference, "Read", "None", "None", "Allow")
}
$acl.SetAccessRule($ace) $acl.SetAccessRule($ace)
Write-Host "'$($a.IdentityReference)' now has Read access to '$FilePath'. " -ForegroundColor Green Write-Host "'$($a.IdentityReference)' now has Read access to '$FilePath'. " -ForegroundColor Green
} }
else else
{ {
@ -381,11 +464,7 @@ function Repair-FilePermissionInternal {
if($needChange) if($needChange)
{ {
Enable-Privilege SeRestorePrivilege | out-null Enable-Privilege SeRestorePrivilege | out-null
Set-Acl -Path $FilePath -AclObject $acl -ErrorVariable e -Confirm:$false Set-Acl -Path $FilePath -AclObject $acl -Confirm:$false
if($e)
{
Write-Warning "Repair permission failed with error: $($e[0].ToString())."
}
} }
return Remove-RuleProtection @paras return Remove-RuleProtection @paras
} }
@ -396,22 +475,8 @@ function Repair-FilePermissionInternal {
if($pscmdlet.ShouldProcess($description, $prompt, "$caption.")) if($pscmdlet.ShouldProcess($description, $prompt, "$caption."))
{ {
$needChange = $true $needChange = $true
$ace = $a $ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
$idRefShortValue = ($a.IdentityReference.Value).split('\')[-1] ($IdentityReferenceSid, $a.FileSystemRights, $a.InheritanceFlags, $a.PropagationFlags, $a.AccessControlType)
if ($specialIdRefs -icontains $idRefShortValue)
{
$ruleIdentity = Get-UserSID -User (New-Object Security.Principal.NTAccount $idRefShortValue)
if($ruleIdentity)
{
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
($ruleIdentity, $a.FileSystemRights, $a.InheritanceFlags, $a.PropagationFlags, $a.AccessControlType)
}
else
{
Write-Warning "Can't translate '$idRefShortValue'. "
continue
}
}
if(-not ($acl.RemoveAccessRule($ace))) if(-not ($acl.RemoveAccessRule($ace)))
{ {
@ -433,19 +498,54 @@ function Repair-FilePermissionInternal {
} }
} }
if($realFullAccessNeeded)
{
$realFullAccessNeeded | % {
$account = Get-UserAccount -UserSid $_
if($account -eq $null)
{
Write-Warning "'$_' needs FullControl access to '$FilePath', but it can't be translated on the machine."
}
else
{
$caption = "'$account' needs FullControl access to '$FilePath'."
$prompt = "Shall I make the above change?"
$description = "Set '$account' FullControl access to '$FilePath'. "
if($pscmdlet.ShouldProcess($description, $prompt, $caption))
{
$needChange = $true
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
($_, "FullControl", "None", "None", "Allow")
$acl.AddAccessRule($ace)
Write-Host "'$account' now has FullControl to '$FilePath'." -ForegroundColor Green
}
else
{
$health = $false
if(-not $PSBoundParameters.ContainsKey("WhatIf"))
{
Write-Host "'$account' does not have FullControl to '$FilePath'." -ForegroundColor Yellow
}
}
}
}
}
#This is the real account list we need to add read access to the file #This is the real account list we need to add read access to the file
if($realReadAccessNeeded) if($realReadAccessNeeded)
{ {
$realReadAccessNeeded | % { $realReadAccessNeeded | % {
if((Get-UserSID -User $_) -eq $null) $account = Get-UserAccount -UserSid $_
if($account -eq $null)
{ {
Write-Warning "'$_' needs Read access to '$FilePath', but it can't be translated on the machine." Write-Warning "'$_' needs Read access to '$FilePath', but it can't be translated on the machine."
} }
else else
{ {
$caption = "'$_' needs Read access to '$FilePath'." $caption = "'$account' needs Read access to '$FilePath'."
$prompt = "Shall I make the above change?" $prompt = "Shall I make the above change?"
$description = "Set '$_' Read only access to '$FilePath'. " $description = "Set '$account' Read only access to '$FilePath'. "
if($pscmdlet.ShouldProcess($description, $prompt, $caption)) if($pscmdlet.ShouldProcess($description, $prompt, $caption))
{ {
@ -453,14 +553,14 @@ function Repair-FilePermissionInternal {
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule ` $ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
($_, "Read", "None", "None", "Allow") ($_, "Read", "None", "None", "Allow")
$acl.AddAccessRule($ace) $acl.AddAccessRule($ace)
Write-Host "'$_' now has Read access to '$FilePath'." -ForegroundColor Green Write-Host "'$account' now has Read access to '$FilePath'." -ForegroundColor Green
} }
else else
{ {
$health = $false $health = $false
if(-not $PSBoundParameters.ContainsKey("WhatIf")) if(-not $PSBoundParameters.ContainsKey("WhatIf"))
{ {
Write-Host "'$_' does not have Read access to '$FilePath'." -ForegroundColor Yellow Write-Host "'$account' does not have Read access to '$FilePath'." -ForegroundColor Yellow
} }
} }
} }
@ -470,11 +570,7 @@ function Repair-FilePermissionInternal {
if($needChange) if($needChange)
{ {
Enable-Privilege SeRestorePrivilege | out-null Enable-Privilege SeRestorePrivilege | out-null
Set-Acl -Path $FilePath -AclObject $acl -ErrorVariable e -Confirm:$false Set-Acl -Path $FilePath -AclObject $acl -Confirm:$false
if($e)
{
Write-Warning "Repair permission failed with error: $($e[0].ToString())."
}
} }
if($health) if($health)
{ {
@ -525,41 +621,44 @@ function Remove-RuleProtection
return $false return $false
} }
} }
<# <#
.Synopsis .Synopsis
Get-UserAccount Get-UserAccount
#> #>
function Get-UserAccount function Get-UserAccount
{ {
[CmdletBinding(DefaultParameterSetName='Sid')]
param param
( [parameter(Mandatory=$true)] ( [parameter(Mandatory=$true, ParameterSetName="Sid")]
[string]$UserSid [ValidateNotNull()]
[System.Security.Principal.SecurityIdentifier]$UserSid,
[parameter(Mandatory=$true, ParameterSetName="WellKnownSidType")]
[ValidateNotNull()]
[System.Security.Principal.WellKnownSidType]$WellKnownSidType
) )
try try
{ {
$objSID = New-Object System.Security.Principal.SecurityIdentifier($UserSid) if($PSBoundParameters.ContainsKey("UserSid"))
$objUser = $objSID.Translate( [System.Security.Principal.NTAccount]) {
$objUser = $UserSid.Translate([System.Security.Principal.NTAccount])
}
elseif($PSBoundParameters.ContainsKey("WellKnownSidType"))
{
$objSID = New-Object System.Security.Principal.SecurityIdentifier($WellKnownSidType, $null)
$objUser = $objSID.Translate( [System.Security.Principal.NTAccount])
}
$objUser $objUser
} }
catch { catch {
return $null
} }
} }
<# <#
.Synopsis .Synopsis
Get-UserSID Enable-Privilege
#> #>
function Get-UserSID
{
param ([System.Security.Principal.NTAccount]$User)
try
{
$User.Translate([System.Security.Principal.SecurityIdentifier])
}
catch {
}
}
function Enable-Privilege { function Enable-Privilege {
param( param(
#The privilege to adjust. This set is taken from #The privilege to adjust. This set is taken from
@ -584,4 +683,4 @@ function Enable-Privilege {
$type[0]::EnablePrivilege($Privilege, $Disable) $type[0]::EnablePrivilege($Privilege, $Disable)
} }
Export-ModuleMember -Function Repair-FilePermission, Repair-SshdConfigPermission, Repair-SshdHostKeyPermission, Repair-AuthorizedKeyPermission, Repair-UserKeyPermission, Repair-UserSshConfigPermission Export-ModuleMember -Function Repair-FilePermission, Repair-SshdConfigPermission, Repair-SshdHostKeyPermission, Repair-AuthorizedKeyPermission, Repair-UserKeyPermission, Repair-UserSshConfigPermission, Enable-Privilege, Get-UserAccount, Get-UserSID

View File

@ -1,84 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<AdminDeploymentCustomizations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.microsoft.com/wix/2011/AdminDeployment">
<BundleCustomizations TargetDir="C:\Program Files (x86)\Microsoft Visual Studio 14.0" NoCacheOnlyMode="default" NoWeb="default" NoRefresh="default" SuppressRefreshPrompt="default" Feed="default" />
<SelectableItemCustomizations>
<SelectableItemCustomization Id="VSUV3RTMV1" Hidden="no" Selected="yes" FriendlyName="Visual Studio 2015 Update 3" />
<SelectableItemCustomization Id="MicroUpdateV3.1" Selected="yes" FriendlyName="Update for Microsoft Visual Studio 2015 (KB3165756)" />
<SelectableItemCustomization Id="NativeLanguageSupport_VCV1" Hidden="no" Selected="yes" FriendlyName="Common Tools for Visual C++ 2015" />
<SelectableItemCustomization Id="Win81SDK_HiddenV1" Hidden="no" Selected="yes" FriendlyName="Windows 8.1 SDK and Universal CRT SDK" />
<SelectableItemCustomization Id="PythonToolsForVisualStudioV6" Hidden="no" Selected="no" FriendlyName="Python Tools for Visual Studio (June 2016)" />
<SelectableItemCustomization Id="WebToolsV1" Hidden="no" Selected="no" FriendlyName="Microsoft Web Developer Tools" />
<SelectableItemCustomization Id="Windows10_ToolsAndSDKV12" Hidden="no" Selected="yes" FriendlyName="Tools (1.4) and Windows 10 SDK (10.0.10586)" />
<SelectableItemCustomization Id="Win10_EmulatorV2" Hidden="no" Selected="no" FriendlyName="Emulators for Windows 10 Mobile (10.0.10586)" />
<SelectableItemCustomization Id="XamarinVSCoreV4" Hidden="no" Selected="no" FriendlyName="C#/.NET (Xamarin v4.1.0)" />
<SelectableItemCustomization Id="XamarinPT_V1" Selected="no" FriendlyName="Xamarin Preparation Tool" />
<SelectableItemCustomization Id="AndroidNDKV1" Hidden="no" Selected="no" FriendlyName="Android Native Development Kit (R10E, 32 bits)" />
<SelectableItemCustomization Id="AndroidNDK_32_V1" Hidden="no" Selected="no" FriendlyName="Android Native Development Kit (R10E, 32 bits)" />
<SelectableItemCustomization Id="AndroidSDKV1" Hidden="no" Selected="no" FriendlyName="Android SDK" />
<SelectableItemCustomization Id="AndroidSDK_API1921V1" Hidden="no" Selected="no" FriendlyName="Android SDK Setup (API Level 19 and 21)" />
<SelectableItemCustomization Id="AndroidSDK_API23V1" Hidden="no" Selected="no" FriendlyName="Android SDK Setup (API Level 23)" />
<SelectableItemCustomization Id="JavaJDKV1" Hidden="no" Selected="no" FriendlyName="Java SE Development Kit (7.0.550.13)" />
<SelectableItemCustomization Id="Node.jsV1" Hidden="no" Selected="no" FriendlyName="Joyent Node.js" />
<SelectableItemCustomization Id="VSEmu_AndroidV1.0.60404.1" Hidden="no" Selected="no" FriendlyName="Microsoft Visual Studio Emulator for Android (April 2016)" />
<SelectableItemCustomization Id="ToolsForWin81_WP80_WP81V1" Hidden="no" Selected="no" FriendlyName="Tools and Windows SDKs" />
<SelectableItemCustomization Id="GitForWindowsx64V5" Hidden="no" Selected="yes" FriendlyName="Git for Windows" />
<SelectableItemCustomization Id="GitForWindowsx86V5" Hidden="no" Selected="yes" FriendlyName="Git for Windows" />
<SelectableItemCustomization Id="GitHubVSV1" Hidden="no" Selected="yes" FriendlyName="GitHub Extension for Visual Studio" />
<SelectableItemCustomization Id="VS_SDK_GroupV5" Hidden="no" Selected="yes" FriendlyName="Visual Studio Extensibility Tools Update 3" />
<SelectableItemCustomization Id="VS_SDK_Breadcrumb_GroupV5" Selected="yes" FriendlyName="Visual Studio Extensibility Tools Update 3" />
<SelectableItemCustomization Id="Win10_VSToolsV12" Hidden="no" Selected="no" FriendlyName="Tools for Universal Windows Apps (1.4) and Windows 10 SDK (10.0.10586)" />
<SelectableItemCustomization Id="Win10SDK_HiddenV3" Selected="yes" FriendlyName="Windows 10 SDK (10.0.10586)" />
<SelectableItemCustomization Id="JavaScript_HiddenV1" Selected="no" FriendlyName="JavaScript Project System for Visual Studio" />
<SelectableItemCustomization Id="JavaScript_HiddenV11" Selected="no" FriendlyName="JavaScript Project System for Visual Studio" />
<SelectableItemCustomization Id="MDDJSDependencyHiddenV1" Selected="no" FriendlyName="MDDJSDependencyHidden" />
<SelectableItemCustomization Id="AppInsightsToolsVisualStudioHiddenRTMV1" Selected="no" FriendlyName="Application Insights Tools" />
<SelectableItemCustomization Id="AppInsightsToolsVisualStudioHiddenVSU3RTMV1" Selected="no" FriendlyName="Developer Analytics Tools v7.0.2" />
<SelectableItemCustomization Id="BlissHidden" Selected="no" FriendlyName="BlissHidden" />
<SelectableItemCustomization Id="HelpHidden" Selected="yes" FriendlyName="HelpHidden" />
<SelectableItemCustomization Id="JavaScript" Selected="yes" FriendlyName="JavascriptHidden" />
<SelectableItemCustomization Id="NetFX4Hidden" Selected="no" FriendlyName="NetFX4Hidden" />
<SelectableItemCustomization Id="NetFX45Hidden" Selected="no" FriendlyName="NetFX45Hidden" />
<SelectableItemCustomization Id="NetFX451MTPackHidden" Selected="no" FriendlyName="NetFX451MTPackHidden" />
<SelectableItemCustomization Id="NetFX451MTPackCoreHidden" Selected="no" FriendlyName="NetFX451MTPackCoreHidden" />
<SelectableItemCustomization Id="NetFX452MTPackHidden" Selected="no" FriendlyName="NetFX452MTPackHidden" />
<SelectableItemCustomization Id="NetFX46MTPackHidden" Selected="no" FriendlyName="NetFX46MTPackHidden" />
<SelectableItemCustomization Id="PortableDTPHidden" Selected="yes" FriendlyName="PortableDTPHidden" />
<SelectableItemCustomization Id="PreEmptiveDotfuscatorHidden" Selected="no" FriendlyName="PreEmptiveDotfuscatorHidden" />
<SelectableItemCustomization Id="PreEmptiveAnalyticsHidden" Selected="no" FriendlyName="PreEmptiveAnalyticsHidden" />
<SelectableItemCustomization Id="ProfilerHidden" Selected="no" FriendlyName="ProfilerHidden" />
<SelectableItemCustomization Id="RoslynLanguageServicesHidden" Selected="no" FriendlyName="RoslynLanguageServicesHidden" />
<SelectableItemCustomization Id="SDKTools3Hidden" Selected="no" FriendlyName="SDKTools3Hidden" />
<SelectableItemCustomization Id="SDKTools4Hidden" Selected="no" FriendlyName="SDKTools4Hidden" />
<SelectableItemCustomization Id="WCFDataServicesHidden" Selected="no" FriendlyName="WCFDataServicesHidden" />
<SelectableItemCustomization Id="VSUV1PreReqV1" Selected="no" FriendlyName="Visual Studio 2015 Update 1 Prerequisite" />
<SelectableItemCustomization Id="MicroUpdateV3" Selected="no" FriendlyName="MicroUpdate 3.0 for Visual Studio 2015 Update 3" />
<SelectableItemCustomization Id="NativeLanguageSupport_MFCV1" Hidden="no" Selected="no" FriendlyName="Microsoft Foundation Classes for C++" />
<SelectableItemCustomization Id="NativeLanguageSupport_XPV1" Hidden="no" Selected="no" FriendlyName="Windows XP Support for C++" />
<SelectableItemCustomization Id="FSharpV1" Hidden="no" Selected="no" FriendlyName="Visual F#" />
<SelectableItemCustomization Id="ClickOnceV1" Hidden="no" Selected="no" FriendlyName="ClickOnce Publishing Tools" />
<SelectableItemCustomization Id="SQLV1" Hidden="no" Selected="no" FriendlyName="Microsoft SQL Server Data Tools" />
<SelectableItemCustomization Id="PowerShellToolsV1" Hidden="no" Selected="no" FriendlyName="PowerShell Tools for Visual Studio" />
<SelectableItemCustomization Id="SilverLight_Developer_KitV1" Hidden="no" Selected="no" FriendlyName="Silverlight Development Kit" />
<SelectableItemCustomization Id="Win10_EmulatorV1" Selected="no" FriendlyName="Emulators for Windows 10 Mobile (10.0.10240)" />
<SelectableItemCustomization Id="MDDJSCoreV11" Hidden="no" Selected="no" FriendlyName="HTML/JavaScript (Apache Cordova) Update 10" />
<SelectableItemCustomization Id="AndroidNDK11C_V1" Hidden="no" Selected="no" FriendlyName="Android Native Development Kit (R11C, 32 bits)" />
<SelectableItemCustomization Id="AndroidNDK11C_32_V1" Hidden="no" Selected="no" FriendlyName="Android Native Development Kit (R11C, 32 bits)" />
<SelectableItemCustomization Id="AndroidNDK11C_64_V1" Hidden="no" Selected="no" FriendlyName="Android Native Development Kit (R11C, 64 bits)" />
<SelectableItemCustomization Id="AndroidNDK_64_V1" Hidden="no" Selected="no" FriendlyName="Android Native Development Kit (R10E, 64 bits)" />
<SelectableItemCustomization Id="AndroidSDK_API22V1" Hidden="no" Selected="no" FriendlyName="Android SDK Setup (API Level 22)" />
<SelectableItemCustomization Id="AntV1" Hidden="no" Selected="no" FriendlyName="Apache Ant (1.9.3)" />
<SelectableItemCustomization Id="L_MDDCPlusPlus_iOS_V7" Hidden="no" Selected="no" FriendlyName="Visual C++ iOS Development (Update 3)" />
<SelectableItemCustomization Id="L_MDDCPlusPlus_Android_V7" Hidden="no" Selected="no" FriendlyName="Visual C++ Android Development (Update 3)" />
<SelectableItemCustomization Id="L_MDDCPlusPlus_ClangC2_V5" Hidden="no" Selected="no" FriendlyName="Clang with Microsoft CodeGen (May 2016)" />
<SelectableItemCustomization Id="L_IncrediBuild_V1" Selected="no" FriendlyName="IncrediBuild" />
<SelectableItemCustomization Id="WebSocket4NetV1" Hidden="no" Selected="no" FriendlyName="WebSocket4Net" />
<SelectableItemCustomization Id="WindowsPhone81EmulatorsV1" Hidden="no" Selected="no" FriendlyName="Emulators for Windows Phone 8.1" />
<SelectableItemCustomization Id="Win10SDK_HiddenV1" Hidden="no" Selected="no" FriendlyName="Windows 10 SDK (10.0.10240)" />
<SelectableItemCustomization Id="Win10SDK_HiddenV2" Selected="no" FriendlyName="Windows 10 SDK (10.0.10586)" />
<SelectableItemCustomization Id="Win10SDK_VisibleV1" Hidden="no" Selected="no" FriendlyName="Windows 10 SDK 10.0.10240" />
<SelectableItemCustomization Id="UWPPatch_KB3073097_HiddenV3" Selected="no" FriendlyName="KB3073097" />
<SelectableItemCustomization Id="AppInsightsToolsVSWinExpressHiddenVSU3RTMV1" Selected="no" FriendlyName="Developer Analytics Tools v7.0.2" />
<SelectableItemCustomization Id="AppInsightsToolsVWDExpressHiddenVSU3RTMV1" Selected="no" FriendlyName="Developer Analytics Tools v7.0.2" />
</SelectableItemCustomizations>
</AdminDeploymentCustomizations>

View File

@ -246,6 +246,7 @@
<ClCompile Include="$(OpenSSH-Src-Path)sshlogin.c" /> <ClCompile Include="$(OpenSSH-Src-Path)sshlogin.c" />
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32_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)contrib\win32\win32compat\wmain_sshd.c" />
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32_monitor_wrap.c" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="version.rc" /> <ResourceCompile Include="version.rc" />

View File

@ -150,6 +150,9 @@
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32_sshpty.c"> <ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32_sshpty.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32_monitor_wrap.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="version.rc"> <ResourceCompile Include="version.rc">

View File

@ -120,3 +120,4 @@ Subsystem sftp sftp-server.exe
# AllowTcpForwarding no # AllowTcpForwarding no
# ForceCommand cvs server # ForceCommand cvs server
# PubkeyAcceptedKeyTypes ssh-ed25519* # PubkeyAcceptedKeyTypes ssh-ed25519*
hostkeyagent \\.\pipe\openssh-ssh-agent

Binary file not shown.

View File

@ -114,9 +114,8 @@ int
fileio_connect(struct w32_io* pio, char* name) fileio_connect(struct w32_io* pio, char* name)
{ {
wchar_t* name_w = NULL; wchar_t* name_w = NULL;
wchar_t pipe_name[PATH_MAX];
HANDLE h = INVALID_HANDLE_VALUE; HANDLE h = INVALID_HANDLE_VALUE;
int ret = 0, r; int ret = 0;
if (pio->handle != 0 && pio->handle != INVALID_HANDLE_VALUE) { if (pio->handle != 0 && pio->handle != INVALID_HANDLE_VALUE) {
debug3("fileio_connect called in unexpected state, pio = %p", pio); debug3("fileio_connect called in unexpected state, pio = %p", pio);
@ -129,16 +128,9 @@ fileio_connect(struct w32_io* pio, char* name)
errno = ENOMEM; errno = ENOMEM;
return -1; return -1;
} }
r = _snwprintf_s(pipe_name, PATH_MAX, PATH_MAX, L"\\\\.\\pipe\\%ls", name_w);
if (r < 0 || r >= PATH_MAX) {
debug3("cannot create pipe name with %s", name);
errno = EOTHER;
return -1;
}
do { do {
h = CreateFileW(pipe_name, GENERIC_READ | GENERIC_WRITE, 0, h = CreateFileW(name_w, GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED | SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION, NULL); NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED | SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION, NULL);
if (h != INVALID_HANDLE_VALUE) if (h != INVALID_HANDLE_VALUE)

View File

@ -478,11 +478,23 @@ strmode(mode_t mode, char *p)
break; break;
} }
/* The below code is commented as the group, other is not applicable on the windows. /* group, other are not applicable on the windows */
* As of now we are keeping "*" for everything.
* TODO - figure out if there is a better option /* usr */
*/ if (mode & S_IREAD)
const char *permissions = "********* "; *p++ = 'r';
else
*p++ = '-';
if (mode & S_IWRITE)
*p++ = 'w';
else
*p++ = '-';
if (mode & S_IEXEC)
*p++ = 'x';
else
*p++ = '-';
const char *permissions = "****** ";
for(int i = 0; i < strlen(permissions); i++) for(int i = 0; i < strlen(permissions); i++)
*p++ = permissions[i]; *p++ = permissions[i];
@ -950,7 +962,8 @@ w32_strerror(int errnum)
} }
char * char *
readpassphrase(const char *prompt, char *outBuf, size_t outBufLen, int flags) { readpassphrase(const char *prompt, char *outBuf, size_t outBufLen, int flags)
{
int current_index = 0; int current_index = 0;
char ch; char ch;
wchar_t* wtmp = NULL; wchar_t* wtmp = NULL;

View File

@ -0,0 +1,8 @@
/*
* Definitions for IPC between sshd and privileged agent
*/
#pragma once
#define SSH_PRIV_AGENT_MSG_ID 0
#define PUBKEY_AUTH_REQUEST "pubkey"
#define LOAD_USER_PROFILE_REQUEST "loadprofile"

View File

@ -102,6 +102,9 @@ struct key_translation keys[] = {
{ L"\x1b[B", VK_DOWN, 0 , 0}, { L"\x1b[B", VK_DOWN, 0 , 0},
{ L"\x1b[C", VK_RIGHT, 0 , 0}, { L"\x1b[C", VK_RIGHT, 0 , 0},
{ L"\x1b[D", VK_LEFT, 0 , 0}, { L"\x1b[D", VK_LEFT, 0 , 0},
{ L"\x1b[F", VK_END, 0 , 0 }, /* KeyPad END */
{ L"\x1b[H", VK_HOME, 0 , 0 }, /* KeyPad HOME */
{ L"\x1b[Z", 0, 0 , 0 }, /* ignore Shift+TAB */
{ L"\x1b[1~", VK_HOME, 0 , 0}, { L"\x1b[1~", VK_HOME, 0 , 0},
{ L"\x1b[2~", VK_INSERT, 0 , 0}, { L"\x1b[2~", VK_INSERT, 0 , 0},
{ L"\x1b[3~", VK_DELETE, 0 , 0}, { L"\x1b[3~", VK_DELETE, 0 , 0},
@ -120,11 +123,17 @@ struct key_translation keys[] = {
{ L"\x1b[21~", VK_F10, 0 , 0}, { L"\x1b[21~", VK_F10, 0 , 0},
{ L"\x1b[23~", VK_F11, 0 , 0}, { L"\x1b[23~", VK_F11, 0 , 0},
{ L"\x1b[24~", VK_F12, 0 , 0}, { L"\x1b[24~", VK_F12, 0 , 0},
{ L"\x1bOP", VK_F1, 0 , 0 },
{ L"\x1bOQ", VK_F2, 0 , 0 },
{ L"\x1bOR", VK_F3, 0 , 0 },
{ L"\x1bOS", VK_F4, 0 , 0 },
{ L"\x1b", VK_ESCAPE, L'\x1b' , 0} { L"\x1b", VK_ESCAPE, L'\x1b' , 0}
}; };
static SHORT lastX = 0; static SHORT lastX = 0;
static SHORT lastY = 0; static SHORT lastY = 0;
static wchar_t cmd_exe_path[PATH_MAX];
SHORT currentLine = 0; SHORT currentLine = 0;
consoleEvent* head = NULL; consoleEvent* head = NULL;
consoleEvent* tail = NULL; consoleEvent* tail = NULL;
@ -939,6 +948,19 @@ cleanup:
return 0; return 0;
} }
wchar_t *
w32_cmd_path()
{
ZeroMemory(cmd_exe_path, PATH_MAX);
if (!GetSystemDirectory(cmd_exe_path, sizeof(cmd_exe_path))) {
printf("GetSystemDirectory failed");
exit(255);
}
wcscat_s(cmd_exe_path, sizeof(cmd_exe_path), L"\\cmd.exe");
return cmd_exe_path;
}
int int
start_with_pty(wchar_t *command) start_with_pty(wchar_t *command)
{ {
@ -1004,9 +1026,8 @@ start_with_pty(wchar_t *command)
/* disable inheritance on pipe_in*/ /* disable inheritance on pipe_in*/
GOTO_CLEANUP_ON_FALSE(SetHandleInformation(pipe_in, HANDLE_FLAG_INHERIT, 0)); GOTO_CLEANUP_ON_FALSE(SetHandleInformation(pipe_in, HANDLE_FLAG_INHERIT, 0));
/*TODO - pick this up from system32*/
cmd[0] = L'\0'; cmd[0] = L'\0';
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L"cmd.exe")); GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, w32_cmd_path()));
if (command) { if (command) {
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L" /c")); GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L" /c"));
@ -1179,9 +1200,8 @@ start_withno_pty(wchar_t *command)
/* if above failed with FILE_NOT_FOUND, try running the provided command under cmd*/ /* if above failed with FILE_NOT_FOUND, try running the provided command under cmd*/
if (run_under_cmd) { if (run_under_cmd) {
/*TODO - pick this up from system32*/
cmd[0] = L'\0'; cmd[0] = L'\0';
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L"cmd.exe")); GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, w32_cmd_path()));
if (command) { if (command) {
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L" /c")); GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L" /c"));
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L" ")); GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L" "));

View File

@ -16,6 +16,6 @@ int process_request_identities(struct sshbuf*, struct sshbuf*, struct agent_conn
int process_sign_request(struct sshbuf*, struct sshbuf*, struct agent_connection*); int process_sign_request(struct sshbuf*, struct sshbuf*, struct agent_connection*);
int process_remove_key(struct sshbuf*, struct sshbuf*, struct agent_connection*); int process_remove_key(struct sshbuf*, struct sshbuf*, struct agent_connection*);
int process_remove_all(struct sshbuf*, struct sshbuf*, struct agent_connection*); int process_remove_all(struct sshbuf*, struct sshbuf*, struct agent_connection*);
int process_authagent_request(struct sshbuf*, struct sshbuf*, struct agent_connection*); int process_privagent_request(struct sshbuf*, struct sshbuf*, struct agent_connection*);
/* auth */ /* auth */

View File

@ -37,7 +37,7 @@
static HANDLE ioc_port = NULL; static HANDLE ioc_port = NULL;
static BOOL debug_mode = FALSE; static BOOL debug_mode = FALSE;
#define AGENT_PIPE_ID L"\\\\.\\pipe\\ssh-agent" #define AGENT_PIPE_ID L"\\\\.\\pipe\\openssh-ssh-agent"
static HANDLE event_stop_agent; static HANDLE event_stop_agent;
static OVERLAPPED ol; static OVERLAPPED ol;
@ -168,12 +168,14 @@ agent_cleanup_connection(struct agent_connection* con)
{ {
debug("connection %p clean up", con); debug("connection %p clean up", con);
CloseHandle(con->pipe_handle); CloseHandle(con->pipe_handle);
if (con->hProfile) if (con->profile_handle)
UnloadUserProfile(con->auth_token, con->hProfile); UnloadUserProfile(con->profile_token, con->profile_handle);
if (con->auth_token) if (con->profile_token)
CloseHandle(con->auth_token); CloseHandle(con->profile_token);
if (con->client_impersonation_token) if (con->client_impersonation_token)
CloseHandle(con->client_impersonation_token); CloseHandle(con->client_impersonation_token);
if (con->client_process_handle)
CloseHandle(con->client_process_handle);
free(con); free(con);
CloseHandle(ioc_port); CloseHandle(ioc_port);
ioc_port = NULL; ioc_port = NULL;
@ -251,13 +253,13 @@ get_con_client_info(struct agent_connection* con)
DWORD sshd_sid_len = 0; DWORD sshd_sid_len = 0;
PSID sshd_sid = NULL; PSID sshd_sid = NULL;
SID_NAME_USE nuse; SID_NAME_USE nuse;
HANDLE client_primary_token = NULL, client_impersonation_token = NULL, client_proc_handle = NULL; HANDLE client_primary_token = NULL, client_impersonation_token = NULL, client_process_handle = NULL;
TOKEN_USER* info = NULL; TOKEN_USER* info = NULL;
BOOL isMember = FALSE; BOOL isMember = FALSE;
if (GetNamedPipeClientProcessId(con->pipe_handle, &client_pid) == FALSE || if (GetNamedPipeClientProcessId(con->pipe_handle, &client_pid) == FALSE ||
(client_proc_handle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, client_pid)) == NULL || (client_process_handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_DUP_HANDLE, FALSE, client_pid)) == NULL ||
OpenProcessToken(client_proc_handle, TOKEN_QUERY | TOKEN_DUPLICATE, &client_primary_token) == FALSE || OpenProcessToken(client_process_handle, TOKEN_QUERY | TOKEN_DUPLICATE, &client_primary_token) == FALSE ||
DuplicateToken(client_primary_token, SecurityImpersonation, &client_impersonation_token) == FALSE) { DuplicateToken(client_primary_token, SecurityImpersonation, &client_impersonation_token) == FALSE) {
error("cannot retrieve client impersonatin token"); error("cannot retrieve client impersonatin token");
goto done; goto done;
@ -341,15 +343,19 @@ done:
free(ref_dom); free(ref_dom);
if (info) if (info)
free(info); free(info);
if (client_proc_handle)
CloseHandle(client_proc_handle);
if (client_primary_token) if (client_primary_token)
CloseHandle(client_primary_token); CloseHandle(client_primary_token);
if (r == 0) if (r == 0) {
con->client_process_handle = client_process_handle;
con->client_impersonation_token = client_impersonation_token; con->client_impersonation_token = client_impersonation_token;
else if (client_impersonation_token) }
CloseHandle(client_impersonation_token); else {
if (client_process_handle)
CloseHandle(client_process_handle);
if (client_impersonation_token)
CloseHandle(client_impersonation_token);
}
return r; return r;
} }

View File

@ -4,17 +4,18 @@
#include "log.h" #include "log.h"
#define MAX_MESSAGE_SIZE 256 * 1024 #define MAX_MESSAGE_SIZE 256 * 1024
#define SSH_ROOT L"SOFTWARE\\SSH" #define SSH_ROOT L"SOFTWARE\\OpenSSH"
#define SSH_AGENT_ROOT SSH_ROOT L"\\Agent" #define SSH_AGENT_ROOT SSH_ROOT L"\\Agent"
#define SSH_KEYS_KEY L"Keys" #define SSH_KEYS_KEY L"Keys"
#define SSH_KEYS_ROOT SSH_ROOT L"\\" SSH_KEYS_KEY #define SSH_KEYS_ROOT SSH_AGENT_ROOT L"\\" SSH_KEYS_KEY
#define HEADER_SIZE 4 #define HEADER_SIZE 4
struct agent_connection { struct agent_connection {
OVERLAPPED ol; OVERLAPPED ol;
HANDLE pipe_handle; HANDLE pipe_handle;
HANDLE client_impersonation_token; HANDLE client_impersonation_token;
HANDLE client_process_handle;
struct { struct {
DWORD num_bytes; DWORD num_bytes;
DWORD transferred; DWORD transferred;
@ -36,8 +37,9 @@ struct agent_connection {
SYSTEM, /* client is running as System */ SYSTEM, /* client is running as System */
SERVICE, /* client is running as LS or NS */ SERVICE, /* client is running as LS or NS */
} client_type; } client_type;
HANDLE auth_token; /* user profile related members */
HANDLE hProfile; HANDLE profile_token;
HANDLE profile_handle;
}; };
void agent_connection_on_io(struct agent_connection*, DWORD, OVERLAPPED*); void agent_connection_on_io(struct agent_connection*, DWORD, OVERLAPPED*);

View File

@ -72,6 +72,12 @@ mm_user_key_allowed(struct passwd *pw, Key *k, int i)
return 0; return 0;
} }
void* mm_auth_pubkey(const char* user_name, const struct sshkey *key,
const u_char *sig, size_t slen, struct sshbuf* b)
{
return NULL;
}
int int
kexgex_server(struct ssh * sh) { kexgex_server(struct ssh * sh) {
return -1; return -1;

View File

@ -39,6 +39,7 @@
#include "agent-request.h" #include "agent-request.h"
#include "key.h" #include "key.h"
#include "inc\utf.h" #include "inc\utf.h"
#include "..\priv-agent.h"
#pragma warning(push, 3) #pragma warning(push, 3)
@ -83,9 +84,11 @@ done:
} }
void static HANDLE
LoadProfile(struct agent_connection* con, wchar_t* user, wchar_t* domain) { LoadProfile(HANDLE user_token, wchar_t* user, wchar_t* domain) {
PROFILEINFOW profileInfo; PROFILEINFOW profileInfo;
HANDLE ret = NULL;
profileInfo.dwFlags = PI_NOUI; profileInfo.dwFlags = PI_NOUI;
profileInfo.lpProfilePath = NULL; profileInfo.lpProfilePath = NULL;
profileInfo.lpUserName = user; profileInfo.lpUserName = user;
@ -96,12 +99,16 @@ LoadProfile(struct agent_connection* con, wchar_t* user, wchar_t* domain) {
profileInfo.dwSize = sizeof(profileInfo); profileInfo.dwSize = sizeof(profileInfo);
EnablePrivilege("SeBackupPrivilege", 1); EnablePrivilege("SeBackupPrivilege", 1);
EnablePrivilege("SeRestorePrivilege", 1); EnablePrivilege("SeRestorePrivilege", 1);
if (LoadUserProfileW(con->auth_token, &profileInfo) == FALSE) if (LoadUserProfileW(user_token, &profileInfo) == FALSE) {
debug("Loading user (%ls,%ls) profile failed ERROR: %d", user, domain, GetLastError()); debug("Loading user (%ls,%ls) profile failed ERROR: %d", user, domain, GetLastError());
goto done;
}
else else
con->hProfile = profileInfo.hProfile; ret = profileInfo.hProfile;
done:
EnablePrivilege("SeBackupPrivilege", 0); EnablePrivilege("SeBackupPrivilege", 0);
EnablePrivilege("SeRestorePrivilege", 0); EnablePrivilege("SeRestorePrivilege", 0);
return ret;
} }
#define MAX_USER_LEN 64 #define MAX_USER_LEN 64
@ -238,73 +245,13 @@ done:
return dup_t; return dup_t;
} }
/* TODO - SecureZeroMemory password */
int process_passwordauth_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
char *user = NULL, *domain = NULL, *pwd = NULL;
size_t user_len, pwd_len;
wchar_t *user_utf16 = NULL, *udom_utf16 = NULL, *pwd_utf16 = NULL, *tmp;
int r = -1;
HANDLE token = 0, dup_token;
if (sshbuf_get_cstring(request, &user, &user_len) != 0 ||
sshbuf_get_cstring(request, &pwd, &pwd_len) != 0 ||
user_len == 0 ||
pwd_len == 0 ||
user_len > MAX_USER_LEN + MAX_FQDN_LEN ||
pwd_len > MAX_PW_LEN) {
debug("bad password auth request");
goto done;
}
if ((user_utf16 = utf8_to_utf16(user)) == NULL ||
(pwd_utf16 = utf8_to_utf16(pwd)) == NULL) {
debug("out of memory");
goto done;
}
if ((tmp = wcschr(user_utf16, L'@') ) != NULL ) {
udom_utf16 = tmp + 1;
*tmp = L'\0';
}
if (LogonUserW(user_utf16, udom_utf16, pwd_utf16, LOGON32_LOGON_NETWORK_CLEARTEXT, LOGON32_PROVIDER_DEFAULT, &token) == FALSE) {
debug("failed to logon user: %ls domain: %ls", user_utf16, udom_utf16);
goto done;
}
if ((dup_token = duplicate_token_for_client(con, token)) == NULL)
goto done;
if (sshbuf_put_u32(response, (int)(intptr_t)dup_token) != 0)
goto done;
con->auth_token = token;
LoadProfile(con, user_utf16, udom_utf16);
r = 0;
done:
/* TODO Fix this hacky protocol*/
if ((r == -1) && (sshbuf_put_u8(response, SSH_AGENT_FAILURE) == 0))
r = 0;
if (user)
free(user);
if (pwd)
free(pwd);
if (user_utf16)
free(user_utf16);
if (pwd_utf16)
free(pwd_utf16);
return r;
}
int process_pubkeyauth_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) { int process_pubkeyauth_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
int r = -1; int r = -1;
char *key_blob, *user, *sig, *blob; char *key_blob, *user, *sig, *blob;
size_t key_blob_len, user_len, sig_len, blob_len; size_t key_blob_len, user_len, sig_len, blob_len;
struct sshkey *key = NULL; struct sshkey *key = NULL;
HANDLE token = NULL, dup_token = NULL; HANDLE token = NULL, dup_token = NULL;
wchar_t *user_utf16 = NULL, *udom_utf16 = NULL, *tmp; wchar_t *user_utf16 = NULL;
PWSTR wuser_home = NULL; PWSTR wuser_home = NULL;
@ -346,14 +293,6 @@ int process_pubkeyauth_request(struct sshbuf* request, struct sshbuf* response,
if (sshbuf_put_u32(response, (int)(intptr_t)dup_token) != 0) if (sshbuf_put_u32(response, (int)(intptr_t)dup_token) != 0)
goto done; goto done;
con->auth_token = token;
token = NULL;
if ((tmp = wcschr(user_utf16, L'@')) != NULL) {
udom_utf16 = tmp + 1;
*tmp = L'\0';
}
LoadProfile(con, user_utf16, udom_utf16);
r = 0; r = 0;
done: done:
/* TODO Fix this hacky protocol*/ /* TODO Fix this hacky protocol*/
@ -373,7 +312,60 @@ done:
return r; return r;
} }
int process_authagent_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) { int process_loadprofile_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
int r = 0, success = 0;
char *user;
size_t user_len;
u_int32_t user_token_int = 0;
HANDLE user_token = NULL;
wchar_t *user_utf16 = NULL, *dom_utf16 = NULL, *tmp;
/* is profile already loaded */
if (con->profile_handle) {
success = 1;
goto done;
}
if (sshbuf_get_cstring(request, &user, &user_len) != 0 ||
user_len > MAX_USER_LEN ||
sshbuf_get_u32(request, &user_token_int) != 0){
debug("invalid loadprofile request");
goto done;
}
if (DuplicateHandle(con->client_process_handle, (HANDLE)(INT_PTR)user_token_int, GetCurrentProcess(),
&user_token, TOKEN_QUERY | TOKEN_IMPERSONATE | TOKEN_DUPLICATE, FALSE, 0) == FALSE) {
debug("cannot duplicate user token, error: %d", GetLastError());
goto done;
}
if ((user_utf16 = utf8_to_utf16(user)) == NULL) {
debug("out of memory");
goto done;
}
/* split user and domain */
if ((tmp = wcschr(user_utf16, L'@')) != NULL) {
dom_utf16 = tmp + 1;
*tmp = L'\0';
}
if ((con->profile_handle = LoadProfile(user_token, user_utf16, dom_utf16)) == NULL)
goto done;
con->profile_token = user_token;
user_token = NULL;
success = 1;
done:
if (sshbuf_put_u8(response, success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE) != 0)
r = -1;
if (user_token)
CloseHandle(user_token);
return r;
}
int process_privagent_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
char *opn; char *opn;
size_t opn_len; size_t opn_len;
if (sshbuf_get_string_direct(request, &opn, &opn_len) != 0) { if (sshbuf_get_string_direct(request, &opn, &opn_len) != 0) {
@ -383,14 +375,14 @@ int process_authagent_request(struct sshbuf* request, struct sshbuf* response, s
/* allow only admins and NT Service\sshd to send auth requests */ /* allow only admins and NT Service\sshd to send auth requests */
if (con->client_type != SSHD_SERVICE && con->client_type != ADMIN_USER) { if (con->client_type != SSHD_SERVICE && con->client_type != ADMIN_USER) {
error("cannot authenticate: client process is not admin or sshd"); error("cannot process request: client process is not admin or sshd");
return -1; return -1;
} }
if (memcmp(opn, PUBKEY_AUTH_REQUEST, opn_len) == 0) if (memcmp(opn, PUBKEY_AUTH_REQUEST, opn_len) == 0)
return process_pubkeyauth_request(request, response, con); return process_pubkeyauth_request(request, response, con);
else if (memcmp(opn, PASSWD_AUTH_REQUEST, opn_len) == 0) else if (memcmp(opn, LOAD_USER_PROFILE_REQUEST, opn_len) == 0)
return process_passwordauth_request(request, response, con); return process_loadprofile_request(request, response, con);
else { else {
debug("unknown auth request: %s", opn); debug("unknown auth request: %s", opn);
return -1; return -1;

View File

@ -30,6 +30,7 @@
*/ */
#include "agent.h" #include "agent.h"
#include "agent-request.h" #include "agent-request.h"
#include "..\priv-agent.h"
#pragma warning(push, 3) #pragma warning(push, 3)
@ -168,8 +169,8 @@ process_request(struct agent_connection* con)
case SSH2_AGENTC_REMOVE_ALL_IDENTITIES: case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
r = process_remove_all(request, response, con); r = process_remove_all(request, response, con);
break; break;
case SSH_AGENT_AUTHENTICATE: case SSH_PRIV_AGENT_MSG_ID:
r = process_authagent_request(request, response, con); r = process_privagent_request(request, response, con);
break; break;
default: default:
debug("unknown agent request %d", type); debug("unknown agent request %d", type);

View File

@ -0,0 +1,214 @@
/*
* Author: Manoj Ampalam <manoj.ampalam@microsoft.com>
* mm_* routines that delegate privileged operations to privileged
* agent.
*
* Copyright (c) 2015 Microsoft Corp.
* All rights reserved
*
* Microsoft openssh win32 port
*
* 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.
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/un.h>
#include <sys/uio.h>
#include <errno.h>
#include <pwd.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#ifdef WITH_OPENSSL
#include <openssl/bn.h>
#include <openssl/dh.h>
#include <openssl/evp.h>
#endif
#include "openbsd-compat/sys-queue.h"
#include "xmalloc.h"
#include "ssh.h"
#ifdef WITH_OPENSSL
#include "dh.h"
#endif
#include "buffer.h"
#include "key.h"
#include "cipher.h"
#include "kex.h"
#include "hostfile.h"
#include "auth.h"
#include "auth-options.h"
#include "packet.h"
#include "mac.h"
#include "log.h"
#include "auth-pam.h"
#include "monitor_wrap.h"
#include "atomicio.h"
#include "monitor_fdpass.h"
#include "misc.h"
#include "uuencode.h"
#include "channels.h"
#include "session.h"
#include "servconf.h"
#include "ssherr.h"
#include "priv-agent.h"
#include "authfd.h"
int priv_agent_sock = -1;
int ssh_request_reply(int, struct sshbuf *, struct sshbuf *);
/*
* Get socket connected to privileged agent
* In Windows, this is implemented within ssh-agent
* that server both as a key-agent (like in Unix) and
* privileged agent.
* This is a temporary accomodation until Windows has
* Unix like privilege separation (monitor and less
* privileged worker)
*/
int get_priv_agent_sock()
{
extern int auth_sock;
char env_value[12]; /* enough to accomodate "ssh-agent"*/
size_t tmp;
if (priv_agent_sock != -1)
return priv_agent_sock;
/* check if auth_sock is populated and connected to "ssh-agent"*/
if (auth_sock != -1 &&
getenv_s(&tmp, env_value, 12, SSH_AUTHSOCKET_ENV_NAME) == 0 &&
strncmp(env_value, "ssh-agent", 12) == 0 )
priv_agent_sock = auth_sock;
else {
struct sockaddr_un sunaddr;
int sock;
memset(&sunaddr, 0, sizeof(sunaddr));
sunaddr.sun_family = AF_UNIX;
strlcpy(sunaddr.sun_path, "\\\\.\\pipe\\openssh-ssh-agent", sizeof(sunaddr.sun_path));
if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
debug("%s: unable to create AF_UNIX socket, errno:%d", __func__, errno);
return -1;
}
/* close on exec */
if (fcntl(sock, F_SETFD, FD_CLOEXEC) == -1 ||
connect(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
close(sock);
debug("%s: unable to connect to privileged agent, errno:%d", __func__, errno);
return -1;
}
priv_agent_sock = sock;
}
return priv_agent_sock;
}
void* mm_auth_pubkey(const char* user_name, const struct sshkey *key,
const u_char *sig, size_t slen, struct sshbuf* b)
{
/* Pass key challenge material to privileged agent to retrieve token upon successful authentication */
struct sshbuf *msg = NULL;
u_char *blob = NULL;
size_t blen = 0;
DWORD token = 0;
int agent_fd;
while (1) {
if ((agent_fd = get_priv_agent_sock()) == -1)
break;
msg = sshbuf_new();
if (!msg)
fatal("%s: out of memory", __func__);
if (sshbuf_put_u8(msg, SSH_PRIV_AGENT_MSG_ID) != 0 ||
sshbuf_put_cstring(msg, PUBKEY_AUTH_REQUEST) != 0 ||
sshkey_to_blob(key, &blob, &blen) != 0 ||
sshbuf_put_string(msg, blob, blen) != 0 ||
sshbuf_put_cstring(msg, user_name) != 0 ||
sshbuf_put_string(msg, sig, slen) != 0 ||
sshbuf_put_string(msg, sshbuf_ptr(b), sshbuf_len(b)) != 0 ||
ssh_request_reply(agent_fd, msg, msg) != 0) {
debug("unable to send pubkeyauth request");
break;
}
if (sshbuf_get_u32(msg, &token) != 0)
break;
debug3("%s authenticated via pubkey", user_name);
break;
}
if (blob)
free(blob);
if (msg)
sshbuf_free(msg);
return (void*)(INT_PTR)token;
}
int mm_load_profile(const char* user_name, u_int token)
{
struct sshbuf *msg = NULL;
int agent_fd;
u_char result = 0;
while (1) {
if ((agent_fd = get_priv_agent_sock()) == -1)
break;
msg = sshbuf_new();
if (!msg)
fatal("%s: out of memory", __func__);
if (sshbuf_put_u8(msg, SSH_PRIV_AGENT_MSG_ID) != 0 ||
sshbuf_put_cstring(msg, LOAD_USER_PROFILE_REQUEST) != 0 ||
sshbuf_put_cstring(msg, user_name) != 0 ||
sshbuf_put_u32(msg, token) != 0 ||
ssh_request_reply(agent_fd, msg, msg) != 0) {
debug("unable to send loadprofile request %s", user_name);
break;
}
if (sshbuf_get_u8(msg, &result) != 0 || result == SSH_AGENT_FAILURE) {
debug("agent failed to load profile for user %s", user_name);
break;
}
break;
}
return result;
}

View File

@ -51,7 +51,7 @@ wmain(int argc, wchar_t **wargv) {
} }
if (getenv("SSH_AUTH_SOCK") == NULL) if (getenv("SSH_AUTH_SOCK") == NULL)
_putenv("SSH_AUTH_SOCK=ssh-agent"); _putenv("SSH_AUTH_SOCK=\\\\.\\pipe\\openssh-ssh-agent");
w32posix_initialize(); w32posix_initialize();

View File

@ -108,9 +108,6 @@ int sshd_main(int argc, wchar_t **wargv) {
argv[i] = utf16_to_utf8(wargv[i]); argv[i] = utf16_to_utf8(wargv[i]);
} }
if (getenv("SSH_AUTH_SOCK") == NULL)
_putenv("SSH_AUTH_SOCK=ssh-agent");
w32posix_initialize(); w32posix_initialize();
if (getenv("SSHD_REMSOC")) if (getenv("SSHD_REMSOC"))
is_child = 1; is_child = 1;

View File

@ -98,4 +98,9 @@ int mm_bsdauth_respond(void *, u_int, char **);
int mm_skey_query(void *, char **, char **, u_int *, char ***, u_int **); int mm_skey_query(void *, char **, char **, u_int *, char ***, u_int **);
int mm_skey_respond(void *, u_int, char **); int mm_skey_respond(void *, u_int, char **);
/* Windows specific */
void* mm_auth_pubkey(const char*, const struct sshkey *, const u_char *, size_t,
struct sshbuf*);
int mm_load_profile(const char*, u_int );
#endif /* _MM_WRAP_H_ */ #endif /* _MM_WRAP_H_ */

View File

@ -1,4 +1,6 @@
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force -DisableNameChecking If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force
Import-Module OpenSSHUtils -Force
$tC = 1 $tC = 1
$tI = 0 $tI = 0
$suite = "authorized_keys_fileperm" $suite = "authorized_keys_fileperm"
@ -6,7 +8,7 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
BeforeAll { BeforeAll {
if($OpenSSHTestInfo -eq $null) if($OpenSSHTestInfo -eq $null)
{ {
Throw "`$OpenSSHTestInfo is null. Please run Setup-OpenSSHTestEnvironment to setup test environment." Throw "`$OpenSSHTestInfo is null. Please run Set-OpenSSHTestEnvironment to set test environments."
} }
$testDir = "$($OpenSSHTestInfo["TestDataPath"])\$suite" $testDir = "$($OpenSSHTestInfo["TestDataPath"])\$suite"
@ -22,17 +24,31 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
$ssouser = $OpenSSHTestInfo["SSOUser"] $ssouser = $OpenSSHTestInfo["SSOUser"]
$PwdUser = $OpenSSHTestInfo["PasswdUser"] $PwdUser = $OpenSSHTestInfo["PasswdUser"]
$ssouserProfile = $OpenSSHTestInfo["SSOUserProfile"] $ssouserProfile = $OpenSSHTestInfo["SSOUserProfile"]
Remove-Item -Path (Join-Path $testDir "*$fileName") -Force -ErrorAction ignore Remove-Item -Path (Join-Path $testDir "*$fileName") -Force -ErrorAction SilentlyContinue
$platform = Get-Platform
$skip = ($platform -eq [PlatformType]::Windows) -and ($PSVersionTable.PSVersion.Major -le 2)
if(($platform -eq [PlatformType]::Windows) -and ($psversiontable.BuildVersion.Major -le 6))
{
#suppress the firewall blocking dialogue on win7
netsh advfirewall firewall add rule name="sshd" program="$($OpenSSHTestInfo['OpenSSHBinPath'])\sshd.exe" protocol=any action=allow dir=in
}
} }
AfterEach { $tI++ } AfterEach { $tI++ }
AfterAll {
if(($platform -eq [PlatformType]::Windows) -and ($psversiontable.BuildVersion.Major -le 6))
{
netsh advfirewall firewall delete rule name="sshd" program="$($OpenSSHTestInfo['OpenSSHBinPath'])\sshd.exe" protocol=any dir=in
}
}
Context "Authorized key file permission" { Context "Authorized key file permission" {
BeforeAll { BeforeAll {
$systemAccount = New-Object System.Security.Principal.NTAccount("NT AUTHORITY", "SYSTEM") $systemSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::LocalSystemSid)
$adminAccount = New-Object System.Security.Principal.NTAccount("BUILTIN","Administrators") $adminsSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid)
$objUser = New-Object System.Security.Principal.NTAccount($ssouser) $currentUserSid = Get-UserSID -User "$($env:USERDOMAIN)\$($env:USERNAME)"
$currentUser = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME)) $objUserSid = Get-UserSID -User $ssouser
$ssouserSSHProfilePath = Join-Path $ssouserProfile .testssh $ssouserSSHProfilePath = Join-Path $ssouserProfile .testssh
if(-not (Test-Path $ssouserSSHProfilePath -PathType Container)) { if(-not (Test-Path $ssouserSSHProfilePath -PathType Container)) {
@ -43,21 +59,22 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
$testknownhosts = Join-path $PSScriptRoot testdata\test_known_hosts $testknownhosts = Join-path $PSScriptRoot testdata\test_known_hosts
Copy-Item $Source $ssouserSSHProfilePath -Force -ErrorAction Stop Copy-Item $Source $ssouserSSHProfilePath -Force -ErrorAction Stop
Adjust-UserKeyFileACL -Filepath $authorizedkeyPath -Owner $objUser -OwnerPerms "Read, Write" Repair-AuthorizedKeyPermission -Filepath $authorizedkeyPath -confirm:$false
Get-Process -Name sshd | Where-Object {$_.SI -ne 0} | Stop-process Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
#add wrong password so ssh does not prompt password if failed with authorized keys #add wrong password so ssh does not prompt password if failed with authorized keys
Add-PasswordSetting -Pass "WrongPass" Add-PasswordSetting -Pass "WrongPass"
$tI=1 $tI=1
} }
AfterAll { AfterAll {
Repair-AuthorizedKeyPermission -Filepath $authorizedkeyPath -confirm:$false
if(Test-Path $authorizedkeyPath) { if(Test-Path $authorizedkeyPath) {
Adjust-UserKeyFileACL -Filepath $authorizedkeyPath -Owner $objUser -OwnerPerms "Read, Write" Repair-AuthorizedKeyPermission -Filepath $authorizedkeyPath -confirm:$false
Remove-Item $authorizedkeyPath -Force -ErrorAction Ignore Remove-Item $authorizedkeyPath -Force -ErrorAction SilentlyContinue
} }
if(Test-Path $ssouserSSHProfilePath) { if(Test-Path $ssouserSSHProfilePath) {
Remove-Item $ssouserSSHProfilePath -Force -ErrorAction Ignore -Recurse Remove-Item $ssouserSSHProfilePath -Force -ErrorAction SilentlyContinue -Recurse
} }
Remove-PasswordSetting Remove-PasswordSetting
$tC++ $tC++
@ -66,11 +83,12 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
BeforeEach { BeforeEach {
$filePath = Join-Path $testDir "$tC.$tI.$fileName" $filePath = Join-Path $testDir "$tC.$tI.$fileName"
$logPath = Join-Path $testDir "$tC.$tI.$logName" $logPath = Join-Path $testDir "$tC.$tI.$logName"
Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
} }
It "$tC.$tI-authorized_keys-positive(pwd user is the owner and running process can access to the file)" { It "$tC.$tI-authorized_keys-positive(pwd user is the owner and running process can access to the file)" {
#setup to have ssouser as owner and grant ssouser read and write, admins group, and local system full control #setup to have ssouser as owner and grant ssouser read and write, admins group, and local system full control
Adjust-UserKeyFileACL -Filepath $authorizedkeyPath -Owner $objUser -OwnerPerms "Read, Write" Repair-FilePermission -Filepath $authorizedkeyPath -Owners $objUserSid -FullAccessNeeded $adminsSid,$systemSid,$objUserSid -confirm:$false
#Run #Run
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow
@ -78,14 +96,12 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
$o | Should Be "1234" $o | Should Be "1234"
#Cleanup #Cleanup
Get-Process -Name sshd | % { if($_.SI -ne 0) { Start-sleep 1; Stop-Process $_; Start-sleep 1 } } Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
} }
It "$tC.$tI-authorized_keys-positive(authorized_keys is owned by local system)" { It "$tC.$tI-authorized_keys-positive(authorized_keys is owned by local system)" {
#setup to have system as owner and grant it full control #setup to have system as owner and grant it full control
Set-FileOwnerAndACL -Filepath $authorizedkeyPath -Owner $systemAccount -OwnerPerms "FullControl" Repair-FilePermission -Filepath $authorizedkeyPath -Owner $systemSid -FullAccessNeeded $adminsSid,$systemSid,$objUserSid -confirm:$false
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $adminAccount -Perms "FullControl"
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $objUser -Perms "Read, Write"
#Run #Run
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow
@ -93,14 +109,12 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
$o | Should Be "1234" $o | Should Be "1234"
#Cleanup #Cleanup
Get-Process -Name sshd | % { if($_.SI -ne 0) { Start-sleep 1; Stop-Process $_; Start-sleep 1 } } Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
} }
It "$tC.$tI-authorized_keys-positive(authorized_keys is owned by admins group and pwd does not have explict ACE)" { It "$tC.$tI-authorized_keys-positive(authorized_keys is owned by admins group and pwd does not have explict ACE)" {
#setup to have admin group as owner and grant it full control #setup to have admin group as owner and grant it full control
Repair-FilePermission -Filepath $authorizedkeyPath -Owner $adminsSid -FullAccessNeeded $adminsSid,$systemSid -confirm:$false
Set-FileOwnerAndACL -Filepath $authorizedkeyPath -Owner $adminAccount -OwnerPerms "FullControl"
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $systemAccount -Perms "FullControl"
#Run #Run
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow
@ -108,15 +122,12 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
$o | Should Be "1234" $o | Should Be "1234"
#Cleanup #Cleanup
Get-Process -Name sshd | % { if($_.SI -ne 0) { Start-sleep 1; Stop-Process $_; Start-sleep 1 } } Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
} }
It "$tC.$tI-authorized_keys-positive(authorized_keys is owned by admins group and pwd have explict ACE)" { It "$tC.$tI-authorized_keys-positive(authorized_keys is owned by admins group and pwd have explict ACE)" {
#setup to have admin group as owner and grant it full control #setup to have admin group as owner and grant it full control
Repair-FilePermission -Filepath $authorizedkeyPath -Owner $adminsSid -FullAccessNeeded $adminsSid,$systemSid,$objUserSid -confirm:$false
Set-FileOwnerAndACL -Filepath $authorizedkeyPath -Owner $adminAccount -OwnerPerms "FullControl"
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $systemAccount -Perms "FullControl"
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $objUser -Perms "Read, Write"
#Run #Run
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow
@ -124,14 +135,12 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
$o | Should Be "1234" $o | Should Be "1234"
#Cleanup #Cleanup
Get-Process -Name sshd | % { if($_.SI -ne 0) { Start-sleep 1; Stop-Process $_; Start-sleep 1 } } Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
} }
It "$tC.$tI-authorized_keys-negative(authorized_keys is owned by other admin user)" { It "$tC.$tI-authorized_keys-negative(authorized_keys is owned by other admin user)" {
#setup to have current user (admin user) as owner and grant it full control #setup to have current user (admin user) as owner and grant it full control
Set-FileOwnerAndACL -Filepath $authorizedkeyPath -Owner $currentUser -OwnerPerms "Read","Write" Repair-FilePermission -Filepath $authorizedkeyPath -Owner $currentUserSid -FullAccessNeeded $adminsSid,$systemSid -confirm:$false
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $systemAccount -Perms "FullControl"
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $adminAccount -Perms "FullControl"
#Run #Run
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow
@ -141,18 +150,16 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
$matches.Count | Should BeGreaterThan 2 $matches.Count | Should BeGreaterThan 2
#Cleanup #Cleanup
Get-Process -Name sshd | % { if($_.SI -ne 0) { Start-sleep 1; Stop-Process $_; Start-sleep 1 } } Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
} }
It "$tC.$tI-authorized_keys-negative(other account can access private key file)" { It "$tC.$tI-authorized_keys-negative(other account can access private key file)" {
#setup to have current user as owner and grant it full control #setup to have current user as owner and grant it full control
Set-FileOwnerAndACL -Filepath $authorizedkeyPath -Owner $objUser -OwnerPerms "Read","Write" Repair-FilePermission -Filepath $authorizedkeyPath -Owner $objUserSid -FullAccessNeeded $adminsSid,$systemSid,$objUserSid -confirm:$false
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $systemAccount -Perms "FullControl"
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $adminAccount -Perms "FullControl"
#add $PwdUser to access the file authorized_keys #add $PwdUser to access the file authorized_keys
$objPwdUser = New-Object System.Security.Principal.NTAccount($PwdUser) $objPwdUserSid = Get-UserSid -User $PwdUser
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $objPwdUser -Perm "Read" Set-FilePermission -FilePath $authorizedkeyPath -User $objPwdUserSid -Perm "Read"
#Run #Run
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow
@ -162,15 +169,13 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
$matches.Count | Should BeGreaterThan 2 $matches.Count | Should BeGreaterThan 2
#Cleanup #Cleanup
Get-Process -Name sshd | % { if($_.SI -ne 0) { Start-sleep 1; Stop-Process $_; Start-sleep 1 } } Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
} }
It "$tC.$tI-authorized_keys-negative(authorized_keys is owned by other non-admin user)" { It "$tC.$tI-authorized_keys-negative(authorized_keys is owned by other non-admin user)" {
#setup to have PwdUser as owner and grant it full control #setup to have PwdUser as owner and grant it full control
$objPwdUser = New-Object System.Security.Principal.NTAccount($PwdUser) $objPwdUserSid = Get-UserSid -User $PwdUser
Set-FileOwnerAndACL -Filepath $authorizedkeyPath -owner $objPwdUser -OwnerPerms "Read","Write" Repair-FilePermission -Filepath $authorizedkeyPath -Owner $objPwdUserSid -FullAccessNeeded $adminsSid,$systemSid,$objPwdUser -confirm:$false
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $systemAccount -Perms "FullControl"
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $adminAccount -Perms "FullControl"
#Run #Run
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow
@ -180,12 +185,12 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
$matches.Count | Should BeGreaterThan 2 $matches.Count | Should BeGreaterThan 2
#Cleanup #Cleanup
Get-Process -Name sshd | % { if($_.SI -ne 0) { Start-sleep 1; Stop-Process $_; Start-sleep 1 } } Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
} }
It "$tC.$tI-authorized_keys-negative(the running process does not have read access to the authorized_keys)" { It "$tC.$tI-authorized_keys-negative(the running process does not have read access to the authorized_keys)" -skip:$skip {
#setup to have ssouser as owner and grant it full control #setup to have ssouser as owner and grant it full control
Set-FileOwnerAndACL -Filepath $authorizedkeyPath -Owner $objUser -OwnerPerms "Read","Write" Repair-FilePermission -Filepath $authorizedkeyPath -Owner $objUserSid -FullAccessNeeded $systemSid,$objUserSid -confirm:$false
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $systemAccount -Perms "FullControl" Set-FilePermission -Filepath $authorizedkeyPath -UserSid $adminsSid -Action Delete
#Run #Run
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow
@ -196,7 +201,7 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
$matches.Count | Should BeGreaterThan 2 $matches.Count | Should BeGreaterThan 2
#Cleanup #Cleanup
Get-Process -Name sshd | % { if($_.SI -ne 0) { Start-sleep 1; Stop-Process $_; Start-sleep 1 } } Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
} }
} }
} }

View File

@ -1,4 +1,5 @@
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force -DisableNameChecking If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force
$tC = 1 $tC = 1
$tI = 0 $tI = 0
$suite = "authorized_keys_fileperm" $suite = "authorized_keys_fileperm"
@ -6,7 +7,7 @@ Describe "Tests for ssh config" -Tags "CI" {
BeforeAll { BeforeAll {
if($OpenSSHTestInfo -eq $null) if($OpenSSHTestInfo -eq $null)
{ {
Throw "`$OpenSSHTestInfo is null. Please run Setup-OpenSSHTestEnvironment to setup test environment." Throw "`$OpenSSHTestInfo is null. Please run Set-OpenSSHTestEnvironment to set test environments."
} }
if(-not (Test-Path $OpenSSHTestInfo["TestDataPath"])) if(-not (Test-Path $OpenSSHTestInfo["TestDataPath"]))
@ -27,38 +28,39 @@ Describe "Tests for ssh config" -Tags "CI" {
# for the first time, delete the existing log files. # for the first time, delete the existing log files.
if ($OpenSSHTestInfo['DebugMode']) if ($OpenSSHTestInfo['DebugMode'])
{ {
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction ignore Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction ignore Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction SilentlyContinue
Remove-Item -Path (Join-Path $testDir "*log*.log") -Force -ErrorAction ignore Remove-Item -Path (Join-Path $testDir "*log*.log") -Force -ErrorAction SilentlyContinue
} }
Remove-Item -Path (Join-Path $testDir "*logName") -Force -ErrorAction ignore Remove-Item -Path (Join-Path $testDir "*logName") -Force -ErrorAction SilentlyContinue
} }
AfterEach { AfterEach {
if( $OpenSSHTestInfo["DebugMode"]) if( $OpenSSHTestInfo["DebugMode"])
{ {
Copy-Item "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" "$testDir\agentlog$tC.$tI.log" -Force -ErrorAction ignore Copy-Item "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" "$testDir\agentlog$tC.$tI.log" -Force -ErrorAction SilentlyContinue
Copy-Item "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" "$testDir\sshdlog$tC.$tI.log" -Force -ErrorAction ignore Copy-Item "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" "$testDir\sshdlog$tC.$tI.log" -Force -ErrorAction SilentlyContinue
#Clear the ssh-agent, sshd logs so that next testcase will get fresh logs. #Clear the ssh-agent, sshd logs so that next testcase will get fresh logs.
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction ignore Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction ignore Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction SilentlyContinue
} }
$tI++ $tI++
} }
Context "$tC-User SSHConfig--ReadConfig" { Context "$tC-User SSHConfig--ReadConfig" {
BeforeAll { BeforeAll {
$systemAccount = New-Object System.Security.Principal.NTAccount("NT AUTHORITY", "SYSTEM") $systemSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::LocalSystemSid)
$adminAccount = New-Object System.Security.Principal.NTAccount("BUILTIN","Administrators") $adminsSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid)
$objUser = New-Object System.Security.Principal.NTAccount($ssouser) $currentUserSid = Get-UserSID -User "$($env:USERDOMAIN)\$($env:USERNAME)"
$currentUser = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME)) $objUserSid = Get-UserSID -User $ssouser
$userConfigFile = Join-Path $home ".ssh\config" $userConfigFile = Join-Path $home ".ssh\config"
if( -not (Test-path $userConfigFile) ) { if( -not (Test-path $userConfigFile) ) {
Copy-item "$PSScriptRoot\testdata\ssh_config" $userConfigFile -force Copy-item "$PSScriptRoot\testdata\ssh_config" $userConfigFile -force
} }
Enable-Privilege SeRestorePrivilege | out-null
$oldACL = Get-ACL $userConfigFile $oldACL = Get-ACL $userConfigFile
$tI=1 $tI=1
} }
@ -68,7 +70,7 @@ Describe "Tests for ssh config" -Tags "CI" {
} }
AfterEach { AfterEach {
Set-Acl -Path $userConfigFile -AclObject $oldACL Set-Acl -Path $userConfigFile -AclObject $oldACL -confirm:$false
} }
AfterAll { AfterAll {
@ -77,9 +79,7 @@ Describe "Tests for ssh config" -Tags "CI" {
It "$tC.$tI-User SSHConfig-ReadConfig positive (current logon user is the owner)" { It "$tC.$tI-User SSHConfig-ReadConfig positive (current logon user is the owner)" {
#setup #setup
Set-FileOwnerAndACL -Filepath $userConfigFile -Owner $currentUser -OwnerPerms "Read","Write" Repair-FilePermission -Filepath $userConfigFile -Owners $currentUserSid -FullAccessNeeded $adminsSid,$systemSid,$currentUserSid -confirm:$false
Add-PermissionToFileACL -FilePath $userConfigFile -User $systemAccount -Perms "FullControl"
Add-PermissionToFileACL -FilePath $userConfigFile -User $adminAccount -Perms "FullControl"
#Run #Run
$o = ssh test_target echo 1234 $o = ssh test_target echo 1234
@ -88,8 +88,7 @@ Describe "Tests for ssh config" -Tags "CI" {
It "$tC.$tI-User SSHConfig-ReadConfig positive (local system is the owner)" { It "$tC.$tI-User SSHConfig-ReadConfig positive (local system is the owner)" {
#setup #setup
Set-FileOwnerAndACL -Filepath $userConfigFile -Owner $systemAccount -OwnerPerms "FullControl" Repair-FilePermission -Filepath $userConfigFile -Owners $systemSid -FullAccessNeeded $adminsSid,$systemSid -confirm:$false
Add-PermissionToFileACL -FilePath $userConfigFile -User $adminAccount -Perms "FullControl"
#Run #Run
$o = ssh test_target echo 1234 $o = ssh test_target echo 1234
@ -98,8 +97,8 @@ Describe "Tests for ssh config" -Tags "CI" {
It "$tC.$tI-User SSHConfig-ReadConfig positive (admin is the owner and current user has no explict ACE)" { It "$tC.$tI-User SSHConfig-ReadConfig positive (admin is the owner and current user has no explict ACE)" {
#setup #setup
Set-FileOwnerAndACL -Filepath $userConfigFile -Owner $adminAccount -OwnerPerms "FullControl" Repair-FilePermission -Filepath $userConfigFile -Owners $adminsSid -FullAccessNeeded $adminsSid,$systemSid -confirm:$false
Add-PermissionToFileACL -FilePath $userConfigFile -User $systemAccount -Perms "FullControl" Set-FilePermission -Filepath $userConfigFile -UserSid $currentUserSid -Action Delete
#Run #Run
$o = ssh test_target echo 1234 $o = ssh test_target echo 1234
@ -108,9 +107,7 @@ Describe "Tests for ssh config" -Tags "CI" {
It "$tC.$tI-User SSHConfig-ReadConfig positive (admin is the owner and current user has explict ACE)" { It "$tC.$tI-User SSHConfig-ReadConfig positive (admin is the owner and current user has explict ACE)" {
#setup #setup
Set-FileOwnerAndACL -Filepath $userConfigFile -Owner $adminAccount -OwnerPerms "FullControl" Repair-FilePermission -Filepath $userConfigFile -Owners $adminsSid -FullAccessNeeded $adminsSid,$systemSid,$currentUserSid -confirm:$false
Add-PermissionToFileACL -FilePath $userConfigFile -User $systemAccount -Perms "FullControl"
Add-PermissionToFileACL -FilePath $userConfigFile -User $currentUser -Perms "Read, Write"
#Run #Run
$o = ssh test_target echo 1234 $o = ssh test_target echo 1234
@ -119,9 +116,7 @@ Describe "Tests for ssh config" -Tags "CI" {
It "$tC.$tI-User SSHConfig-ReadConfig negative (wrong owner)" { It "$tC.$tI-User SSHConfig-ReadConfig negative (wrong owner)" {
#setup #setup
Set-FileOwnerAndACL -Filepath $userConfigFile -Owner $ssouser -OwnerPerms "Read","Write" Repair-FilePermission -Filepath $userConfigFile -Owners $objUserSid -FullAccessNeeded $adminsSid,$systemSid,$objUserSid -confirm:$false
Add-PermissionToFileACL -FilePath $userConfigFile -User $systemAccount -Perms "FullControl"
Add-PermissionToFileACL -FilePath $userConfigFile -User $adminAccount -Perms "FullControl"
#Run #Run
cmd /c "ssh test_target echo 1234 2> $logPath" cmd /c "ssh test_target echo 1234 2> $logPath"
@ -131,10 +126,7 @@ Describe "Tests for ssh config" -Tags "CI" {
It "$tC.$tI-User SSHConfig-ReadConfig negative (others has permission)" { It "$tC.$tI-User SSHConfig-ReadConfig negative (others has permission)" {
#setup #setup
Set-FileOwnerAndACL -Filepath $userConfigFile -Owner $currentUser -OwnerPerms "Read","Write" Repair-FilePermission -Filepath $userConfigFile -Owners $currentUserSid -FullAccessNeeded $adminsSid,$systemSid,$currentUserSid -ReadAccessNeeded $objUserSid -confirm:$false
Add-PermissionToFileACL -FilePath $userConfigFile -User $systemAccount -Perms "FullControl"
Add-PermissionToFileACL -FilePath $userConfigFile -User $adminAccount -Perms "FullControl"
Add-PermissionToFileACL -FilePath $userConfigFile -User $objUser -Perms "Read"
#Run #Run
cmd /c "ssh test_target echo 1234 2> $logPath" cmd /c "ssh test_target echo 1234 2> $logPath"

View File

@ -1,8 +1,13 @@
Enum PlatformType { Import-Module OpenSSHUtils -Force
Windows
Linux Add-Type -TypeDefinition @"
OSX public enum PlatformType
} {
Windows,
Linux,
OSX
}
"@
function Get-Platform { function Get-Platform {
# Use the .NET Core APIs to determine the current platform; if a runtime # Use the .NET Core APIs to determine the current platform; if a runtime
@ -31,157 +36,59 @@ function Get-Platform {
} }
} }
<# function Set-FilePermission
.Synopsis
user key should be owned by current user account
private key can be accessed only by the file owner, localsystem and Administrators
public user key can be accessed by only file owner, localsystem and Administrators and read by everyone
.Outputs
N/A
.Inputs
FilePath - The path to the file
Owner - The file owner
OwnerPerms - The permissions grant to owner
#>
function Adjust-UserKeyFileACL
{
param (
[parameter(Mandatory=$true)]
[string]$FilePath,
[System.Security.Principal.NTAccount] $Owner = $null,
[System.Security.AccessControl.FileSystemRights[]] $OwnerPerms = $null
)
$myACL = Get-ACL $FilePath
$myACL.SetAccessRuleProtection($True, $FALSE)
Set-Acl -Path $FilePath -AclObject $myACL
$systemAccount = New-Object System.Security.Principal.NTAccount("NT AUTHORITY", "SYSTEM")
$adminAccount = New-Object System.Security.Principal.NTAccount("BUILTIN","Administrators")
$everyoneAccount = New-Object System.Security.Principal.NTAccount("EveryOne")
$myACL = Get-ACL $FilePath
$actualOwner = $null
if($Owner -eq $null)
{
$actualOwner = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME))
}
else
{
$actualOwner = $Owner
}
$myACL.SetOwner($actualOwner)
if($myACL.Access)
{
$myACL.Access | % {
if(-not ($myACL.RemoveAccessRule($_)))
{
throw "failed to remove access of $($_.IdentityReference.Value) rule in setup "
}
}
}
$adminACE = New-Object System.Security.AccessControl.FileSystemAccessRule `
($adminAccount, "FullControl", "None", "None", "Allow")
$myACL.AddAccessRule($adminACE)
$systemACE = New-Object System.Security.AccessControl.FileSystemAccessRule `
($systemAccount, "FullControl", "None", "None", "Allow")
$myACL.AddAccessRule($systemACE)
if(-not ($actualOwner.Equals($adminAccount)) -and (-not $actualOwner.Equals($systemAccount)) -and $OwnerPerms)
{
$OwnerPerms | % {
$ownerACE = New-Object System.Security.AccessControl.FileSystemAccessRule `
($actualOwner, $_, "None", "None", "Allow")
$myACL.AddAccessRule($ownerACE)
}
}
if($FilePath.EndsWith(".pub"))
{
$everyoneAce = New-Object System.Security.AccessControl.FileSystemAccessRule `
("Everyone", "Read", "None", "None", "Allow")
$myACL.AddAccessRule($everyoneAce)
}
Set-Acl -Path $FilePath -AclObject $myACL
}
function Set-FileOwnerAndACL
{ {
param( param(
[parameter(Mandatory=$true)] [parameter(Mandatory=$true)]
[string]$FilePath, [string]$FilePath,
[System.Security.Principal.NTAccount]$Owner = $null,
[System.Security.AccessControl.FileSystemRights[]] $OwnerPerms = @("Read", "Write")
)
$myACL = Get-ACL -Path $FilePath
$myACL.SetAccessRuleProtection($True, $FALSE)
Set-Acl -Path $FilePath -AclObject $myACL
$myACL = Get-ACL $FilePath
$actualOwner = $null
if($owner -eq $null)
{
$actualOwner = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME))
}
else
{
$actualOwner = $Owner
}
$myACL.SetOwner($actualOwner)
if($myACL.Access)
{
$myACL.Access | % {
if(-not ($myACL.RemoveAccessRule($_)))
{
throw "failed to remove access of $($_.IdentityReference.Value) rule in setup "
}
}
}
if($OwnerPerms)
{
$OwnerPerms | % {
$ownerACE = New-Object System.Security.AccessControl.FileSystemAccessRule `
($actualOwner, $_, "None", "None", "Allow")
$myACL.AddAccessRule($ownerACE)
}
}
Set-Acl -Path $FilePath -AclObject $myACL
}
function Add-PermissionToFileACL
{
param(
[parameter(Mandatory=$true)] [parameter(Mandatory=$true)]
[string]$FilePath, [System.Security.Principal.SecurityIdentifier] $UserSid,
[System.Security.Principal.NTAccount] $User,
[System.Security.AccessControl.FileSystemRights[]]$Perms, [System.Security.AccessControl.FileSystemRights[]]$Perms,
[System.Security.AccessControl.AccessControlType] $AccessType = "Allow" [System.Security.AccessControl.AccessControlType] $AccessType = "Allow",
[ValidateSet("Add", "Delete")]
[string]$Action = "Add"
) )
$myACL = Get-ACL $FilePath $myACL = Get-ACL $FilePath
$account = Get-UserAccount -UserSid $UserSid
if($Action -ieq "Delete")
{
$myACL.SetAccessRuleProtection($True, $True)
Enable-Privilege SeRestorePrivilege | out-null
Set-Acl -Path $FilePath -AclObject $myACL
$myACL = Get-ACL $FilePath
if($Perms) if($myACL.Access)
{
$myACL.Access | % {
if($_.IdentityReference.Equals($account))
{
if($_.IsInherited)
{
$myACL.SetAccessRuleProtection($True, $True)
Enable-Privilege SeRestorePrivilege | out-null
Set-Acl -Path $FilePath -AclObject $myACL
$myACL = Get-ACL $FilePath
}
if(-not ($myACL.RemoveAccessRule($_)))
{
throw "failed to remove access of $($_.IdentityReference) rule in setup "
}
}
}
}
}
elseif($Perms)
{ {
$Perms | % { $Perms | % {
$userACE = New-Object System.Security.AccessControl.FileSystemAccessRule ` $userACE = New-Object System.Security.AccessControl.FileSystemAccessRule `
($User, $_, "None", "None", $AccessType) ($UserSid, $_, "None", "None", $AccessType)
$myACL.AddAccessRule($userACE) $myACL.AddAccessRule($userACE)
} }
} }
Enable-Privilege SeRestorePrivilege | out-null
Set-Acl -Path $FilePath -AclObject $myACL Set-Acl -Path $FilePath -AclObject $myACL -confirm:$false
} }
function Add-PasswordSetting function Add-PasswordSetting

View File

@ -1,4 +1,5 @@
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force -DisableNameChecking If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force
$tC = 1 $tC = 1
$tI = 0 $tI = 0
$suite = "hostkey_fileperm" $suite = "hostkey_fileperm"
@ -6,7 +7,7 @@ Describe "Tests for host keys file permission" -Tags "CI" {
BeforeAll { BeforeAll {
if($OpenSSHTestInfo -eq $null) if($OpenSSHTestInfo -eq $null)
{ {
Throw "`$OpenSSHTestInfo is null. Please run Setup-OpenSSHTestEnvironment to setup test environment." Throw "`$OpenSSHTestInfo is null. Please run Set-OpenSSHTestEnvironment to set test environments."
} }
$testDir = "$($OpenSSHTestInfo["TestDataPath"])\$suite" $testDir = "$($OpenSSHTestInfo["TestDataPath"])\$suite"
@ -19,30 +20,57 @@ Describe "Tests for host keys file permission" -Tags "CI" {
$port = 47003 $port = 47003
$ssouser = $OpenSSHTestInfo["SSOUser"] $ssouser = $OpenSSHTestInfo["SSOUser"]
$script:logNum = 0 $script:logNum = 0
Remove-Item -Path (Join-Path $testDir "*$logName") -Force -ErrorAction ignore Remove-Item -Path (Join-Path $testDir "*$logName") -Force -ErrorAction SilentlyContinue
$platform = Get-Platform
$skip = ($platform -eq [PlatformType]::Windows) -and ($PSVersionTable.PSVersion.Major -le 2)
if(($platform -eq [PlatformType]::Windows) -and ($psversiontable.BuildVersion.Major -le 6))
{
#suppress the firewall blocking dialogue on win7
netsh advfirewall firewall add rule name="sshd" program="$($OpenSSHTestInfo['OpenSSHBinPath'])\sshd.exe" protocol=any action=allow dir=in
}
} }
AfterEach { $tI++ } AfterEach { $tI++ }
AfterAll {
if(($platform -eq [PlatformType]::Windows) -and ($psversiontable.BuildVersion.Major -le 6))
{
netsh advfirewall firewall delete rule name="sshd" program="$($OpenSSHTestInfo['OpenSSHBinPath'])\sshd.exe" protocol=any dir=in
}
}
Context "$tC - Host key files permission" { Context "$tC - Host key files permission" {
BeforeAll { BeforeAll {
$systemAccount = New-Object System.Security.Principal.NTAccount("NT AUTHORITY", "SYSTEM") $systemSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::LocalSystemSid)
$adminAccount = New-Object System.Security.Principal.NTAccount("BUILTIN","Administrators") $adminsSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid)
$objUser = New-Object System.Security.Principal.NTAccount($ssouser) $currentUserSid = Get-UserSID -User "$($env:USERDOMAIN)\$($env:USERNAME)"
$currentUser = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME)) $objUserSid = Get-UserSID -User $ssouser
$everyone = New-Object System.Security.Principal.NTAccount("EveryOne") $everyoneSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::WorldSid)
$hostKeyFilePath = join-path $testDir hostkeyFilePermTest_ed25519_key $hostKeyFilePath = join-path $testDir hostkeyFilePermTest_ed25519_key
if(Test-path $hostKeyFilePath -PathType Leaf) { if(Test-path $hostKeyFilePath -PathType Leaf) {
Set-FileOwnerAndACL -filepath $hostKeyFilePath Repair-SshdHostKeyPermission -filepath $hostKeyFilePath -confirm:$false
} }
if(Test-path "$hostKeyFilePath.pub" -PathType Leaf){ Remove-Item -path "$hostKeyFilePath*" -Force -ErrorAction SilentlyContinue
Set-FileOwnerAndACL -filepath "$hostKeyFilePath.pub"
}
Remove-Item -path "$hostKeyFilePath*" -Force -ErrorAction Ignore
ssh-keygen.exe -t ed25519 -f $hostKeyFilePath -P `"`" ssh-keygen.exe -t ed25519 -f $hostKeyFilePath -P `"`"
Get-Process -Name sshd | Where-Object {$_.SI -ne 0} | Stop-process Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
$tI=1 $tI=1
function WaitForValidation
{
param([string]$logPath, [int]$length)
$num = 0
while((-not (Test-Path $logPath -PathType leaf)) -or ((Get-item $logPath).Length -lt $length) -and ($num++ -lt 4))
{
Start-Sleep -Milliseconds 1000
}
Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
$num = 0
while ([string]::IsNullorEmpty($(Get-Content $logPath -ErrorAction SilentlyContinue | Out-String)) -and ($num++ -lt 4))
{
Start-Sleep -Milliseconds 1000
}
}
} }
BeforeEach { BeforeEach {
@ -50,76 +78,59 @@ Describe "Tests for host keys file permission" -Tags "CI" {
} }
AfterAll { AfterAll {
if(Test-path $hostKeyFilePath -PathType Leaf){ if(Test-path $hostKeyFilePath -PathType Leaf) {
Adjust-UserKeyFileACL -Filepath $hostKeyFilePath -Owner $systemAccount Repair-SshdHostKeyPermission -filepath $hostKeyFilePath -confirm:$false
}
if(Test-path "$hostKeyFilePath.pub" -PathType Leaf){
Adjust-UserKeyFileACL -Filepath "$hostKeyFilePath.pub" -Owner $systemAccount
} }
$tC++ $tC++
} }
It "$tC.$tI-Host keys-positive (both public and private keys are owned by admin groups and running process can access to public key file)" { It "$tC.$tI-Host keys-positive (both public and private keys are owned by admin groups and running process can access to public key file)" {
Set-FileOwnerAndACL -Filepath $hostKeyFilePath -Owner $adminAccount -OwnerPerms "FullControl" Repair-FilePermission -Filepath $hostKeyFilePath -Owners $adminsSid -FullAccessNeeded $adminsSid,$systemSid -confirm:$false
Add-PermissionToFileACL -FilePath $hostKeyFilePath -User $systemAccount -Perms "FullControl" Repair-FilePermission -Filepath "$hostKeyFilePath.pub" -Owners $adminsSid -FullAccessNeeded $adminsSid,$systemSid -confirm:$false
Set-FileOwnerAndACL -Filepath "$hostKeyFilePath.pub" -Owner $adminAccount -OwnerPerms "FullControl"
Add-PermissionToFileACL -FilePath "$hostKeyFilePath.pub" -User $systemAccount -Perms "FullControl"
Add-PermissionToFileACL -FilePath "$hostKeyFilePath.pub" -User $everyOne -Perms "Read"
#Run #Run
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-h $hostKeyFilePath", "-E $logPath") -NoNewWindow Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-h $hostKeyFilePath", "-E $logPath") -NoNewWindow
Get-Process -Name sshd | % { if($_.SI -ne 0) { Start-sleep 2; Stop-Process $_; Start-sleep 1 } } WaitForValidation -LogPath $logPath -Length 600
#validate file content does not contain unprotected info. #validate file content does not contain unprotected info.
$logPath | Should Not Contain "UNPROTECTED PRIVATE KEY FILE!" $logPath | Should Not Contain "UNPROTECTED PRIVATE KEY FILE!"
} }
It "$tC.$tI-Host keys-positive (both public and private keys are owned by admin groups and pwd user has explicit ACE)" { It "$tC.$tI-Host keys-positive (both public and private keys are owned by admin groups and pwd user has explicit ACE)" {
Set-FileOwnerAndACL -Filepath $hostKeyFilePath -Owner $adminAccount -OwnerPerms "FullControl" Repair-FilePermission -Filepath $hostKeyFilePath -Owners $adminsSid -FullAccessNeeded $adminsSid,$systemSid -ReadAccessNeeded $currentUserSid -confirm:$false
Add-PermissionToFileACL -FilePath $hostKeyFilePath -User $systemAccount -Perms "FullControl" Repair-FilePermission -Filepath "$hostKeyFilePath.pub" -Owners $adminsSid -FullAccessNeeded $adminsSid,$systemSid -ReadAccessNeeded $everyOneSid -confirm:$false
Add-PermissionToFileACL -FilePath "$hostKeyFilePath.pub" -User $currentUser -Perms "Read"
Set-FileOwnerAndACL -Filepath "$hostKeyFilePath.pub" -Owner $adminAccount -OwnerPerms "FullControl"
Add-PermissionToFileACL -FilePath "$hostKeyFilePath.pub" -User $systemAccount -Perms "FullControl"
Add-PermissionToFileACL -FilePath "$hostKeyFilePath.pub" -User $everyOne -Perms "Read"
#Run #Run
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-h $hostKeyFilePath", "-E $logPath") -NoNewWindow Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-h $hostKeyFilePath", "-E $logPath") -NoNewWindow
Get-Process -Name sshd | % { if($_.SI -ne 0) { Start-sleep 2; Stop-Process $_; Start-sleep 1 } } WaitForValidation -LogPath $logPath -Length 600
#validate file content does not contain unprotected info. #validate file content does not contain unprotected info.
$logPath | Should Not Contain "UNPROTECTED PRIVATE KEY FILE!" $logPath | Should Not Contain "UNPROTECTED PRIVATE KEY FILE!"
} }
It "$tC.$tI-Host keys-positive (both public and private keys are owned by system and running process can access to public key file)" { It "$tC.$tI-Host keys-positive (both public and private keys are owned by system and running process can access to public key file)" -skip:$skip {
Set-FileOwnerAndACL -Filepath $hostKeyFilePath -Owner $systemAccount -OwnerPerms "FullControl" Repair-FilePermission -Filepath $hostKeyFilePath -Owners $systemSid -FullAccessNeeded $systemSid,$adminsSid -ReadAccessNeeded $currentUserSid -confirm:$false
Add-PermissionToFileACL -FilePath $hostKeyFilePath -User $adminAccount -Perms "Read" Set-FilePermission -Filepath $hostKeyFilePath -UserSid $adminsSid -Action Delete
Repair-FilePermission -Filepath "$hostKeyFilePath.pub" -Owners $systemSid -FullAccessNeeded $systemSid,$adminsSid -ReadAccessNeeded $currentUserSid -confirm:$false
Set-FileOwnerAndACL -Filepath "$hostKeyFilePath.pub" -Owner $systemAccount -OwnerPerms "FullControl" Set-FilePermission -Filepath "$hostKeyFilePath.pub" -UserSid $adminsSid -Action Delete
Add-PermissionToFileACL -FilePath "$hostKeyFilePath.pub" -User $adminAccount -Perms "Read"
#Run #Run
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-h $hostKeyFilePath", "-E $logPath") -NoNewWindow Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-h $hostKeyFilePath", "-E $logPath") -NoNewWindow
Get-Process -Name sshd | % { if($_.SI -ne 0) { Start-sleep 2; Stop-Process $_; Start-sleep 1 } } WaitForValidation -LogPath $logPath -Length 600
#validate file content does not contain unprotected info. #validate file content does not contain unprotected info.
$logPath | Should Not Contain "UNPROTECTED PRIVATE KEY FILE!" $logPath | Should Not Contain "UNPROTECTED PRIVATE KEY FILE!"
} }
It "$tC.$tI-Host keys-negative (other account can access private key file)" { It "$tC.$tI-Host keys-negative (other account can access private key file)" {
Set-FileOwnerAndACL -Filepath $hostKeyFilePath -Owner $systemAccount -OwnerPerms "FullControl" Repair-FilePermission -Filepath $hostKeyFilePath -Owners $adminsSid -FullAccessNeeded $systemSid,$adminsSid -ReadAccessNeeded $objUserSid -confirm:$false
Add-PermissionToFileACL -FilePath $hostKeyFilePath -User $adminAccount -Perms "FullControl" Repair-FilePermission -Filepath "$hostKeyFilePath.pub" -Owners $adminsSid -FullAccessNeeded $systemSid,$adminsSid -ReadAccessNeeded $everyOneSid -confirm:$false
Add-PermissionToFileACL -FilePath $hostKeyFilePath -User $objUser -Perms "Read"
Set-FileOwnerAndACL -Filepath "$hostKeyFilePath.pub" -Owner $adminAccount -OwnerPerms "FullControl"
Add-PermissionToFileACL -FilePath "$hostKeyFilePath.pub" -User $systemAccount -Perms "FullControl"
Add-PermissionToFileACL -FilePath "$hostKeyFilePath.pub" -User $everyOne -Perms "Read"
#Run #Run
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-h $hostKeyFilePath", "-E $logPath") -NoNewWindow Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-h $hostKeyFilePath", "-E $logPath") -NoNewWindow
Get-Process -Name sshd | % { if($_.SI -ne 0) { Start-sleep 2; Stop-Process $_; Start-sleep 1 } } WaitForValidation -LogPath $logPath -Length 1100
#validate file content contains unprotected info. #validate file content contains unprotected info.
$logPath | Should Contain "key_load_private: bad permissions" $logPath | Should Contain "key_load_private: bad permissions"
@ -127,32 +138,26 @@ Describe "Tests for host keys file permission" -Tags "CI" {
It "$tC.$tI-Host keys-negative (the private key has wrong owner)" { It "$tC.$tI-Host keys-negative (the private key has wrong owner)" {
#setup to have ssouser as owner and grant it full control #setup to have ssouser as owner and grant it full control
Set-FileOwnerAndACL -FilePath $hostKeyFilePath -Owner $objUser -OwnerPerms "Read","Write" Repair-FilePermission -Filepath $hostKeyFilePath -Owners $objUserSid -FullAccessNeeded $systemSid,$adminsSid,$objUserSid -confirm:$false
Add-PermissionToFileACL -FilePath $hostKeyFilePath -User $adminAccount -Perms "FullControl" Repair-FilePermission -Filepath "$hostKeyFilePath.pub" -Owners $adminsSid -FullAccessNeeded $systemSid,$adminsSid -ReadAccessNeeded $everyOneSid -confirm:$false
Add-PermissionToFileACL -FilePath $hostKeyFilePath -User $systemAccount -Perms "FullControl"
Set-FileOwnerAndACL -Filepath "$hostKeyFilePath.pub" -Owner $adminAccount -OwnerPerms "FullControl"
Add-PermissionToFileACL -FilePath "$hostKeyFilePath.pub" -User $systemAccount -Perms "FullControl"
Add-PermissionToFileACL -FilePath "$hostKeyFilePath.pub" -User $everyOne -Perms "Read"
#Run #Run
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-h $hostKeyFilePath", "-E $logPath") -NoNewWindow Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-h $hostKeyFilePath", "-E $logPath") -NoNewWindow
Get-Process -Name sshd | % { if($_.SI -ne 0) { Start-sleep 2; Stop-Process $_; Start-sleep 1 } } WaitForValidation -LogPath $logPath -Length 1100
#validate file content contains unprotected info. #validate file content contains unprotected info.
$logPath | Should Contain "key_load_private: bad permissions" $logPath | Should Contain "key_load_private: bad permissions"
} }
It "$tC.$tI-Host keys-negative (the running process does not have read access to public key)" { It "$tC.$tI-Host keys-negative (the running process does not have read access to public key)" -skip:$skip {
#setup to have ssouser as owner and grant it full control #setup to have ssouser as owner and grant it full control
Set-FileOwnerAndACL -FilePath $hostKeyFilePath -Owner $systemAccount -OwnerPerms "FullControl" Repair-FilePermission -Filepath $hostKeyFilePath -Owners $systemSid -FullAccessNeeded $systemSid,$adminsSid -confirm:$false
Add-PermissionToFileACL -FilePath $hostKeyFilePath -User $adminAccount -Perms "Read" Repair-FilePermission -Filepath "$hostKeyFilePath.pub" -Owners $systemSid -FullAccessNeeded $systemSid -confirm:$false
Set-FilePermission -Filepath "$hostKeyFilePath.pub" -UserSid $adminsSid -Action Delete
Set-FileOwnerAndACL -Filepath "$hostKeyFilePath.pub" -Owner $systemAccount -OwnerPerms "FullControl"
#Run #Run
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-h $hostKeyFilePath", "-E $logPath") -NoNewWindow Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-h $hostKeyFilePath", "-E $logPath") -NoNewWindow
Get-Process -Name sshd | % { if($_.SI -ne 0) { Start-sleep 2; Stop-Process $_; Start-sleep 1 } } WaitForValidation -LogPath $logPath -Length 1100
#validate file content contains unprotected info. #validate file content contains unprotected info.
$logPath | Should Contain "key_load_public: Permission denied" $logPath | Should Contain "key_load_public: Permission denied"

View File

@ -1,4 +1,5 @@
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force -DisableNameChecking If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force
$tC = 1 $tC = 1
$tI = 0 $tI = 0
$suite = "keyutils" $suite = "keyutils"
@ -7,7 +8,7 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
BeforeAll { BeforeAll {
if($OpenSSHTestInfo -eq $null) if($OpenSSHTestInfo -eq $null)
{ {
Throw "`$OpenSSHTestInfo is null. Please run Setup-OpenSSHTestEnvironment to setup test environment." Throw "`$OpenSSHTestInfo is null. Please run Set-OpenSSHTestEnvironment to set test environments."
} }
$testDir = "$($OpenSSHTestInfo["TestDataPath"])\$suite" $testDir = "$($OpenSSHTestInfo["TestDataPath"])\$suite"
@ -21,47 +22,57 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
$ssouser = $OpenSSHTestInfo["SSOUser"] $ssouser = $OpenSSHTestInfo["SSOUser"]
$systemAccount = New-Object System.Security.Principal.NTAccount("NT AUTHORITY", "SYSTEM") $systemSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::LocalSystemSid)
$adminsAccount = New-Object System.Security.Principal.NTAccount("BUILTIN","Administrators") $adminsSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid)
$currentUser = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME)) $currentUserSid = Get-UserSID -User "$($env:USERDOMAIN)\$($env:USERNAME)"
$everyone = New-Object System.Security.Principal.NTAccount("EveryOne") $objUserSid = Get-UserSID -User $ssouser
$objUser = New-Object System.Security.Principal.NTAccount($ssouser) $everyoneSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::WorldSid)
#only validate owner and ACEs of the file #only validate owner and ACEs of the file
function ValidateKeyFile { function ValidateKeyFile {
param([string]$FilePath) param([string]$FilePath)
$myACL = Get-ACL $FilePath $myACL = Get-ACL $FilePath
$myACL.Owner.Equals($currentUser.Value) | Should Be $true $currentOwnerSid = Get-UserSid -User $myACL.Owner
$currentOwnerSid.Equals($currentUserSid) | Should Be $true
$myACL.Access | Should Not Be $null $myACL.Access | Should Not Be $null
$ReadAccessPerm = ([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Read.value__) -bor `
([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Synchronize.value__)
$ReadWriteAccessPerm = ([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Read.value__) -bor `
([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Write.value__) -bor `
([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Synchronize.value__)
$FullControlPerm = [System.UInt32] [System.Security.AccessControl.FileSystemRights]::FullControl.value__
if($FilePath.EndsWith(".pub")) { if($FilePath.EndsWith(".pub")) {
$myACL.Access.Count | Should Be 4 $myACL.Access.Count | Should Be 4
$identities = @($systemAccount.Value, $adminsAccount.Value, $currentUser.Value, $everyone.Value) $identities = @($systemSid, $adminsSid, $currentUserSid, $everyoneSid)
} }
else { else {
$myACL.Access.Count | Should Be 3 $myACL.Access.Count | Should Be 3
$identities = @($systemAccount.Value, $adminsAccount.Value, $currentUser.Value) $identities = @($systemSid, $adminsSid, $currentUserSid)
} }
foreach ($a in $myACL.Access) { foreach ($a in $myACL.Access) {
$a.IdentityReference.Value -in $identities | Should Be $true $id = Get-UserSid -User $a.IdentityReference
$identities -contains $id | Should Be $true
switch ($a.IdentityReference.Value) switch ($id)
{ {
{$_ -in @($systemAccount.Value, $adminsAccount.Value)} {@($systemSid, $adminsSid) -contains $_}
{ {
$a.FileSystemRights | Should Be "FullControl" ([System.UInt32]$a.FileSystemRights.value__) | Should Be $FullControlPerm
break; break;
} }
$currentUser.Value $currentUserSid
{ {
$a.FileSystemRights | Should Be "Write, Read, Synchronize" ([System.UInt32]$a.FileSystemRights.value__) | Should Be $ReadWriteAccessPerm
break; break;
} }
$everyone.Value $everyoneSid
{ {
$a.FileSystemRights | Should Be "Read, Synchronize" ([System.UInt32]$a.FileSystemRights.value__) | Should Be $ReadAccessPerm
break; break;
} }
} }
@ -106,7 +117,7 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
foreach($type in $keytypes) foreach($type in $keytypes)
{ {
$keyPath = Join-Path $testDir "id_$type" $keyPath = Join-Path $testDir "id_$type"
remove-item $keyPath -ErrorAction ignore remove-item $keyPath -ErrorAction SilentlyContinue
ssh-keygen -t $type -P $keypassphrase -f $keyPath ssh-keygen -t $type -P $keypassphrase -f $keyPath
ValidateKeyFile -FilePath $keyPath ValidateKeyFile -FilePath $keyPath
ValidateKeyFile -FilePath "$keyPath.pub" ValidateKeyFile -FilePath "$keyPath.pub"
@ -116,7 +127,17 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
# This uses keys generated in above context # This uses keys generated in above context
Context "$tC -ssh-add test cases" { Context "$tC -ssh-add test cases" {
BeforeAll {$tI=1} BeforeAll {
$tI=1
function WaitForStatus
{
param([string]$ServiceName, [string]$Status)
while((((Get-Service $ServiceName).Status) -ine $Status) -and ($num++ -lt 4))
{
Start-Sleep -Milliseconds 1000
}
}
}
AfterAll{$tC++} AfterAll{$tC++}
# Executing ssh-agent will start agent service # Executing ssh-agent will start agent service
@ -131,16 +152,21 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
(Get-Service sshd).Status | Should Be "Stopped" (Get-Service sshd).Status | Should Be "Stopped"
ssh-agent ssh-agent
WaitForStatus -ServiceName ssh-agent -Status "Running"
(Get-Service ssh-agent).Status | Should Be "Running" (Get-Service ssh-agent).Status | Should Be "Running"
Stop-Service ssh-agent -Force Stop-Service ssh-agent -Force
WaitForStatus -ServiceName ssh-agent -Status "Stopped"
(Get-Service ssh-agent).Status | Should Be "Stopped" (Get-Service ssh-agent).Status | Should Be "Stopped"
(Get-Service sshd).Status | Should Be "Stopped" (Get-Service sshd).Status | Should Be "Stopped"
# this should automatically start both the services # this should automatically start both the services
Start-Service sshd Start-Service sshd
WaitForStatus -ServiceName sshd -Status "Running"
(Get-Service ssh-agent).Status | Should Be "Running" (Get-Service ssh-agent).Status | Should Be "Running"
(Get-Service sshd).Status | Should Be "Running" (Get-Service sshd).Status | Should Be "Running"
} }
@ -170,7 +196,7 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
{ {
$keyPath = Join-Path $testDir "id_$type" $keyPath = Join-Path $testDir "id_$type"
$pubkeyraw = ((Get-Content "$keyPath.pub").Split(' '))[1] $pubkeyraw = ((Get-Content "$keyPath.pub").Split(' '))[1]
($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 1 @($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 1
} }
#delete added keys #delete added keys
@ -188,7 +214,7 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
{ {
$keyPath = Join-Path $testDir "id_$type" $keyPath = Join-Path $testDir "id_$type"
$pubkeyraw = ((Get-Content "$keyPath.pub").Split(' '))[1] $pubkeyraw = ((Get-Content "$keyPath.pub").Split(' '))[1]
($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 0 @($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 0
} }
} }
} }
@ -197,7 +223,7 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
BeforeAll { BeforeAll {
$keyFileName = "sshadd_userPermTestkey_ed25519" $keyFileName = "sshadd_userPermTestkey_ed25519"
$keyFilePath = Join-Path $testDir $keyFileName $keyFilePath = Join-Path $testDir $keyFileName
Remove-Item -path "$keyFilePath*" -Force -ErrorAction Ignore Remove-Item -path "$keyFilePath*" -Force -ErrorAction SilentlyContinue
ssh-keygen.exe -t ed25519 -f $keyFilePath -P $keypassphrase ssh-keygen.exe -t ed25519 -f $keyFilePath -P $keypassphrase
#set up SSH_ASKPASS #set up SSH_ASKPASS
Add-PasswordSetting -Pass $keypassphrase Add-PasswordSetting -Pass $keypassphrase
@ -209,7 +235,7 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
} }
AfterEach { AfterEach {
if(Test-Path $keyFilePath) { if(Test-Path $keyFilePath) {
Adjust-UserKeyFileACL -FilePath $keyFilePath -Owner $currentUser -OwnerPerms "Read, Write" Repair-FilePermission -FilePath $keyFilePath -Owner $currentUserSid -FullAccessNeeded $currentUserSid,$systemSid,$adminsSid -confirm:$false
} }
} }
@ -221,14 +247,14 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
It "$tC.$tI- ssh-add - positive (Secured private key owned by current user)" { It "$tC.$tI- ssh-add - positive (Secured private key owned by current user)" {
#setup to have current user as owner and grant it full control #setup to have current user as owner and grant it full control
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $currentUser -OwnerPerms "FullControl" Repair-FilePermission -FilePath $keyFilePath -Owner $currentUserSid -FullAccessNeeded $currentUserSid,$systemSid,$adminsSid -confirm:$false
# for ssh-add to consume SSh_ASKPASS, stdin should not be TTY # for ssh-add to consume SSh_ASKPASS, stdin should not be TTY
cmd /c "ssh-add $keyFilePath < $nullFile 2> nul" cmd /c "ssh-add $keyFilePath < $nullFile 2> nul"
$LASTEXITCODE | Should Be 0 $LASTEXITCODE | Should Be 0
$allkeys = ssh-add -L $allkeys = ssh-add -L
$pubkeyraw = ((Get-Content "$keyFilePath.pub").Split(' '))[1] $pubkeyraw = ((Get-Content "$keyFilePath.pub").Split(' '))[1]
($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 1 @($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 1
#clean up #clean up
cmd /c "ssh-add -d $keyFilePath 2> nul " cmd /c "ssh-add -d $keyFilePath 2> nul "
@ -236,14 +262,14 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
It "$tC.$tI - ssh-add - positive (Secured private key owned by Administrators group and the current user has no explicit ACE)" { It "$tC.$tI - ssh-add - positive (Secured private key owned by Administrators group and the current user has no explicit ACE)" {
#setup to have local admin group as owner and grant it full control #setup to have local admin group as owner and grant it full control
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $adminsAccount -OwnerPerms "FullControl" Repair-FilePermission -FilePath $keyFilePath -Owner $adminsSid -FullAccessNeeded $adminsSid,$systemSid -confirm:$false
# for ssh-add to consume SSh_ASKPASS, stdin should not be TTY # for ssh-add to consume SSh_ASKPASS, stdin should not be TTY
cmd /c "ssh-add $keyFilePath < $nullFile 2> nul " cmd /c "ssh-add $keyFilePath < $nullFile 2> nul "
$LASTEXITCODE | Should Be 0 $LASTEXITCODE | Should Be 0
$allkeys = ssh-add -L $allkeys = ssh-add -L
$pubkeyraw = ((Get-Content "$keyFilePath.pub").Split(' '))[1] $pubkeyraw = ((Get-Content "$keyFilePath.pub").Split(' '))[1]
($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 1 @($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 1
#clean up #clean up
cmd /c "ssh-add -d $keyFilePath 2> nul " cmd /c "ssh-add -d $keyFilePath 2> nul "
@ -251,15 +277,14 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
It "$tC.$tI - ssh-add - positive (Secured private key owned by Administrators group and the current user has explicit ACE)" { It "$tC.$tI - ssh-add - positive (Secured private key owned by Administrators group and the current user has explicit ACE)" {
#setup to have local admin group as owner and grant it full control #setup to have local admin group as owner and grant it full control
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $adminsAccount -OwnerPerms "FullControl" Repair-FilePermission -FilePath $keyFilePath -Owners $adminsSid -FullAccessNeeded $currentUserSid,$adminsSid,$systemSid -confirm:$false
Add-PermissionToFileACL -FilePath $keyFilePath -User $currentUser -Perm "Read, Write"
# for ssh-add to consume SSh_ASKPASS, stdin should not be TTY # for ssh-add to consume SSh_ASKPASS, stdin should not be TTY
cmd /c "ssh-add $keyFilePath < $nullFile 2> nul " cmd /c "ssh-add $keyFilePath < $nullFile 2> nul "
$LASTEXITCODE | Should Be 0 $LASTEXITCODE | Should Be 0
$allkeys = ssh-add -L $allkeys = ssh-add -L
$pubkeyraw = ((Get-Content "$keyFilePath.pub").Split(' '))[1] $pubkeyraw = ((Get-Content "$keyFilePath.pub").Split(' '))[1]
($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 1 @($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 1
#clean up #clean up
cmd /c "ssh-add -d $keyFilePath 2> nul " cmd /c "ssh-add -d $keyFilePath 2> nul "
@ -267,15 +292,14 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
It "$tC.$tI - ssh-add - positive (Secured private key owned by local system group)" { It "$tC.$tI - ssh-add - positive (Secured private key owned by local system group)" {
#setup to have local admin group as owner and grant it full control #setup to have local admin group as owner and grant it full control
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $systemAccount -OwnerPerms "FullControl" Repair-FilePermission -FilePath $keyFilePath -Owners $systemSid -FullAccessNeeded $systemSid,$adminsSid -confirm:$false
Add-PermissionToFileACL -FilePath $keyFilePath -User $adminsAccount -Perm "FullControl"
# for ssh-add to consume SSh_ASKPASS, stdin should not be TTY # for ssh-add to consume SSh_ASKPASS, stdin should not be TTY
cmd /c "ssh-add $keyFilePath < $nullFile 2> nul " cmd /c "ssh-add $keyFilePath < $nullFile 2> nul "
$LASTEXITCODE | Should Be 0 $LASTEXITCODE | Should Be 0
$allkeys = ssh-add -L $allkeys = ssh-add -L
$pubkeyraw = ((Get-Content "$keyFilePath.pub").Split(' '))[1] $pubkeyraw = ((Get-Content "$keyFilePath.pub").Split(' '))[1]
($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 1 @($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 1
#clean up #clean up
cmd /c "ssh-add -d $keyFilePath 2> nul " cmd /c "ssh-add -d $keyFilePath 2> nul "
@ -283,30 +307,26 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
It "$tC.$tI- ssh-add - negative (other account can access private key file)" { It "$tC.$tI- ssh-add - negative (other account can access private key file)" {
#setup to have current user as owner and grant it full control #setup to have current user as owner and grant it full control
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $currentUser -OwnerPerms "FullControl" Repair-FilePermission -FilePath $keyFilePath -Owners $currentUserSid -FullAccessNeeded $currentUserSid,$adminsSid, $systemSid -ReadAccessNeeded $objUserSid -confirm:$false
#add ssouser to access the private key
Add-PermissionToFileACL -FilePath $keyFilePath -User $objUser -Perm "Read"
cmd /c "ssh-add $keyFilePath < $nullFile 2> nul " cmd /c "ssh-add $keyFilePath < $nullFile 2> nul "
$LASTEXITCODE | Should Not Be 0 $LASTEXITCODE | Should Not Be 0
$allkeys = ssh-add -L $allkeys = ssh-add -L
$pubkeyraw = ((Get-Content "$keyFilePath.pub").Split(' '))[1] $pubkeyraw = ((Get-Content "$keyFilePath.pub").Split(' '))[1]
($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 0 @($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 0
} }
It "$tC.$tI - ssh-add - negative (the private key has wrong owner)" { It "$tC.$tI - ssh-add - negative (the private key has wrong owner)" {
#setup to have ssouser as owner and grant it full control #setup to have ssouser as owner and grant it full control
Set-FileOwnerAndACL -FilePath $keyFilePath -owner $objUser -OwnerPerms "Read, Write" Repair-FilePermission -FilePath $keyFilePath -Owners $objUserSid -FullAccessNeeded $objUserSid,$adminsSid, $systemSid -confirm:$false
Add-PermissionToFileACL -FilePath $keyFilePath -User $adminsAccount -Perm "FullControl"
cmd /c "ssh-add $keyFilePath < $nullFile 2> nul " cmd /c "ssh-add $keyFilePath < $nullFile 2> nul "
$LASTEXITCODE | Should Not Be 0 $LASTEXITCODE | Should Not Be 0
$allkeys = ssh-add -L $allkeys = ssh-add -L
$pubkeyraw = ((Get-Content "$keyFilePath.pub").Split(' '))[1] $pubkeyraw = ((Get-Content "$keyFilePath.pub").Split(' '))[1]
($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 0 @($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 0
} }
} }
@ -314,7 +334,7 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
BeforeAll { BeforeAll {
$tI=1 $tI=1
$port = $OpenSSHTestInfo["Port"] $port = $OpenSSHTestInfo["Port"]
Remove-item (join-path $testDir "$tC.$tI.out.txt") -force -ErrorAction Ignore Remove-item (join-path $testDir "$tC.$tI.out.txt") -force -ErrorAction SilentlyContinue
} }
BeforeEach { BeforeEach {
$outputFile = join-path $testDir "$tC.$tI.out.txt" $outputFile = join-path $testDir "$tC.$tI.out.txt"

View File

@ -1,4 +1,6 @@
$tC = 1 If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force
$tC = 1
$tI = 0 $tI = 0
$suite = "log_fileperm" $suite = "log_fileperm"
@ -17,36 +19,50 @@ Describe "Tests for log file permission" -Tags "CI" {
$port = 47003 $port = 47003
$logName = "log.txt" $logName = "log.txt"
$systemAccount = New-Object System.Security.Principal.NTAccount("NT AUTHORITY", "SYSTEM") $systemSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::LocalSystemSid)
$adminsAccount = New-Object System.Security.Principal.NTAccount("BUILTIN","Administrators") $adminsSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid)
$currentUser = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME)) $currentUserSid = Get-UserSID -User "$($env:USERDOMAIN)\$($env:USERNAME)"
Remove-Item (Join-Path $testDir "*$logName") -Force -ErrorAction Ignore Remove-Item (Join-Path $testDir "*$logName") -Force -ErrorAction SilentlyContinue
$platform = Get-Platform
if(($platform -eq [PlatformType]::Windows) -and ($psversiontable.BuildVersion.Major -le 6))
{
#suppress the firewall blocking dialogue on win7
netsh advfirewall firewall add rule name="sshd" program="$($OpenSSHTestInfo['OpenSSHBinPath'])\sshd.exe" protocol=any action=allow dir=in
}
#only validate owner and ACEs of the file #only validate owner and ACEs of the file
function ValiLogFilePerm { function ValidateLogFilePerm {
param([string]$FilePath) param([string]$FilePath)
$myACL = Get-ACL $FilePath $myACL = Get-ACL $FilePath
$myACL.Owner.Equals($currentUser.Value) | Should Be $true $currentOwnerSid = Get-UserSid -User $myACL.Owner
$currentOwnerSid.Equals($currentUserSid) | Should Be $true
$myACL.Access | Should Not Be $null $myACL.Access | Should Not Be $null
$ReadWriteAccessPerm = ([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Read.value__) -bor `
([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Write.value__) -bor `
([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Synchronize.value__)
$FullControlPerm = [System.UInt32] [System.Security.AccessControl.FileSystemRights]::FullControl.value__
$myACL.Access.Count | Should Be 3 $myACL.Access.Count | Should Be 3
$identities = @($systemAccount.Value, $adminsAccount.Value, $currentUser.Value) $identities = @($systemSid, $adminsSid, $currentUserSid)
foreach ($a in $myACL.Access) { foreach ($a in $myACL.Access) {
$a.IdentityReference.Value -in $identities | Should Be $true $id = Get-UserSid -User $a.IdentityReference
$identities -contains $id | Should Be $true
switch ($a.IdentityReference.Value) switch ($id)
{ {
{$_ -in @($systemAccount.Value, $adminsAccount.Value)} {@($systemSid, $adminsSid) -contains $_}
{ {
$a.FileSystemRights | Should Be "FullControl" ([System.UInt32]$a.FileSystemRights.value__) | Should Be $FullControlPerm
break; break;
} }
$currentUserSid
$currentUser.Value
{ {
$a.FileSystemRights | Should Be "Write, Read, Synchronize" ([System.UInt32]$a.FileSystemRights.value__) | Should Be $ReadWriteAccessPerm
break; break;
} }
} }
@ -64,10 +80,16 @@ Describe "Tests for log file permission" -Tags "CI" {
} }
AfterEach {$tI++;} AfterEach {$tI++;}
AfterAll {
if(($platform -eq [PlatformType]::Windows) -and ($psversiontable.BuildVersion.Major -le 6))
{
netsh advfirewall firewall delete rule name="sshd" program="$($OpenSSHTestInfo['OpenSSHBinPath'])\sshd.exe" protocol=any dir=in
}
}
Context "$tC-SSHD -E Log file permission" { Context "$tC-SSHD -E Log file permission" {
BeforeAll { BeforeAll {
Get-Process -Name sshd | Where-Object {$_.SI -ne 0} | Stop-process Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
$tI=1 $tI=1
} }
@ -79,8 +101,8 @@ Describe "Tests for log file permission" -Tags "CI" {
#Run #Run
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-E $logPath") -NoNewWindow Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-E $logPath") -NoNewWindow
Start-sleep 1; Start-sleep 1;
ValiLogFilePerm -FilePath $logPath ValidateLogFilePerm -FilePath $logPath
Get-Process -Name sshd | % { if($_.SI -ne 0) { Stop-Process $_; Start-sleep 1 } } Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
} }
} }
} }

View File

@ -1,14 +1,22 @@
$tC = 1 If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force
$tC = 1
$tI = 0 $tI = 0
$suite = "portfwd" $suite = "portfwd"
Describe "E2E scenarios for port forwarding" -Tags "CI" { Describe "E2E scenarios for port forwarding" -Tags "CI" {
BeforeAll { BeforeAll {
if($OpenSSHTestInfo -eq $null)
{
Throw "`$OpenSSHTestInfo is null. Please run Set-OpenSSHTestEnvironment to set test environments."
}
$testDir = Join-Path $OpenSSHTestInfo["TestDataPath"] $suite $testDir = Join-Path $OpenSSHTestInfo["TestDataPath"] $suite
if(-not (Test-Path $testDir)) if(-not (Test-Path $testDir))
{ {
$null = New-Item $testDir -ItemType directory -Force -ErrorAction SilentlyContinue $null = New-Item $testDir -ItemType directory -Force -ErrorAction SilentlyContinue
} }
$platform = Get-Platform
$skip = ($platform -eq [PlatformType]::Windows) -and ($PSVersionTable.PSVersion.Major -le 2)
} }
BeforeEach { BeforeEach {
@ -23,12 +31,12 @@ Describe "E2E scenarios for port forwarding" -Tags "CI" {
AfterAll{$tC++} AfterAll{$tC++}
#TODO - this relies on winrm (that is windows specific) #TODO - this relies on winrm (that is windows specific)
It "$tC.$tI - local port forwarding" { It "$tC.$tI - local port forwarding" -skip:$skip {
ssh -L 5432:127.0.0.1:47001 test_target powershell.exe Test-WSMan -computer 127.0.0.1 -port 5432 | Set-Content $stdoutFile ssh -L 5432:127.0.0.1:47001 test_target powershell.exe Test-WSMan -computer 127.0.0.1 -port 5432 | Set-Content $stdoutFile
$stdoutFile | Should Contain "wsmid" $stdoutFile | Should Contain "wsmid"
} }
It "$tC.$tI - remote port forwarding" { It "$tC.$tI - remote port forwarding" -skip:$skip {
ssh -R 5432:127.0.0.1:47001 test_target powershell.exe Test-WSMan -computer 127.0.0.1 -port 5432 | Set-Content $stdoutFile ssh -R 5432:127.0.0.1:47001 test_target powershell.exe Test-WSMan -computer 127.0.0.1 -port 5432 | Set-Content $stdoutFile
$stdoutFile | Should Contain "wsmid" $stdoutFile | Should Contain "wsmid"
} }

View File

@ -1,11 +1,12 @@
 If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force
#covered -i -p -q -r -v -c -S -C #covered -i -p -q -r -v -c -S -C
#todo: -F, -l and -P should be tested over the network #todo: -F, -l and -P should be tested over the network
Describe "Tests for scp command" -Tags "CI" { Describe "Tests for scp command" -Tags "CI" {
BeforeAll { BeforeAll {
if($OpenSSHTestInfo -eq $null) if($OpenSSHTestInfo -eq $null)
{ {
Throw "`$OpenSSHTestInfo is null. Please run Setup-OpenSSHTestEnvironment to setup test environment." Throw "`$OpenSSHTestInfo is null. Please run Set-OpenSSHTestEnvironment to set test environments."
} }
$fileName1 = "test.txt" $fileName1 = "test.txt"
@ -19,8 +20,8 @@ Describe "Tests for scp command" -Tags "CI" {
$NestedSourceFilePath = Join-Path $NestedSourceDir $fileName2 $NestedSourceFilePath = Join-Path $NestedSourceDir $fileName2
$null = New-Item $SourceDir -ItemType directory -Force -ErrorAction SilentlyContinue $null = New-Item $SourceDir -ItemType directory -Force -ErrorAction SilentlyContinue
$null = New-Item $NestedSourceDir -ItemType directory -Force -ErrorAction SilentlyContinue $null = New-Item $NestedSourceDir -ItemType directory -Force -ErrorAction SilentlyContinue
$null = New-item -path $SourceFilePath -force -ErrorAction SilentlyContinue $null = New-item -path $SourceFilePath -ItemType file -force -ErrorAction SilentlyContinue
$null = New-item -path $NestedSourceFilePath -force -ErrorAction SilentlyContinue $null = New-item -path $NestedSourceFilePath -ItemType file -force -ErrorAction SilentlyContinue
"Test content111" | Set-content -Path $SourceFilePath "Test content111" | Set-content -Path $SourceFilePath
"Test content in nested dir" | Set-content -Path $NestedSourceFilePath "Test content in nested dir" | Set-content -Path $NestedSourceFilePath
$null = New-Item $DestinationDir -ItemType directory -Force -ErrorAction SilentlyContinue $null = New-Item $DestinationDir -ItemType directory -Force -ErrorAction SilentlyContinue
@ -94,8 +95,8 @@ Describe "Tests for scp command" -Tags "CI" {
# for the first time, delete the existing log files. # for the first time, delete the existing log files.
if ($OpenSSHTestInfo['DebugMode']) if ($OpenSSHTestInfo['DebugMode'])
{ {
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction ignore Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction ignore Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction SilentlyContinue
} }
function CheckTarget { function CheckTarget {
@ -110,8 +111,8 @@ Describe "Tests for scp command" -Tags "CI" {
$script:logNum++ $script:logNum++
# clear the ssh-agent, sshd logs so that next testcase will get fresh logs. # clear the ssh-agent, sshd logs so that next testcase will get fresh logs.
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction ignore Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction ignore Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction SilentlyContinue
} }
return $false return $false
@ -144,6 +145,7 @@ Describe "Tests for scp command" -Tags "CI" {
AfterEach { AfterEach {
Get-ChildItem $DestinationDir -Recurse | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue Get-ChildItem $DestinationDir -Recurse | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
Start-Sleep 1
} }
@ -184,7 +186,7 @@ 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).Length -eq 0 $equal = @(Compare-Object (Get-ChildItem -Recurse -path $SourceDir) (Get-ChildItem -Recurse -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length).Length -eq 0
$equal | Should Be $true $equal | Should Be $true
if($Options.contains("-p")) if($Options.contains("-p") -and ($platform -eq [PlatformType]::Windows) -and ($PSVersionTable.PSVersion.Major -gt 2))
{ {
$equal = @(Compare-Object (Get-ChildItem -Recurse -path $SourceDir).LastWriteTime.DateTime (Get-ChildItem -Recurse -path (join-path $DestinationDir $SourceDirName) ).LastWriteTime.DateTime).Length -eq 0 $equal = @(Compare-Object (Get-ChildItem -Recurse -path $SourceDir).LastWriteTime.DateTime (Get-ChildItem -Recurse -path (join-path $DestinationDir $SourceDirName) ).LastWriteTime.DateTime).Length -eq 0
$equal | Should Be $true $equal | Should Be $true

View File

@ -1,9 +1,12 @@
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force -DisableNameChecking If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force
Describe "SFTP Test Cases" -Tags "CI" { Describe "SFTP Test Cases" -Tags "CI" {
BeforeAll { BeforeAll {
$serverDirectory = $null
$clientDirectory = $null
if($OpenSSHTestInfo -eq $null) if($OpenSSHTestInfo -eq $null)
{ {
Throw "`$OpenSSHTestInfo is null. Please run Setup-OpenSSHTestEnvironment to setup test environment." Throw "`$OpenSSHTestInfo is null. Please run Set-OpenSSHTestEnvironment to set test environments."
} }
$rootDirectory = "$($OpenSSHTestInfo["TestDataPath"])\SFTP" $rootDirectory = "$($OpenSSHTestInfo["TestDataPath"])\SFTP"
@ -29,8 +32,11 @@ Describe "SFTP Test Cases" -Tags "CI" {
$ssouser = $OpenSSHTestInfo["SSOUser"] $ssouser = $OpenSSHTestInfo["SSOUser"]
$script:testId = 1 $script:testId = 1
Remove-item (Join-Path $rootDirectory "*.$outputFileName") -Force -ErrorAction Ignore Remove-item (Join-Path $rootDirectory "*.$outputFileName") -Force -ErrorAction SilentlyContinue
Remove-item (Join-Path $rootDirectory "*.$batchFileName") -Force -ErrorAction Ignore Remove-item (Join-Path $rootDirectory "*.$batchFileName") -Force -ErrorAction SilentlyContinue
$platform = Get-Platform
$skip = ($platform -eq [PlatformType]::Windows) -and ($PSVersionTable.PSVersion.Major -le 2)
$testData1 = @( $testData1 = @(
@{ @{
@ -162,9 +168,9 @@ Describe "SFTP Test Cases" -Tags "CI" {
# for the first time, delete the existing log files. # for the first time, delete the existing log files.
if ($OpenSSHTestInfo['DebugMode']) if ($OpenSSHTestInfo['DebugMode'])
{ {
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction ignore Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction ignore Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction SilentlyContinue
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sftp-server.log" -Force -ErrorAction ignore Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sftp-server.log" -Force -ErrorAction SilentlyContinue
} }
function CopyDebugLogs { function CopyDebugLogs {
@ -175,21 +181,21 @@ Describe "SFTP Test Cases" -Tags "CI" {
Copy-Item "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sftp-server.log" "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sftp-server_$script:testId.log" -Force Copy-Item "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sftp-server.log" "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sftp-server_$script:testId.log" -Force
# clear the ssh-agent, sshd logs so that next testcase will get fresh logs. # clear the ssh-agent, sshd logs so that next testcase will get fresh logs.
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction ignore Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction ignore Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction SilentlyContinue
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sftp-server.log" -Force -ErrorAction ignore Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sftp-server.log" -Force -ErrorAction SilentlyContinue
} }
} }
} }
AfterAll { AfterAll {
Get-ChildItem $serverDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue if($serverDirectory) { Get-ChildItem $serverDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue }
Get-ChildItem $clientDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue if($clientDirectory) { Get-ChildItem $clientDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue }
} }
BeforeEach { BeforeEach {
Get-ChildItem $serverDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue if($serverDirectory) { Get-ChildItem $serverDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue }
Get-ChildItem $clientDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue if($clientDirectory) { Get-ChildItem $clientDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue }
$outputFilePath = Join-Path $rootDirectory "$($script:testId).$outputFileName" $outputFilePath = Join-Path $rootDirectory "$($script:testId).$outputFileName"
$batchFilePath = Join-Path $rootDirectory "$($script:testId).$batchFileName" $batchFilePath = Join-Path $rootDirectory "$($script:testId).$batchFileName"
} }
@ -212,6 +218,7 @@ Describe "SFTP Test Cases" -Tags "CI" {
It '<Title>' -TestCases:$testData2 { It '<Title>' -TestCases:$testData2 {
param([string]$Title, $Options, $tmpFileName1, $tmpFilePath1, $tmpFileName2, $tmpFilePath2, $tmpDirectoryName1, $tmpDirectoryPath1, $tmpDirectoryName2, $tmpDirectoryPath2) param([string]$Title, $Options, $tmpFileName1, $tmpFilePath1, $tmpFileName2, $tmpFilePath2, $tmpDirectoryName1, $tmpDirectoryPath1, $tmpDirectoryName2, $tmpDirectoryPath2)
if($skip) { return }
#rm (remove file) #rm (remove file)
$commands = "mkdir $tmpDirectoryPath1 $commands = "mkdir $tmpDirectoryPath1
@ -263,16 +270,19 @@ Describe "SFTP Test Cases" -Tags "CI" {
} }
It "$script:testId-ls lists items the user has no read permission" { It "$script:testId-ls lists items the user has no read permission" {
$adminsSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid)
$currentUserSid = Get-UserSID -User "$($env:USERDOMAIN)\$($env:USERNAME)"
$permTestHasAccessFile = "permTestHasAccessFile.txt" $permTestHasAccessFile = "permTestHasAccessFile.txt"
$permTestHasAccessFilePath = Join-Path $serverDirectory $permTestHasAccessFile $permTestHasAccessFilePath = Join-Path $serverDirectory $permTestHasAccessFile
Remove-Item $permTestHasAccessFilePath -Force -ErrorAction Ignore Remove-Item $permTestHasAccessFilePath -Force -ErrorAction SilentlyContinue
New-Item $permTestHasAccessFilePath -ItemType file -Force -value "perm test has access file data" | Out-Null New-Item $permTestHasAccessFilePath -ItemType file -Force -value "perm test has access file data" | Out-Null
$permTestNoAccessFile = "permTestNoAccessFile.txt" $permTestNoAccessFile = "permTestNoAccessFile.txt"
$permTestNoAccessFilePath = Join-Path $serverDirectory $permTestNoAccessFile $permTestNoAccessFilePath = Join-Path $serverDirectory $permTestNoAccessFile
Remove-Item $permTestNoAccessFilePath -Force -ErrorAction Ignore Remove-Item $permTestNoAccessFilePath -Force -ErrorAction SilentlyContinue
New-Item $permTestNoAccessFilePath -ItemType file -Force -value "perm test no access file data" | Out-Null New-Item $permTestNoAccessFilePath -ItemType file -Force -value "perm test no access file data" | Out-Null
Set-FileOwnerAndACL -Filepath $permTestNoAccessFilePath -OwnerPerms "Read","Write" Repair-FilePermission -Filepath $permTestNoAccessFilePath -Owners $currentUserSid -FullAccessNeeded $adminsSid,$currentUserSid -confirm:$false
$Commands = "ls $serverDirectory" $Commands = "ls $serverDirectory"
Set-Content $batchFilePath -Encoding UTF8 -value $Commands Set-Content $batchFilePath -Encoding UTF8 -value $Commands
@ -282,11 +292,11 @@ Describe "SFTP Test Cases" -Tags "CI" {
#cleanup #cleanup
$HasAccessPattern = $permTestHasAccessFilePath.Replace("\", "[/\\]") $HasAccessPattern = $permTestHasAccessFilePath.Replace("\", "[/\\]")
$matches = $content | select-string -Pattern "^/$HasAccessPattern\s{0,}$" $matches = @($content | select-string -Pattern "^/$HasAccessPattern\s{0,}$")
$matches.count | Should be 1 $matches.count | Should be 1
$NoAccessPattern = $permTestNoAccessFilePath.Replace("\", "[/\\]") $NoAccessPattern = $permTestNoAccessFilePath.Replace("\", "[/\\]")
$matches = $content | select-string -Pattern "^/$NoAccessPattern\s{0,}$" $matches = @($content | select-string -Pattern "^/$NoAccessPattern\s{0,}$")
$matches.count | Should be 1 $matches.count | Should be 1
} }
} }

View File

@ -1,4 +1,6 @@
#todo: -i -q -v -l -c -C If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force
#todo: -i -q -v -l -c -C
#todo: -S -F -V -e #todo: -S -F -V -e
$tC = 1 $tC = 1
$tI = 0 $tI = 0
@ -8,7 +10,7 @@ Describe "E2E scenarios for ssh client" -Tags "CI" {
BeforeAll { BeforeAll {
if($OpenSSHTestInfo -eq $null) if($OpenSSHTestInfo -eq $null)
{ {
Throw "`$OpenSSHTestInfo is null. Please run Setup-OpenSSHTestEnvironment to setup test environment." Throw "`$OpenSSHTestInfo is null. Please run Set-OpenSSHTestEnvironment to set test environments."
} }
$server = $OpenSSHTestInfo["Target"] $server = $OpenSSHTestInfo["Target"]
@ -20,6 +22,8 @@ Describe "E2E scenarios for ssh client" -Tags "CI" {
{ {
$null = New-Item $testDir -ItemType directory -Force -ErrorAction SilentlyContinue $null = New-Item $testDir -ItemType directory -Force -ErrorAction SilentlyContinue
} }
$platform = Get-Platform
$skip = ($platform -eq [PlatformType]::Windows) -and ($PSVersionTable.PSVersion.Major -le 2)
<#$testData = @( <#$testData = @(
@{ @{
@ -112,7 +116,7 @@ Describe "E2E scenarios for ssh client" -Tags "CI" {
BeforeAll {$tI=1} BeforeAll {$tI=1}
AfterAll{$tC++} AfterAll{$tC++}
It "$tC.$tI - stdout to file" { It "$tC.$tI - stdout to file" -skip:$skip {
ssh test_target powershell get-process > $stdoutFile ssh test_target powershell get-process > $stdoutFile
$stdoutFile | Should Contain "ProcessName" $stdoutFile | Should Contain "ProcessName"
} }

View File

@ -50,7 +50,7 @@
$client.AddPasswordSetting($password) $client.AddPasswordSetting($password)
} }
AfterEach { AfterEach {
Remove-Item -Path $filePath -Force -ea ignore Remove-Item -Path $filePath -Force -ea SilentlyContinue
} }
AfterAll { AfterAll {

View File

@ -126,3 +126,4 @@ PubkeyAcceptedKeyTypes ssh-ed25519*
#AllowUsers allowuser1 allowu*r2 allow?se?3 allowuser4 localuser1 localu*r2 loc?lu?er3 localadmin #AllowUsers allowuser1 allowu*r2 allow?se?3 allowuser4 localuser1 localu*r2 loc?lu?er3 localadmin
#DenyGroups denygroup1 denygr*p2 deny?rou?3 #DenyGroups denygroup1 denygr*p2 deny?rou?3
#AllowGroups allowgroup1 allowg*2 allowg?ou?3 Adm* #AllowGroups allowgroup1 allowg*2 allowg?ou?3 Adm*
hostkeyagent \\.\pipe\openssh-ssh-agent

View File

@ -1,4 +1,5 @@
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force -DisableNameChecking If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force
$tC = 1 $tC = 1
$tI = 0 $tI = 0
@ -8,7 +9,7 @@ Describe "Tests for user Key file permission" -Tags "CI" {
BeforeAll { BeforeAll {
if($OpenSSHTestInfo -eq $null) if($OpenSSHTestInfo -eq $null)
{ {
Throw "`$OpenSSHTestInfo is null. Please run Setup-OpenSSHTestEnvironment to setup test environment." Throw "`$OpenSSHTestInfo is null. Please run Set-OpenSSHTestEnvironment to setup test environment."
} }
$testDir = "$($OpenSSHTestInfo["TestDataPath"])\$suite" $testDir = "$($OpenSSHTestInfo["TestDataPath"])\$suite"
if( -not (Test-path $testDir -PathType Container)) if( -not (Test-path $testDir -PathType Container))
@ -25,12 +26,12 @@ Describe "Tests for user Key file permission" -Tags "CI" {
$userName = "$env:USERNAME@$env:USERDOMAIN" $userName = "$env:USERNAME@$env:USERDOMAIN"
$keypassphrase = "testpassword" $keypassphrase = "testpassword"
$systemAccount = New-Object System.Security.Principal.NTAccount("NT AUTHORITY", "SYSTEM") $systemSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::LocalSystemSid)
$adminsAccount = New-Object System.Security.Principal.NTAccount("BUILTIN","Administrators") $adminsSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid)
$objUser = New-Object System.Security.Principal.NTAccount($ssouser) $currentUserSid = Get-UserSID -User "$($env:USERDOMAIN)\$($env:USERNAME)"
$pubKeyUserAccount = New-Object System.Security.Principal.NTAccount($pubKeyUser) $objUserSid = Get-UserSID -User $ssouser
$currentUser = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME)) $everyoneSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::WorldSid)
$everyone = New-Object System.Security.Principal.NTAccount("EveryOne") $pubKeyUserAccountSid = Get-UserSID -User $pubKeyUser
Add-PasswordSetting -Pass $keypassphrase Add-PasswordSetting -Pass $keypassphrase
} }
@ -48,7 +49,7 @@ Describe "Tests for user Key file permission" -Tags "CI" {
BeforeAll { BeforeAll {
$keyFileName = "sshtest_userPermTestkey_ed25519" $keyFileName = "sshtest_userPermTestkey_ed25519"
$keyFilePath = Join-Path $testDir $keyFileName $keyFilePath = Join-Path $testDir $keyFileName
Remove-Item -path "$keyFilePath*" -Force -ErrorAction Ignore Remove-Item -path "$keyFilePath*" -Force -ErrorAction SilentlyContinue
ssh-keygen.exe -t ed25519 -f $keyFilePath -P $keypassphrase ssh-keygen.exe -t ed25519 -f $keyFilePath -P $keypassphrase
$pubKeyUserProfilePath = Join-Path $pubKeyUserProfile .ssh $pubKeyUserProfilePath = Join-Path $pubKeyUserProfile .ssh
@ -58,22 +59,22 @@ Describe "Tests for user Key file permission" -Tags "CI" {
$testAuthorizedKeyPath = Join-Path $pubKeyUserProfilePath authorized_keys $testAuthorizedKeyPath = Join-Path $pubKeyUserProfilePath authorized_keys
Copy-Item "$keyFilePath.pub" $testAuthorizedKeyPath -Force -ErrorAction SilentlyContinue Copy-Item "$keyFilePath.pub" $testAuthorizedKeyPath -Force -ErrorAction SilentlyContinue
Adjust-UserKeyFileACL -FilePath $testAuthorizedKeyPath -Owner $pubKeyUserAccount -OwnerPerms "Read, Write" Repair-AuthorizedKeyPermission -FilePath $testAuthorizedKeyPath -confirm:$false
Add-PermissionToFileACL -FilePath $testAuthorizedKeyPath -User "NT Service\sshd" -Perm "Read"
$tI=1 $tI=1
} }
AfterAll { AfterAll {
if(Test-Path $testAuthorizedKeyPath) { if(Test-Path $testAuthorizedKeyPath) {
Remove-Item $testAuthorizedKeyPath -Force -ErrorAction Ignore Remove-Item $testAuthorizedKeyPath -Force -ErrorAction SilentlyContinue
} }
if(Test-Path $pubKeyUserProfilePath) { if(Test-Path $pubKeyUserProfilePath) {
Remove-Item $pubKeyUserProfilePath -Recurse -Force -ErrorAction Ignore Remove-Item $pubKeyUserProfilePath -Recurse -Force -ErrorAction SilentlyContinue
} }
$tC++ $tC++
} }
It "$tC.$tI-ssh with private key file -- positive (Secured private key owned by current user)" { It "$tC.$tI-ssh with private key file -- positive (Secured private key owned by current user)" {
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $currentUser -OwnerPerms "Read, Write" Repair-FilePermission -FilePath $keyFilePath -Owners $currentUserSid -FullAccessNeeded $adminsSid,$systemSid,$currentUserSid -confirm:$false
#Run #Run
$o = ssh -p $port -i $keyFilePath $pubKeyUser@$server echo 1234 $o = ssh -p $port -i $keyFilePath $pubKeyUser@$server echo 1234
$o | Should Be "1234" $o | Should Be "1234"
@ -81,7 +82,7 @@ Describe "Tests for user Key file permission" -Tags "CI" {
It "$tC.$tI-ssh with private key file -- positive(Secured private key owned by Administrators group and current user has no explicit ACE)" { It "$tC.$tI-ssh with private key file -- positive(Secured private key owned by Administrators group and current user has no explicit ACE)" {
#setup to have local admin group as owner and grant it full control #setup to have local admin group as owner and grant it full control
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $adminsAccount -OwnerPerms "FullControl" Repair-FilePermission -FilePath $keyFilePath -Owners $adminsSid -FullAccessNeeded $adminsSid,$systemSid -confirm:$false
#Run #Run
$o = ssh -p $port -i $keyFilePath $pubKeyUser@$server echo 1234 $o = ssh -p $port -i $keyFilePath $pubKeyUser@$server echo 1234
@ -90,8 +91,7 @@ Describe "Tests for user Key file permission" -Tags "CI" {
It "$tC.$tI-ssh with private key file -- positive(Secured private key owned by Administrators group and current user has explicit ACE)" { It "$tC.$tI-ssh with private key file -- positive(Secured private key owned by Administrators group and current user has explicit ACE)" {
#setup to have local admin group as owner and grant it full control #setup to have local admin group as owner and grant it full control
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $adminsAccount -OwnerPerms "FullControl" Repair-FilePermission -FilePath $keyFilePath -Owners $adminsSid -FullAccessNeeded $adminsSid,$systemSid -ReadAccessNeeded $currentUserSid -confirm:$false
Add-PermissionToFileACL -FilePath $keyFilePath -User $currentUser -Perm "Read"
#Run #Run
$o = ssh -p $port -i $keyFilePath $pubKeyUser@$server echo 1234 $o = ssh -p $port -i $keyFilePath $pubKeyUser@$server echo 1234
@ -100,8 +100,7 @@ Describe "Tests for user Key file permission" -Tags "CI" {
It "$tC.$tI-ssh with private key file -- positive (Secured private key owned by local system)" { It "$tC.$tI-ssh with private key file -- positive (Secured private key owned by local system)" {
#setup to have local system as owner and grant it full control #setup to have local system as owner and grant it full control
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $systemAccount -OwnerPerms "FullControl" Repair-FilePermission -FilePath $keyFilePath -Owners $systemSid -FullAccessNeeded $adminsSid,$systemSid -confirm:$false
Add-PermissionToFileACL -FilePath $keyFilePath -User $adminsAccount -Perm "Read"
#Run #Run
$o = ssh -p $port -i $keyFilePath $pubKeyUser@$server echo 1234 $o = ssh -p $port -i $keyFilePath $pubKeyUser@$server echo 1234
@ -110,10 +109,7 @@ Describe "Tests for user Key file permission" -Tags "CI" {
It "$tC.$tI-ssh with private key file -- negative(other account can access private key file)" { It "$tC.$tI-ssh with private key file -- negative(other account can access private key file)" {
#setup to have current user as owner and grant it full control #setup to have current user as owner and grant it full control
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $currentUser -OwnerPerms "Read, Write" Repair-FilePermission -FilePath $keyFilePath -Owners $currentUserSid -FullAccessNeeded $currentUser,$adminsSid,$systemSid -ReadAccessNeeded $objUserSid -confirm:$false
#add ssouser to access the private key
Add-PermissionToFileACL -FilePath $keyFilePath -User $objUser -Perm "Read"
#Run #Run
$o = ssh -p $port -i $keyFilePath -E $logPath $pubKeyUser@$server echo 1234 $o = ssh -p $port -i $keyFilePath -E $logPath $pubKeyUser@$server echo 1234
@ -124,8 +120,7 @@ Describe "Tests for user Key file permission" -Tags "CI" {
It "$tC.$tI-ssh with private key file -- negative(the private key has wrong owner)" { It "$tC.$tI-ssh with private key file -- negative(the private key has wrong owner)" {
#setup to have ssouser as owner and grant it full control #setup to have ssouser as owner and grant it full control
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $objUser -OwnerPerms "Read, Write" Repair-FilePermission -FilePath $keyFilePath -Owners $objUserSid -FullAccessNeeded $objUserSid,$adminsSid,$systemSid -ReadAccessNeeded $objUserSid -confirm:$false
Add-PermissionToFileACL -FilePath $keyFilePath -User $adminsAccount -Perm "FullControl"
$o = ssh -p $port -i $keyFilePath -E $logPath $pubKeyUser@$server echo 1234 $o = ssh -p $port -i $keyFilePath -E $logPath $pubKeyUser@$server echo 1234
$LASTEXITCODE | Should Not Be 0 $LASTEXITCODE | Should Not Be 0

View File

@ -605,8 +605,9 @@ derelativise_path(const char *path)
return xstrdup("none"); return xstrdup("none");
expanded = tilde_expand_filename(path, getuid()); expanded = tilde_expand_filename(path, getuid());
#ifdef WINDOWS #ifdef WINDOWS
/* Windows absolute paths have a drive letter followed by :*/ /* Windows absolute paths - \abc, /abc, c:\abc, c:/abc*/
if (*expanded != '\0' && expanded[1] == ':') if (*expanded == '/' || *expanded == '\\' ||
(*expanded != '\0' && expanded[1] == ':'))
#else /* !WINDOWS */ #else /* !WINDOWS */
if (*expanded == '/') if (*expanded == '/')
#endif /* !WINDOWS */ #endif /* !WINDOWS */

View File

@ -477,6 +477,9 @@ int do_exec_windows(Session *s, const char *command, int pty) {
*cmd = '\0'; *cmd = '\0';
} }
/* load user profile */
mm_load_profile(s->pw->pw_name, ((INT_PTR)s->authctxt->auth_token) & 0xffffffff);
/* start the process */ /* start the process */
{ {
memset(&si, 0, sizeof(STARTUPINFO)); memset(&si, 0, sizeof(STARTUPINFO));
@ -492,7 +495,7 @@ int do_exec_windows(Session *s, const char *command, int pty) {
si.hStdError = (HANDLE)w32_fd_to_handle(pipeerr[1]); si.hStdError = (HANDLE)w32_fd_to_handle(pipeerr[1]);
si.lpDesktop = NULL; si.lpDesktop = NULL;
hToken = s->authctxt->methoddata; hToken = s->authctxt->auth_token;
debug("Executing command: %s", exec_command); debug("Executing command: %s", exec_command);
UTF8_TO_UTF16_FATAL(exec_command_w, exec_command); UTF8_TO_UTF16_FATAL(exec_command_w, exec_command);

11
sftp.c
View File

@ -296,9 +296,14 @@ static void
local_do_shell(const char *args) local_do_shell(const char *args)
{ {
#ifdef WINDOWS #ifdef WINDOWS
/* execute via system call in Windows*/ /* execute via system call in Windows*/
if (!*args) { char cmd_path[PATH_MAX] = { 0, };
args = (char *) getenv("ComSpec"); // get name of Windows cmd shell if (!*args){
if (!GetSystemDirectory(cmd_path, sizeof(cmd_path)))
fatal("GetSystemDirectory failed");
strcat_s(cmd_path, PATH_MAX, "\\cmd.exe");
args = cmd_path;
} else { } else {
convertToBackslash((char *) args); convertToBackslash((char *) args);
} }

4
sshd.c
View File

@ -1765,9 +1765,7 @@ main(int ac, char **av)
error("Could not connect to agent \"%s\": %s", error("Could not connect to agent \"%s\": %s",
options.host_key_agent, ssh_err(r)); options.host_key_agent, ssh_err(r));
} }
#ifdef WINDOWS /* Windows version always needs and has agent running */
have_agent = 1;
#endif
for (i = 0; i < options.num_host_key_files; i++) { for (i = 0; i < options.num_host_key_files; i++) {
if (options.host_key_files[i] == NULL) if (options.host_key_files[i] == NULL)
continue; continue;