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
branches:
only:
- latestw_all
- latestw_all_openssl
init:
- ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
build_script:
- 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
after_build:
- 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
before_test:
- ps: |
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking
Setup-OpenSSHTestEnvironment -Quiet
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1
Set-OpenSSHTestEnvironment -Confirm:$false
test_script:
- ps: |
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking
Run-OpenSSHTests
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1
Invoke-OpenSSHTests
after_test:
- ps: |
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking
Upload-OpenSSHTestResults
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1
Publish-OpenSSHTestResults
on_finish:
- 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

View File

@ -226,38 +226,45 @@ sys_auth_passwd(Authctxt *authctxt, const char *password)
#elif defined(WINDOWS)
/*
* Authenticate on Windows - Pass credentials to ssh-agent and retrieve token
* upon successful authentication
* TODO - password is sent in plain text over IPC. Consider implications.
* Authenticate on Windows - Call LogonUser and retrieve user token
*/
int sys_auth_passwd(Authctxt *authctxt, const char *password)
{
struct sshbuf *msg = NULL;
size_t blen = 0;
DWORD token = 0;
extern int auth_sock;
wchar_t *user_utf16 = NULL, *udom_utf16 = NULL, *pwd_utf16 = NULL, *tmp;
HANDLE token = NULL;
int r = 0;
int ssh_request_reply(int, struct sshbuf *, struct sshbuf *);
msg = sshbuf_new();
if (!msg)
fatal("%s: out of memory", __func__);
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;
if ((user_utf16 = utf8_to_utf16(authctxt->pw->pw_name)) == NULL ||
(pwd_utf16 = utf8_to_utf16(password)) == NULL) {
fatal("out of memory");
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;
done:
if (msg)
sshbuf_free(msg);
if (user_utf16)
free(user_utf16);
if (pwd_utf16)
SecureZeroMemory(pwd_utf16, sizeof(wchar_t) * wcslen(pwd_utf16));
return r;
}
#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,
"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
* compatible and prepend the '%h/'
@ -413,6 +420,8 @@ expand_authorized_keys(const char *filename, struct passwd *pw)
return (file);
i = snprintf(ret, sizeof(ret), "%s/%s", pw->pw_dir, file);
#endif // WINDOWS
if (i < 0 || (size_t)i >= sizeof(ret))
fatal("expand_authorized_keys: path too long");
free(file);

4
auth.h
View File

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

View File

@ -200,54 +200,14 @@ userauth_pubkey(struct ssh *ssh)
/* test for correct signature */
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)) &&
#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),
sshbuf_len(b), ssh->compat)) == 0) {
#endif
authenticated = 1;
/* Record the successful key to prevent reuse */
auth2_record_userkey(authctxt, key);
@ -255,7 +215,6 @@ userauth_pubkey(struct ssh *ssh)
}
sshbuf_free(b);
free(sig);
#endif /* !WINDOWS */
} else {
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);
/* Messages for the authentication agent connection. */
/* Message Id 0 is reserved */
#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
#define SSH_AGENT_RSA_IDENTITIES_ANSWER 2
#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_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 */

View File

@ -1,12 +1,14 @@
$ErrorActionPreference = 'Stop'
Import-Module $PSScriptRoot\OpenSSHCommonUtils.psm1 -Force -DisableNameChecking
Import-Module $PSScriptRoot\OpenSSHBuildHelper.psm1 -Force -DisableNameChecking
Import-Module $PSScriptRoot\OpenSSHTestHelper.psm1 -Force -DisableNameChecking
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\OpenSSHBuildHelper.psm1 -Force
Import-Module $PSScriptRoot\OpenSSHTestHelper.psm1 -Force
$repoRoot = Get-RepositoryRoot
$script:messageFile = join-path $repoRoot.FullName "BuildMessage.log"
# Sets a build variable
# Write the build message
Function Write-BuildMessage
{
param(
@ -77,12 +79,11 @@ function Invoke-AppVeyorFull
{
$env:APPVEYOR_SCHEDULED_BUILD = 'True'
}
try {
Set-OpenSSHTestParams
try {
Invoke-AppVeyorBuild
Install-OpenSSH
Setup-OpenSSHTestEnvironment
Run-OpenSSHTests
Set-OpenSSHTestEnvironment -confirm:$false
Invoke-OpenSSHTests
Publish-Artifact
}
finally {
@ -97,8 +98,8 @@ function Invoke-AppVeyorFull
function Invoke-AppVeyorBuild
{
Set-BuildVariable TestPassed True
Build-OpenSSH -Configuration Release -NativeHostArch x64
Build-OpenSSH -Configuration Debug -NativeHostArch x86
Start-OpenSSHBuild -Configuration Release -NativeHostArch x64
Start-OpenSSHBuild -Configuration Release -NativeHostArch x86
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
Publishes package build artifacts.
@ -170,11 +265,11 @@ function Add-Artifact
function Publish-Artifact
{
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
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)
{
@ -186,7 +281,6 @@ function Publish-Artifact
foreach ($artifact in $artifacts)
{
Write-Host "Publishing $artifact as Appveyor artifact"
# NOTE: attempt to publish subsequent artifacts even if the current one fails
Push-AppveyorArtifact $artifact -ErrorAction Continue
}
}
@ -195,10 +289,10 @@ function Publish-Artifact
.Synopsis
Runs the tests for this repo
#>
function Run-OpenSSHTests
function Invoke-OpenSSHTests
{
Write-Host "Start running unit tests"
$unitTestFailed = Run-OpenSSHUnitTest
$unitTestFailed = Invoke-OpenSSHUnitTest
if($unitTestFailed)
{
@ -212,14 +306,14 @@ function Run-OpenSSHTests
Write-BuildMessage -Message "All Unit tests passed!" -Category Information
}
# Run all E2E tests.
Run-OpenSSHE2ETest
Invoke-OpenSSHE2ETest
if (($OpenSSHTestInfo -eq $null) -or (-not (Test-Path $OpenSSHTestInfo["E2ETestResultsFile"])))
{
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
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)
{
$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
upload OpenSSH pester test results.
#>
function Upload-OpenSSHTestResults
function Publish-OpenSSHTestResults
{
if ($env:APPVEYOR_JOB_ID)
{

View File

@ -1,7 +1,7 @@
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
param ()
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
#check sshd config file

View File

@ -1,7 +1,7 @@
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
param ()
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

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
[System.IO.DirectoryInfo] $script:OpenSSHRoot = $null
[System.IO.DirectoryInfo] $script:gitRoot = $null
@ -83,7 +83,7 @@ function Write-BuildMsg
[switch] $Silent
)
if ($AsVerbose)
if($PSBoundParameters.ContainsKey("AsVerbose"))
{
if ($script:Verbose)
{
@ -96,17 +96,24 @@ function Write-BuildMsg
return
}
if ($AsInfo)
if($PSBoundParameters.ContainsKey("AsInfo"))
{
Write-Log -Message "INFO: $message"
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
}
if ($AsWarning)
if($PSBoundParameters.ContainsKey("AsWarning"))
{
Write-Log -Message "WARNING: $message"
if (-not $Silent)
@ -116,7 +123,7 @@ function Write-BuildMsg
return
}
if ($AsError)
if($PSBoundParameters.ContainsKey("AsError"))
{
Write-Log -Message "ERROR: $message"
if (-not $Silent)
@ -137,8 +144,6 @@ function Write-BuildMsg
function Start-OpenSSHBootstrap
{
[bool] $silent = -not $script:Verbose
Set-StrictMode -Version Latest
Write-BuildMsg -AsInfo -Message "Checking tools and dependencies" -Silent:$silent
$machinePath = [Environment]::GetEnvironmentVariable('Path', 'MACHINE')
@ -146,7 +151,7 @@ function Start-OpenSSHBootstrap
# Install chocolatey
$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
}
@ -156,20 +161,38 @@ function Start-OpenSSHBootstrap
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
$gitCmdPath = "$env:ProgramFiles\git\cmd"
if (-not ($machinePath.ToLower().Contains($gitCmdPath.ToLower())))
{
Write-BuildMsg -AsVerbose -Message "Adding $gitCmdPath to Path environment variable" -Silent:$silent
$newMachineEnvironmentPath = "$gitCmdPath;$newMachineEnvironmentPath"
if(-not ($env:Path.ToLower().Contains($gitCmdPath.ToLower())))
{
$env:Path = "$gitCmdPath;$env:Path"
}
}
else
{
Write-BuildMsg -AsVerbose -Message "$gitCmdPath already present in Path environment variable" -Silent:$silent
}
$nativeMSBuildPath = "${env:ProgramFiles(x86)}\MSBuild\14.0\bin"
if($script:platform -ieq "AMD64")
$nativeMSBuildPath = "${env:ProgramFiles(x86)}\MSBuild\14.0\bin"
if($env:PROCESSOR_ARCHITECTURE -ieq "AMD64")
{
$nativeMSBuildPath += "\amd64"
}
@ -178,12 +201,15 @@ function Start-OpenSSHBootstrap
{
Write-BuildMsg -AsVerbose -Message "Adding $nativeMSBuildPath to Path environment variable" -Silent:$silent
$newMachineEnvironmentPath += ";$nativeMSBuildPath"
$env:Path += ";$nativeMSBuildPath"
if(-not ($env:Path.ToLower().Contains($nativeMSBuildPath.ToLower())))
{
$env:Path += ";$nativeMSBuildPath"
}
}
else
{
Write-BuildMsg -AsVerbose -Message "$nativeMSBuildPath already present in Path environment variable" -Silent:$silent
}
}
# Update machine environment path
if ($newMachineEnvironmentPath -ne $machinePath)
@ -191,42 +217,53 @@ function Start-OpenSSHBootstrap
[Environment]::SetEnvironmentVariable('Path', $newMachineEnvironmentPath, 'MACHINE')
}
# Install Visual Studio 2015 Community
$packageName = "VisualStudio2015Community"
$VSPackageInstalled = Get-ItemProperty "HKLM:\software\WOW6432Node\Microsoft\VisualStudio\14.0\setup\vs" -ErrorAction SilentlyContinue
if ($null -eq $VSPackageInstalled)
$VCTargetsPath = "${env:ProgramFiles(x86)}\MSBuild\Microsoft.Cpp\v4.0\V140"
if([Environment]::GetEnvironmentVariable('VCTargetsPath', 'MACHINE') -eq $null)
{
Write-BuildMsg -AsInfo -Message "$packageName not present. Installing $packageName."
$adminFilePath = "$script:OpenSSHRoot\contrib\win32\openssh\VSWithBuildTools.xml"
choco install $packageName -packageParameters "--AdminFile $adminFilePath" -y --force --limitoutput --execution-timeout 10000 2>&1 >> $script:BuildLogFile
[Environment]::SetEnvironmentVariable('VCTargetsPath', $VCTargetsPath, 'MACHINE')
}
else
if ($env:VCTargetsPath -eq $null)
{
Write-BuildMsg -AsVerbose -Message "$packageName present. Skipping installation." -Silent:$silent
$env:VCTargetsPath = $VCTargetsPath
}
# Install Windows 8.1 SDK
$packageName = "windows-sdk-8.1"
$vcVars = "${env:ProgramFiles(x86)}\Microsoft Visual Studio 14.0\Common7\Tools\vsvars32.bat"
$sdkPath = "${env:ProgramFiles(x86)}\Windows Kits\8.1\bin\x86\register_app.vbs"
if (-not (Test-Path -Path $sdkPath))
{
Write-BuildMsg -AsInfo -Message "Windows 8.1 SDK not present. Installing $packageName."
choco install $packageName -y --limitoutput --force 2>&1 >> $script:BuildLogFile
$packageName = "vcbuildtools"
If ((-not (Test-Path $nativeMSBuildPath)) -or (-not (Test-Path $VcVars)) -or (-not (Test-Path $sdkPath))) {
Write-BuildMsg -AsInfo -Message "$packageName 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
$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
{
Write-BuildMsg -AsInfo -Message "$packageName present. Skipping installation." -Silent:$silent
}
# 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
Write-BuildMsg -AsVerbose -Message 'VC++ 2015 Build Tools already present.'
}
# Ensure the VS C toolset is installed
@ -241,11 +278,11 @@ function Start-OpenSSHBootstrap
Write-BuildMsg -AsVerbose -Message "vcPath: $script:vcPath" -Silent:$silent
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
@ -264,7 +301,7 @@ function Clone-Win32OpenSSH
Pop-Location
}
function Delete-Win32OpenSSH
function Remove-Win32OpenSSHRepo
{
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)]
param
@ -290,7 +327,7 @@ function Package-OpenSSH
[ValidateSet('x86', 'x64')]
[string]$NativeHostArch = "x64",
[ValidateSet('Debug', 'Release', '')]
[ValidateSet('Debug', 'Release')]
[string]$Configuration = "Release",
# Copy payload to DestinationPath instead of packaging
@ -315,7 +352,7 @@ function Package-OpenSSH
if ($NativeHostArch -ieq 'x86') {
$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
#sleep to wait the servicelog file write
@ -361,11 +398,17 @@ function Package-OpenSSH
}
else {
Remove-Item ($packageDir + '.zip') -Force -ErrorAction SilentlyContinue
Compress-Archive -Path $packageDir -DestinationPath ($packageDir + '.zip')
Write-BuildMsg -AsInfo -Message "Packaged Payload - '$packageDir'.zip"
if(get-command Compress-Archive -ErrorAction SilentlyContinue)
{
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
if ($DestinationPath -ne "") {
Copy-Item -Path $symbolsDir\* -Destination $DestinationPath -Force -Recurse
@ -373,13 +416,20 @@ function Package-OpenSSH
}
else {
Remove-Item ($symbolsDir + '.zip') -Force -ErrorAction SilentlyContinue
Compress-Archive -Path $symbolsDir -DestinationPath ($symbolsDir + '.zip')
Write-BuildMsg -AsInfo -Message "Packaged Symbols - '$symbolsDir'.zip"
if(get-command Compress-Archive -ErrorAction SilentlyContinue)
{
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
}
function Build-OpenSSH
function Start-OpenSSHBuild
{
[CmdletBinding(SupportsShouldProcess=$false)]
param
@ -387,12 +437,11 @@ function Build-OpenSSH
[ValidateSet('x86', 'x64')]
[string]$NativeHostArch = "x64",
[ValidateSet('Debug', 'Release', '')]
[ValidateSet('Debug', 'Release')]
[string]$Configuration = "Release",
[switch]$NoOpenSSL
)
Set-StrictMode -Version Latest
)
$script:BuildLogFile = $null
[System.IO.DirectoryInfo] $repositoryRoot = Get-RepositoryRoot
@ -420,9 +469,9 @@ function Build-OpenSSH
$script:win32OpenSSHPath = join-path $script:gitRoot "Win32-OpenSSH"
if (-not (Test-Path (Join-Path $PSScriptRoot LibreSSLSDK)))
{
Clone-Win32OpenSSH
Get-Win32OpenSSHRepo
Copy-LibreSSLSDK
Delete-Win32OpenSSH
Remove-Win32OpenSSHRepo
}
if ($NoOpenSSL)
@ -465,7 +514,7 @@ function Get-BuildLogFile
[ValidateSet('x86', 'x64')]
[string]$NativeHostArch = "x64",
[ValidateSet('Debug', 'Release', '')]
[ValidateSet('Debug', 'Release')]
[string]$Configuration = "Release"
)
@ -483,122 +532,6 @@ function Get-SolutionFile
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"
)
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
Export-ModuleMember -Function Start-OpenSSHBuild, Get-BuildLogFile, Start-OpenSSHPackage

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
Finds the root of the git repository
.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
None
.Notes
FileNotFoundException is thrown if the current directory does not contain a CMakeLists.txt file.
#>
function Get-RepositoryRoot
{
$currentDir = (Get-Item -Path $PSCommandPath).Directory
{
$start = $currentDir = (Get-Item -Path $PSScriptRoot)
while ($null -ne $currentDir.Parent)
{
$path = Join-Path -Path $currentDir.FullName -ChildPath '.git'
@ -24,147 +22,7 @@ function Get-RepositoryRoot
}
$currentDir = $currentDir.Parent
}
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
return $start
}
<#
@ -177,9 +35,9 @@ function Adjust-UserKeyFileACL
.Inputs
FilePath - The path to the file
User - account name
Perm - The permission to grant.
Perms - The permission to grant.
#>
function Add-PermissionToFileACL
function Add-PermissionToFileACL
{
param (
[parameter(Mandatory=$true)]
@ -200,8 +58,8 @@ function Add-PermissionToFileACL
$myACL.AddAccessRule($userACE)
}
}
Enable-Privilege SeRestorePrivilege | out-null
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'
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
# test environment parameters initialized with defaults
@ -17,23 +19,28 @@ $Script:E2ETestResultsFile = Join-Path $TestDataPath $E2ETestResultsFileName
$Script:UnitTestResultsFile = Join-Path $TestDataPath $UnitTestResultsFileName
$Script:TestSetupLogFile = Join-Path $TestDataPath $TestSetupLogFileName
$Script:E2ETestDirectory = Join-Path $repositoryRoot.FullName -ChildPath "regress\pesterTests"
$Script:WindowsInBox = $false
<#
.Synopsis
Setup-OpenSSHTestEnvironment
Set-OpenSSHTestEnvironment
TODO - split these steps into client and server side
#>
function Setup-OpenSSHTestEnvironment
function Set-OpenSSHTestEnvironment
{
[CmdletBinding()]
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
param
(
[switch] $Quiet,
(
[string] $OpenSSHBinPath,
[string] $TestDataPath = "$env:SystemDrive\OpenSSHTests",
[Boolean] $DebugMode = $false
)
if($PSBoundParameters.ContainsKey("Verbose"))
{
$verboseInfo = ($PSBoundParameters['Verbose']).IsPresent
}
if($Global:OpenSSHTestInfo -ne $null)
{
$Global:OpenSSHTestInfo.Clear()
@ -65,41 +72,30 @@ function Setup-OpenSSHTestEnvironment
#if user does not set path, pick it up
if([string]::IsNullOrEmpty($OpenSSHBinPath))
{
$sshcmd = get-command ssh.exe -ErrorAction Ignore
$sshcmd = get-command ssh.exe -ErrorAction SilentlyContinue
if($sshcmd -eq $null)
{
Throw "Cannot find ssh.exe. Please specify -OpenSSHBinPath to the OpenSSH installed location."
}
elseif($Quiet)
{
$dirToCheck = split-path $sshcmd.Path
$script:OpenSSHBinPath = $dirToCheck
}
else
{
$dirToCheck = split-path $sshcmd.Path
$message = "Do you want to test openssh installed at $($dirToCheck)? [Yes] Y; [No] N (default is `"Y`")"
$response = Read-Host -Prompt $message
if( ($response -eq "") -or ($response -ieq "Y") -or ($response -ieq "Yes") )
{
$script:OpenSSHBinPath = $dirToCheck
}
elseif( ($response -ieq "N") -or ($response -ieq "No") )
$description = "Pick up ssh.exe from $dirToCheck."
$prompt = "Are you sure you want to pick up ssh.exe from $($dirToCheck)?"
$caption = "Found ssh.exe from $dirToCheck"
if(-not $pscmdlet.ShouldProcess($description, $prompt, $caption))
{
Write-Host "User decided not to pick up ssh.exe from $dirToCheck. Please specify -OpenSSHBinPath to the OpenSSH installed location."
return
}
else
{
Throw "User entered invalid option ($response). Please specify -OpenSSHBinPath to the OpenSSH installed location"
}
$script:OpenSSHBinPath = $dirToCheck
}
}
else
{
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
{
@ -113,7 +109,15 @@ function Setup-OpenSSHTestEnvironment
$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
- sshd_config will be backed up as sshd_config.ori
- 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
- test accounts - ssouser, pubkeyuser, and passwduser will be added
- Setup single signon for ssouser
- To cleanup - Run Cleanup-OpenSSHTestEnvironment
"@
if (-not $Quiet) {
Write-Warning $warning
$continue = Read-Host -Prompt "Do you want to continue with the above changes? [Yes] Y; [No] N (default is `"Y`")"
if( ($continue -ieq "N") -or ($continue -ieq "No") )
{
Write-Host "User decided not to make the changes."
return
}
elseif(($continue -ne "") -and ($continue -ine "Y") -and ($continue -ine "Yes"))
{
Throw "User entered invalid option ($continue). Exit now."
}
- To cleanup - Run Clear-OpenSSHTestEnvironment
"@
$prompt = "Are you sure you want to perform the above operations?"
$caption = $description
if(-not $pscmdlet.ShouldProcess($description, $prompt, $caption))
{
Write-Host "User decided not to make the changes."
return
}
Install-OpenSSHTestDependencies
@ -154,9 +152,15 @@ WARNING: Following changes will be made to OpenSSH configuration
if (-not (Test-Path $backupConfigPath -PathType Leaf)) {
Copy-Item (Join-Path $script:OpenSSHBinPath sshd_config) $backupConfigPath -Force
}
$targetsshdConfig = Join-Path $script:OpenSSHBinPath 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
@ -164,12 +168,18 @@ WARNING: Following changes will be made to OpenSSH configuration
Copy-Item "$($Script:E2ETestDirectory)\sshtest*hostkey*" $script:OpenSSHBinPath -Force
Get-ChildItem "$($script:OpenSSHBinPath)\sshtest*hostkey*"| % {
#workaround for the cariggage new line added by git before copy them
(Get-Content $_.FullName -Raw).Replace("`r`n","`n") | Set-Content $_.FullName -Force
Adjust-HostKeyFileACL -FilePath $_.FullName
if (-not ($_.Name.EndsWith(".pub"))) {
#register private key with agent
ssh-add-hostkey.ps1 $_.FullName
}
$filePath = "$($_.FullName)"
$con = (Get-Content $filePath | Out-String).Replace("`r`n","`n")
Set-Content -Path $filePath -Value "$con"
if (-not ($_.Name.EndsWith(".pub")))
{
Repair-SshdHostKeyPermission -FilePath $_.FullName -confirm:$false
if($psversiontable.BuildVersion.Major -gt 6)
{
#register private key with agent
ssh-add-hostkey.ps1 $_.FullName
}
}
}
Restart-Service sshd -Force
@ -192,7 +202,7 @@ WARNING: Following changes will be made to OpenSSH configuration
Copy-Item $sshConfigFilePath (Join-Path $dotSshDirectoryPath config.ori) -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
#TODO - this is Windows specific. Need to be in PAL
@ -210,21 +220,22 @@ WARNING: Following changes will be made to OpenSSH configuration
}
}
#setup single sign on for ssouser
#setup single sign on for ssouser
$ssouserProfile = Get-LocalUserProfile -User $SSOUser
$Global:OpenSSHTestInfo.Add("SSOUserProfile", $ssouserProfile)
$Global:OpenSSHTestInfo.Add("PubKeyUserProfile", (Get-LocalUserProfile -User $PubKeyUser))
$Global:OpenSSHTestInfo.Add("PubKeyUserProfile", (Get-LocalUserProfile -User $PubKeyUser))
New-Item -ItemType Directory -Path (Join-Path $ssouserProfile .ssh) -Force -ErrorAction SilentlyContinue | out-null
$authorizedKeyPath = Join-Path $ssouserProfile .ssh\authorized_keys
$testPubKeyPath = Join-Path $Script:E2ETestDirectory sshtest_userssokey_ed25519.pub
$testPubKeyPath = Join-Path $Script:E2ETestDirectory sshtest_userssokey_ed25519.pub
Copy-Item $testPubKeyPath $authorizedKeyPath -Force -ErrorAction SilentlyContinue
$owner = New-Object System.Security.Principal.NTAccount($SSOUser)
Adjust-UserKeyFileACL -FilePath $authorizedKeyPath -Owner $owner -OwnerPerms "Read","Write"
Add-PermissionToFileACL -FilePath $authorizedKeyPath -User "NT Service\sshd" -Perm "Read"
Repair-AuthorizedKeyPermission -FilePath $authorizedKeyPath -confirm:$false
$testPriKeypath = Join-Path $Script:E2ETestDirectory sshtest_userssokey_ed25519
(Get-Content $testPriKeypath -Raw).Replace("`r`n","`n") | Set-Content $testPriKeypath -Force
Adjust-UserKeyFileACL -FilePath $testPriKeypath -OwnerPerms "Read, Write"
$con = (Get-Content $testPriKeypath | Out-String).Replace("`r`n","`n")
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"
Backup-OpenSSHTestInfo
}
@ -256,6 +267,19 @@ function Install-OpenSSHTestDependencies
{
[CmdletBinding()]
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
if(-not (Get-Command "choco" -ErrorAction SilentlyContinue))
@ -267,10 +291,66 @@ function Install-OpenSSHTestDependencies
$isModuleAvailable = Get-Module 'Pester' -ListAvailable
if (-not ($isModuleAvailable))
{
Write-Log -Message "Installing Pester..."
choco install Pester -y --force --limitoutput 2>&1 >> $Script:TestSetupLogFile
Write-Log -Message "Installing Pester..."
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
Get-UserSID
@ -296,12 +376,12 @@ function Get-UserSID
<#
.Synopsis
Cleanup-OpenSSHTestEnvironment
Clear-OpenSSHTestEnvironment
#>
function Cleanup-OpenSSHTestEnvironment
function Clear-OpenSSHTestEnvironment
{
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"]
@ -356,6 +436,13 @@ function Cleanup-OpenSSHTestEnvironment
$Global:OpenSSHTestInfo.Clear()
$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
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
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'
Pop-Location
}
@ -432,35 +520,45 @@ function Run-OpenSSHE2ETest
.Synopsis
Run openssh unit tests.
#>
function Run-OpenSSHUnitTest
function Invoke-OpenSSHUnitTest
{
# Discover all CI tests and run them.
if([string]::Isnullorempty($Script:UnitTestDirectory))
{
$Script:UnitTestDirectory = $OpenSSHTestInfo["UnitTestDirectory"]
}
Push-Location $Script:UnitTestDirectory
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
}
$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} |
Sort-Object -Unique
$testfailed = $false
if ($testFolders -ne $null)
{
$testFolders | % {
Push-Location $_
$testFolders | % {
$unittestFile = "$(Split-Path $_ -Leaf).exe"
Write-log "Running OpenSSH unit $unittestFile ..."
& .\$unittestFile >> $Script:UnitTestResultsFile
$unittestFilePath = join-path $_ $unittestFile
$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
if ($errorCode -ne 0)
{
$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
}
Pop-Location
}
}
}
Pop-Location
@ -475,7 +573,7 @@ function Backup-OpenSSHTestInfo
)
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
@ -492,7 +590,7 @@ function Backup-OpenSSHTestInfo
}
}
function Recover-OpenSSHTestInfo
function Restore-OpenSSHTestInfo
{
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
$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))
$everyone = New-Object System.Security.Principal.NTAccount("EveryOne")
$sshdAccount = New-Object System.Security.Principal.NTAccount("NT SERVICE","sshd")
<#
.Synopsis
Get-UserSID
#>
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.
$definition = @'
@ -72,7 +112,7 @@ function Repair-SshdConfigPermission
[ValidateNotNullOrEmpty()]
[string]$FilePath)
Repair-FilePermission -Owners $systemAccount,$adminsAccount -ReadAccessNeeded $sshdAccount @psBoundParameters
Repair-FilePermission -Owners $systemSid,$adminsSid -ReadAccessNeeded $sshdSid @psBoundParameters
}
<#
@ -86,18 +126,18 @@ function Repair-SshdHostKeyPermission
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
param (
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]$FilePath)
[ValidateNotNullOrEmpty()]
[string]$FilePath)
if($PSBoundParameters["FilePath"].EndsWith(".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"
Repair-FilePermission -Owners $systemAccount,$adminsAccount -ReadAccessOK $everyone -ReadAccessNeeded $sshdAccount @psBoundParameters
$PSBoundParameters["FilePath"] += ".pub"
Repair-FilePermission -Owners $systemSid,$adminsSid -ReadAccessOK $everyoneSid -ReadAccessNeeded $sshdSid @psBoundParameters
}
<#
@ -127,20 +167,14 @@ function Repair-AuthorizedKeyPermission
{
$userProfilePath = $properties.ProfileImagePath
}
$fullPath -ieq "$userProfilePath\.ssh\authorized_keys"
$userProfilePath = $userProfilePath.Replace("\", "\\")
$fullPath -match "^$userProfilePath[\\|\W|\w]+authorized_keys$"
}
if($profileItem)
{
$userSid = $profileItem.PSChildName
$account = Get-UserAccount -UserSid $userSid
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
}
$userSid = $profileItem.PSChildName
Repair-FilePermission -Owners $userSid,$adminsSid,$systemSid -AnyAccessOK $userSid -ReadAccessNeeded $sshdSid @psBoundParameters
}
else
{
@ -162,16 +196,16 @@ function Repair-UserKeyPermission
[parameter(Mandatory=$true, Position = 0)]
[ValidateNotNullOrEmpty()]
[string]$FilePath,
[System.Security.Principal.NTAccount] $User = $currentUser)
[System.Security.Principal.SecurityIdentifier] $UserSid = $currentUserSid)
if($PSBoundParameters["FilePath"].EndsWith(".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"
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 (
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]$FilePath)
Repair-FilePermission -Owners $currentUser,$adminsAccount,$systemAccount -AnyAccessOK $currentUser @psBoundParameters
[string]$FilePath,
[System.Security.Principal.SecurityIdentifier] $UserSid = $currentUserSid)
Repair-FilePermission -Owners $UserSid,$adminsSid,$systemSid -AnyAccessOK $UserSid @psBoundParameters
}
<#
@ -202,10 +237,11 @@ function Repair-FilePermission
[ValidateNotNullOrEmpty()]
[string]$FilePath,
[ValidateNotNull()]
[System.Security.Principal.NTAccount[]] $Owners = $currentUser,
[System.Security.Principal.NTAccount[]] $AnyAccessOK,
[System.Security.Principal.NTAccount[]] $ReadAccessOK,
[System.Security.Principal.NTAccount[]] $ReadAccessNeeded
[System.Security.Principal.SecurityIdentifier[]] $Owners = $currentUserSid,
[System.Security.Principal.SecurityIdentifier[]] $AnyAccessOK = $null,
[System.Security.Principal.SecurityIdentifier[]] $FullAccessNeeded = $null,
[System.Security.Principal.SecurityIdentifier[]] $ReadAccessOK = $null,
[System.Security.Principal.SecurityIdentifier[]] $ReadAccessNeeded = $null
)
if(-not (Test-Path $FilePath -PathType Leaf))
@ -235,10 +271,11 @@ function Repair-FilePermissionInternal {
[ValidateNotNullOrEmpty()]
[string]$FilePath,
[ValidateNotNull()]
[System.Security.Principal.NTAccount[]] $Owners = $currentUser,
[System.Security.Principal.NTAccount[]] $AnyAccessOK,
[System.Security.Principal.NTAccount[]] $ReadAccessOK,
[System.Security.Principal.NTAccount[]] $ReadAccessNeeded
[System.Security.Principal.SecurityIdentifier[]] $Owners = $currentUserSid,
[System.Security.Principal.SecurityIdentifier[]] $AnyAccessOK = $null,
[System.Security.Principal.SecurityIdentifier[]] $FullAccessNeeded = $null,
[System.Security.Principal.SecurityIdentifier[]] $ReadAccessOK = $null,
[System.Security.Principal.SecurityIdentifier[]] $ReadAccessNeeded = $null
)
$acl = Get-Acl $FilePath
@ -246,26 +283,19 @@ function Repair-FilePermissionInternal {
$health = $true
$paras = @{}
$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)}
if($validOwner -eq $null)
{
$caption = "Current owner: '$($acl.Owner)'. '$($Owners[0])' should own '$FilePath'."
$currentOwnerSid = Get-UserSid -User $acl.owner
if($owners -notcontains $currentOwnerSid)
{
$newOwner = Get-UserAccount -User $Owners[0]
$caption = "Current owner: '$($acl.Owner)'. '$newOwner' should own '$FilePath'."
$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))
{
{
Enable-Privilege SeRestorePrivilege | out-null
$acl.SetOwner($Owners[0])
Set-Acl -Path $FilePath -AclObject $acl -ErrorVariable e -Confirm:$false
if($e)
{
Write-Warning "Set owner failed with error: $($e[0].ToString())."
}
else
{
Write-Host "'$($Owners[0])' now owns '$FilePath'. " -ForegroundColor Green
}
$acl.SetOwner($newOwner)
Set-Acl -Path $FilePath -AclObject $acl -Confirm:$false
}
else
{
@ -279,56 +309,126 @@ function Repair-FilePermissionInternal {
$ReadAccessPerm = ([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Read.value__) -bor `
([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
$realAnyAccessOKList = $AnyAccessOK + @($systemAccount, $adminsAccount)
#if accounts in the ReadAccessNeeded already part of dacl, they are okay; need to make sure they have read access only
$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
$realAnyAccessOKList = @($systemSid, $adminsSid)
if($AnyAccessOK)
{
$realAnyAccessOKList += $AnyAccessOK
}
$realFullAccessNeeded = $FullAccessNeeded
$realReadAccessNeeded = $ReadAccessNeeded
#'APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES'- can't translate fully qualified name. it is a win32 API bug.
#'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"
if($realFullAccessNeeded -contains $everyoneSid)
{
$realFullAccessNeeded = @($everyoneSid)
$realReadAccessNeeded = $null
}
if($realReadAccessNeeded -contains $everyoneSid)
{
$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)
{
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.
continue;
}
#If everyone is in the ReadAccessOK list, any user can have read access;
# below block make sure they are granted Read access only
elseif($realReadAcessOKList -and ((($realReadAcessOKList | ? { $_.Equals($everyone)}) -ne $null) -or `
(($realReadAcessOKList | ? { $_.equals($a.IdentityReference)}) -ne $null)))
elseif(($realReadAcessOKList -contains $everyoneSid) -or ($realReadAcessOKList -contains $IdentityReferenceSid))
{
if($realReadAccessNeeded -and ($a.IdentityReference.Equals($everyone)))
if($realReadAccessNeeded -and ($IdentityReferenceSid.Equals($everyoneSid)))
{
$realReadAccessNeeded=@()
$realReadAccessNeeded= $null
}
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 `
(-not (([System.UInt32]$a.FileSystemRights.value__) -band (-bnot $ReadAccessPerm))))
{
continue;
}
}
if($a.IsInherited)
{
if($needChange)
{
Enable-Privilege SeRestorePrivilege | out-null
Set-Acl -Path $FilePath -AclObject $acl -ErrorVariable e -Confirm:$false
if($e)
{
Write-Warning "Repair permission failed with error: $($e[0].ToString())."
}
Set-Acl -Path $FilePath -AclObject $acl -Confirm:$false
}
return Remove-RuleProtection @paras
@ -340,28 +440,11 @@ function Repair-FilePermissionInternal {
if($pscmdlet.ShouldProcess($description, $prompt, $caption))
{
$needChange = $true
$idRefShortValue = ($a.IdentityReference.Value).split('\')[-1]
if ($specialIdRefs -icontains $idRefShortValue )
{
$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")
}
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
($IdentityReferenceSid, "Read", "None", "None", "Allow")
$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
{
@ -381,11 +464,7 @@ function Repair-FilePermissionInternal {
if($needChange)
{
Enable-Privilege SeRestorePrivilege | out-null
Set-Acl -Path $FilePath -AclObject $acl -ErrorVariable e -Confirm:$false
if($e)
{
Write-Warning "Repair permission failed with error: $($e[0].ToString())."
}
Set-Acl -Path $FilePath -AclObject $acl -Confirm:$false
}
return Remove-RuleProtection @paras
}
@ -395,23 +474,9 @@ function Repair-FilePermissionInternal {
if($pscmdlet.ShouldProcess($description, $prompt, "$caption."))
{
$needChange = $true
$ace = $a
$idRefShortValue = ($a.IdentityReference.Value).split('\')[-1]
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
}
}
$needChange = $true
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
($IdentityReferenceSid, $a.FileSystemRights, $a.InheritanceFlags, $a.PropagationFlags, $a.AccessControlType)
if(-not ($acl.RemoveAccessRule($ace)))
{
@ -432,20 +497,55 @@ 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
if($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."
}
else
{
$caption = "'$_' needs Read access to '$FilePath'."
$caption = "'$account' needs Read access to '$FilePath'."
$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))
{
@ -453,14 +553,14 @@ function Repair-FilePermissionInternal {
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
($_, "Read", "None", "None", "Allow")
$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
{
$health = $false
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)
{
Enable-Privilege SeRestorePrivilege | out-null
Set-Acl -Path $FilePath -AclObject $acl -ErrorVariable e -Confirm:$false
if($e)
{
Write-Warning "Repair permission failed with error: $($e[0].ToString())."
}
Set-Acl -Path $FilePath -AclObject $acl -Confirm:$false
}
if($health)
{
@ -525,41 +621,44 @@ function Remove-RuleProtection
return $false
}
}
<#
.Synopsis
Get-UserAccount
#>
function Get-UserAccount
{
[CmdletBinding(DefaultParameterSetName='Sid')]
param
( [parameter(Mandatory=$true)]
[string]$UserSid
( [parameter(Mandatory=$true, ParameterSetName="Sid")]
[ValidateNotNull()]
[System.Security.Principal.SecurityIdentifier]$UserSid,
[parameter(Mandatory=$true, ParameterSetName="WellKnownSidType")]
[ValidateNotNull()]
[System.Security.Principal.WellKnownSidType]$WellKnownSidType
)
try
{
$objSID = New-Object System.Security.Principal.SecurityIdentifier($UserSid)
$objUser = $objSID.Translate( [System.Security.Principal.NTAccount])
if($PSBoundParameters.ContainsKey("UserSid"))
{
$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
}
catch {
return $null
}
}
<#
.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 {
param(
#The privilege to adjust. This set is taken from
@ -584,4 +683,4 @@ function Enable-Privilege {
$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)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\win32_monitor_wrap.c" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="version.rc" />

View File

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

View File

@ -119,4 +119,5 @@ Subsystem sftp sftp-server.exe
# X11Forwarding no
# AllowTcpForwarding no
# 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)
{
wchar_t* name_w = NULL;
wchar_t pipe_name[PATH_MAX];
HANDLE h = INVALID_HANDLE_VALUE;
int ret = 0, r;
int ret = 0;
if (pio->handle != 0 && pio->handle != INVALID_HANDLE_VALUE) {
debug3("fileio_connect called in unexpected state, pio = %p", pio);
@ -129,16 +128,9 @@ fileio_connect(struct w32_io* pio, char* name)
errno = ENOMEM;
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 {
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);
if (h != INVALID_HANDLE_VALUE)

View File

@ -478,11 +478,23 @@ strmode(mode_t mode, char *p)
break;
}
/* The below code is commented as the group, other is not applicable on the windows.
* As of now we are keeping "*" for everything.
* TODO - figure out if there is a better option
*/
const char *permissions = "********* ";
/* group, other are not applicable on the windows */
/* usr */
if (mode & S_IREAD)
*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++)
*p++ = permissions[i];
@ -950,7 +962,8 @@ w32_strerror(int errnum)
}
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;
char ch;
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[C", VK_RIGHT, 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[2~", VK_INSERT, 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[23~", VK_F11, 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}
};
static SHORT lastX = 0;
static SHORT lastY = 0;
static wchar_t cmd_exe_path[PATH_MAX];
SHORT currentLine = 0;
consoleEvent* head = NULL;
consoleEvent* tail = NULL;
@ -939,6 +948,19 @@ cleanup:
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
start_with_pty(wchar_t *command)
{
@ -1004,9 +1026,8 @@ start_with_pty(wchar_t *command)
/* disable inheritance on pipe_in*/
GOTO_CLEANUP_ON_FALSE(SetHandleInformation(pipe_in, HANDLE_FLAG_INHERIT, 0));
/*TODO - pick this up from system32*/
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) {
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L" /c"));
@ -1178,10 +1199,9 @@ start_withno_pty(wchar_t *command)
run_under_cmd = TRUE;
/* if above failed with FILE_NOT_FOUND, try running the provided command under cmd*/
if (run_under_cmd) {
/*TODO - pick this up from system32*/
if (run_under_cmd) {
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) {
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L" /c"));
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_remove_key(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 */

View File

@ -37,7 +37,7 @@
static HANDLE ioc_port = NULL;
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 OVERLAPPED ol;
@ -168,12 +168,14 @@ agent_cleanup_connection(struct agent_connection* con)
{
debug("connection %p clean up", con);
CloseHandle(con->pipe_handle);
if (con->hProfile)
UnloadUserProfile(con->auth_token, con->hProfile);
if (con->auth_token)
CloseHandle(con->auth_token);
if (con->profile_handle)
UnloadUserProfile(con->profile_token, con->profile_handle);
if (con->profile_token)
CloseHandle(con->profile_token);
if (con->client_impersonation_token)
CloseHandle(con->client_impersonation_token);
if (con->client_process_handle)
CloseHandle(con->client_process_handle);
free(con);
CloseHandle(ioc_port);
ioc_port = NULL;
@ -251,13 +253,13 @@ get_con_client_info(struct agent_connection* con)
DWORD sshd_sid_len = 0;
PSID sshd_sid = NULL;
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;
BOOL isMember = FALSE;
if (GetNamedPipeClientProcessId(con->pipe_handle, &client_pid) == FALSE ||
(client_proc_handle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, client_pid)) == NULL ||
OpenProcessToken(client_proc_handle, TOKEN_QUERY | TOKEN_DUPLICATE, &client_primary_token) == FALSE ||
(client_process_handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_DUP_HANDLE, FALSE, client_pid)) == NULL ||
OpenProcessToken(client_process_handle, TOKEN_QUERY | TOKEN_DUPLICATE, &client_primary_token) == FALSE ||
DuplicateToken(client_primary_token, SecurityImpersonation, &client_impersonation_token) == FALSE) {
error("cannot retrieve client impersonatin token");
goto done;
@ -341,15 +343,19 @@ done:
free(ref_dom);
if (info)
free(info);
if (client_proc_handle)
CloseHandle(client_proc_handle);
if (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;
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;
}

View File

@ -4,17 +4,18 @@
#include "log.h"
#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_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
struct agent_connection {
OVERLAPPED ol;
HANDLE pipe_handle;
HANDLE client_impersonation_token;
HANDLE client_impersonation_token;
HANDLE client_process_handle;
struct {
DWORD num_bytes;
DWORD transferred;
@ -36,8 +37,9 @@ struct agent_connection {
SYSTEM, /* client is running as System */
SERVICE, /* client is running as LS or NS */
} client_type;
HANDLE auth_token;
HANDLE hProfile;
/* user profile related members */
HANDLE profile_token;
HANDLE profile_handle;
};
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;
}
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
kexgex_server(struct ssh * sh) {
return -1;

View File

@ -39,6 +39,7 @@
#include "agent-request.h"
#include "key.h"
#include "inc\utf.h"
#include "..\priv-agent.h"
#pragma warning(push, 3)
@ -83,9 +84,11 @@ done:
}
void
LoadProfile(struct agent_connection* con, wchar_t* user, wchar_t* domain) {
static HANDLE
LoadProfile(HANDLE user_token, wchar_t* user, wchar_t* domain) {
PROFILEINFOW profileInfo;
HANDLE ret = NULL;
profileInfo.dwFlags = PI_NOUI;
profileInfo.lpProfilePath = NULL;
profileInfo.lpUserName = user;
@ -96,12 +99,16 @@ LoadProfile(struct agent_connection* con, wchar_t* user, wchar_t* domain) {
profileInfo.dwSize = sizeof(profileInfo);
EnablePrivilege("SeBackupPrivilege", 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());
goto done;
}
else
con->hProfile = profileInfo.hProfile;
ret = profileInfo.hProfile;
done:
EnablePrivilege("SeBackupPrivilege", 0);
EnablePrivilege("SeRestorePrivilege", 0);
return ret;
}
#define MAX_USER_LEN 64
@ -238,73 +245,13 @@ done:
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 r = -1;
char *key_blob, *user, *sig, *blob;
size_t key_blob_len, user_len, sig_len, blob_len;
struct sshkey *key = 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;
@ -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)
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;
done:
/* TODO Fix this hacky protocol*/
@ -373,7 +312,60 @@ done:
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;
size_t opn_len;
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 */
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;
}
if (memcmp(opn, PUBKEY_AUTH_REQUEST, opn_len) == 0)
return process_pubkeyauth_request(request, response, con);
else if (memcmp(opn, PASSWD_AUTH_REQUEST, opn_len) == 0)
return process_passwordauth_request(request, response, con);
else if (memcmp(opn, LOAD_USER_PROFILE_REQUEST, opn_len) == 0)
return process_loadprofile_request(request, response, con);
else {
debug("unknown auth request: %s", opn);
return -1;

View File

@ -30,6 +30,7 @@
*/
#include "agent.h"
#include "agent-request.h"
#include "..\priv-agent.h"
#pragma warning(push, 3)
@ -168,8 +169,8 @@ process_request(struct agent_connection* con)
case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
r = process_remove_all(request, response, con);
break;
case SSH_AGENT_AUTHENTICATE:
r = process_authagent_request(request, response, con);
case SSH_PRIV_AGENT_MSG_ID:
r = process_privagent_request(request, response, con);
break;
default:
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)
_putenv("SSH_AUTH_SOCK=ssh-agent");
_putenv("SSH_AUTH_SOCK=\\\\.\\pipe\\openssh-ssh-agent");
w32posix_initialize();

View File

@ -108,9 +108,6 @@ int sshd_main(int argc, wchar_t **wargv) {
argv[i] = utf16_to_utf8(wargv[i]);
}
if (getenv("SSH_AUTH_SOCK") == NULL)
_putenv("SSH_AUTH_SOCK=ssh-agent");
w32posix_initialize();
if (getenv("SSHD_REMSOC"))
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_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_ */

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
$tI = 0
$suite = "authorized_keys_fileperm"
@ -6,7 +8,7 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
BeforeAll {
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"
@ -22,17 +24,31 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
$ssouser = $OpenSSHTestInfo["SSOUser"]
$PwdUser = $OpenSSHTestInfo["PasswdUser"]
$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++ }
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" {
BeforeAll {
$systemAccount = New-Object System.Security.Principal.NTAccount("NT AUTHORITY", "SYSTEM")
$adminAccount = New-Object System.Security.Principal.NTAccount("BUILTIN","Administrators")
$objUser = New-Object System.Security.Principal.NTAccount($ssouser)
$currentUser = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME))
$systemSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::LocalSystemSid)
$adminsSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid)
$currentUserSid = Get-UserSID -User "$($env:USERDOMAIN)\$($env:USERNAME)"
$objUserSid = Get-UserSID -User $ssouser
$ssouserSSHProfilePath = Join-Path $ssouserProfile .testssh
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
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-PasswordSetting -Pass "WrongPass"
$tI=1
}
AfterAll {
Repair-AuthorizedKeyPermission -Filepath $authorizedkeyPath -confirm:$false
if(Test-Path $authorizedkeyPath) {
Adjust-UserKeyFileACL -Filepath $authorizedkeyPath -Owner $objUser -OwnerPerms "Read, Write"
Remove-Item $authorizedkeyPath -Force -ErrorAction Ignore
Repair-AuthorizedKeyPermission -Filepath $authorizedkeyPath -confirm:$false
Remove-Item $authorizedkeyPath -Force -ErrorAction SilentlyContinue
}
if(Test-Path $ssouserSSHProfilePath) {
Remove-Item $ssouserSSHProfilePath -Force -ErrorAction Ignore -Recurse
Remove-Item $ssouserSSHProfilePath -Force -ErrorAction SilentlyContinue -Recurse
}
Remove-PasswordSetting
$tC++
@ -66,11 +83,12 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
BeforeEach {
$filePath = Join-Path $testDir "$tC.$tI.$fileName"
$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)" {
#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
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"
#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)" {
#setup to have system as owner and grant it full control
Set-FileOwnerAndACL -Filepath $authorizedkeyPath -Owner $systemAccount -OwnerPerms "FullControl"
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $adminAccount -Perms "FullControl"
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $objUser -Perms "Read, Write"
Repair-FilePermission -Filepath $authorizedkeyPath -Owner $systemSid -FullAccessNeeded $adminsSid,$systemSid,$objUserSid -confirm:$false
#Run
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"
#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)" {
#setup to have admin group as owner and grant it full control
Set-FileOwnerAndACL -Filepath $authorizedkeyPath -Owner $adminAccount -OwnerPerms "FullControl"
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $systemAccount -Perms "FullControl"
#setup to have admin group as owner and grant it full control
Repair-FilePermission -Filepath $authorizedkeyPath -Owner $adminsSid -FullAccessNeeded $adminsSid,$systemSid -confirm:$false
#Run
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"
#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)" {
#setup to have admin group as owner and grant it full control
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"
Repair-FilePermission -Filepath $authorizedkeyPath -Owner $adminsSid -FullAccessNeeded $adminsSid,$systemSid,$objUserSid -confirm:$false
#Run
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"
#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)" {
#setup to have current user (admin user) as owner and grant it full control
Set-FileOwnerAndACL -Filepath $authorizedkeyPath -Owner $currentUser -OwnerPerms "Read","Write"
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $systemAccount -Perms "FullControl"
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $adminAccount -Perms "FullControl"
Repair-FilePermission -Filepath $authorizedkeyPath -Owner $currentUserSid -FullAccessNeeded $adminsSid,$systemSid -confirm:$false
#Run
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
#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)" {
#setup to have current user as owner and grant it full control
Set-FileOwnerAndACL -Filepath $authorizedkeyPath -Owner $objUser -OwnerPerms "Read","Write"
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $systemAccount -Perms "FullControl"
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $adminAccount -Perms "FullControl"
#setup to have current user as owner and grant it full control
Repair-FilePermission -Filepath $authorizedkeyPath -Owner $objUserSid -FullAccessNeeded $adminsSid,$systemSid,$objUserSid -confirm:$false
#add $PwdUser to access the file authorized_keys
$objPwdUser = New-Object System.Security.Principal.NTAccount($PwdUser)
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $objPwdUser -Perm "Read"
$objPwdUserSid = Get-UserSid -User $PwdUser
Set-FilePermission -FilePath $authorizedkeyPath -User $objPwdUserSid -Perm "Read"
#Run
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
#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)" {
#setup to have PwdUser as owner and grant it full control
$objPwdUser = New-Object System.Security.Principal.NTAccount($PwdUser)
Set-FileOwnerAndACL -Filepath $authorizedkeyPath -owner $objPwdUser -OwnerPerms "Read","Write"
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $systemAccount -Perms "FullControl"
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $adminAccount -Perms "FullControl"
#setup to have PwdUser as owner and grant it full control
$objPwdUserSid = Get-UserSid -User $PwdUser
Repair-FilePermission -Filepath $authorizedkeyPath -Owner $objPwdUserSid -FullAccessNeeded $adminsSid,$systemSid,$objPwdUser -confirm:$false
#Run
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
#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
Set-FileOwnerAndACL -Filepath $authorizedkeyPath -Owner $objUser -OwnerPerms "Read","Write"
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $systemAccount -Perms "FullControl"
Repair-FilePermission -Filepath $authorizedkeyPath -Owner $objUserSid -FullAccessNeeded $systemSid,$objUserSid -confirm:$false
Set-FilePermission -Filepath $authorizedkeyPath -UserSid $adminsSid -Action Delete
#Run
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
#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
$tI = 0
$suite = "authorized_keys_fileperm"
@ -6,7 +7,7 @@ Describe "Tests for ssh config" -Tags "CI" {
BeforeAll {
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"]))
@ -27,38 +28,39 @@ Describe "Tests for ssh config" -Tags "CI" {
# for the first time, delete the existing log files.
if ($OpenSSHTestInfo['DebugMode'])
{
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction ignore
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction ignore
Remove-Item -Path (Join-Path $testDir "*log*.log") -Force -ErrorAction ignore
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction SilentlyContinue
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 {
if( $OpenSSHTestInfo["DebugMode"])
{
Copy-Item "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" "$testDir\agentlog$tC.$tI.log" -Force -ErrorAction ignore
Copy-Item "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" "$testDir\sshdlog$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 SilentlyContinue
#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\sshd.log" -Force -ErrorAction ignore
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction SilentlyContinue
}
$tI++
}
Context "$tC-User SSHConfig--ReadConfig" {
BeforeAll {
$systemAccount = New-Object System.Security.Principal.NTAccount("NT AUTHORITY", "SYSTEM")
$adminAccount = New-Object System.Security.Principal.NTAccount("BUILTIN","Administrators")
$objUser = New-Object System.Security.Principal.NTAccount($ssouser)
$currentUser = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME))
$systemSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::LocalSystemSid)
$adminsSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid)
$currentUserSid = Get-UserSID -User "$($env:USERDOMAIN)\$($env:USERNAME)"
$objUserSid = Get-UserSID -User $ssouser
$userConfigFile = Join-Path $home ".ssh\config"
if( -not (Test-path $userConfigFile) ) {
Copy-item "$PSScriptRoot\testdata\ssh_config" $userConfigFile -force
}
Enable-Privilege SeRestorePrivilege | out-null
$oldACL = Get-ACL $userConfigFile
$tI=1
}
@ -67,8 +69,8 @@ Describe "Tests for ssh config" -Tags "CI" {
$logPath = Join-Path $testDir "$tC.$tI.$logName"
}
AfterEach {
Set-Acl -Path $userConfigFile -AclObject $oldACL
AfterEach {
Set-Acl -Path $userConfigFile -AclObject $oldACL -confirm:$false
}
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)" {
#setup
Set-FileOwnerAndACL -Filepath $userConfigFile -Owner $currentUser -OwnerPerms "Read","Write"
Add-PermissionToFileACL -FilePath $userConfigFile -User $systemAccount -Perms "FullControl"
Add-PermissionToFileACL -FilePath $userConfigFile -User $adminAccount -Perms "FullControl"
Repair-FilePermission -Filepath $userConfigFile -Owners $currentUserSid -FullAccessNeeded $adminsSid,$systemSid,$currentUserSid -confirm:$false
#Run
$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)" {
#setup
Set-FileOwnerAndACL -Filepath $userConfigFile -Owner $systemAccount -OwnerPerms "FullControl"
Add-PermissionToFileACL -FilePath $userConfigFile -User $adminAccount -Perms "FullControl"
Repair-FilePermission -Filepath $userConfigFile -Owners $systemSid -FullAccessNeeded $adminsSid,$systemSid -confirm:$false
#Run
$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)" {
#setup
Set-FileOwnerAndACL -Filepath $userConfigFile -Owner $adminAccount -OwnerPerms "FullControl"
Add-PermissionToFileACL -FilePath $userConfigFile -User $systemAccount -Perms "FullControl"
Repair-FilePermission -Filepath $userConfigFile -Owners $adminsSid -FullAccessNeeded $adminsSid,$systemSid -confirm:$false
Set-FilePermission -Filepath $userConfigFile -UserSid $currentUserSid -Action Delete
#Run
$o = ssh test_target echo 1234
@ -108,10 +107,8 @@ Describe "Tests for ssh config" -Tags "CI" {
It "$tC.$tI-User SSHConfig-ReadConfig positive (admin is the owner and current user has explict ACE)" {
#setup
Set-FileOwnerAndACL -Filepath $userConfigFile -Owner $adminAccount -OwnerPerms "FullControl"
Add-PermissionToFileACL -FilePath $userConfigFile -User $systemAccount -Perms "FullControl"
Add-PermissionToFileACL -FilePath $userConfigFile -User $currentUser -Perms "Read, Write"
Repair-FilePermission -Filepath $userConfigFile -Owners $adminsSid -FullAccessNeeded $adminsSid,$systemSid,$currentUserSid -confirm:$false
#Run
$o = ssh test_target echo 1234
$o | Should Be "1234"
@ -119,9 +116,7 @@ Describe "Tests for ssh config" -Tags "CI" {
It "$tC.$tI-User SSHConfig-ReadConfig negative (wrong owner)" {
#setup
Set-FileOwnerAndACL -Filepath $userConfigFile -Owner $ssouser -OwnerPerms "Read","Write"
Add-PermissionToFileACL -FilePath $userConfigFile -User $systemAccount -Perms "FullControl"
Add-PermissionToFileACL -FilePath $userConfigFile -User $adminAccount -Perms "FullControl"
Repair-FilePermission -Filepath $userConfigFile -Owners $objUserSid -FullAccessNeeded $adminsSid,$systemSid,$objUserSid -confirm:$false
#Run
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)" {
#setup
Set-FileOwnerAndACL -Filepath $userConfigFile -Owner $currentUser -OwnerPerms "Read","Write"
Add-PermissionToFileACL -FilePath $userConfigFile -User $systemAccount -Perms "FullControl"
Add-PermissionToFileACL -FilePath $userConfigFile -User $adminAccount -Perms "FullControl"
Add-PermissionToFileACL -FilePath $userConfigFile -User $objUser -Perms "Read"
Repair-FilePermission -Filepath $userConfigFile -Owners $currentUserSid -FullAccessNeeded $adminsSid,$systemSid,$currentUserSid -ReadAccessNeeded $objUserSid -confirm:$false
#Run
cmd /c "ssh test_target echo 1234 2> $logPath"

View File

@ -1,8 +1,13 @@
Enum PlatformType {
Windows
Linux
OSX
}
Import-Module OpenSSHUtils -Force
Add-Type -TypeDefinition @"
public enum PlatformType
{
Windows,
Linux,
OSX
}
"@
function Get-Platform {
# Use the .NET Core APIs to determine the current platform; if a runtime
@ -31,157 +36,59 @@ function Get-Platform {
}
}
<#
.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(
[parameter(Mandatory=$true)]
[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
function Set-FilePermission
{
param(
[parameter(Mandatory=$true)]
[string]$FilePath,
[System.Security.Principal.NTAccount] $User,
[parameter(Mandatory=$true)]
[System.Security.Principal.SecurityIdentifier] $UserSid,
[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
if($Perms)
$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($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 | % {
$userACE = New-Object System.Security.AccessControl.FileSystemAccessRule `
($User, $_, "None", "None", $AccessType)
($UserSid, $_, "None", "None", $AccessType)
$myACL.AddAccessRule($userACE)
}
}
Set-Acl -Path $FilePath -AclObject $myACL
}
Enable-Privilege SeRestorePrivilege | out-null
Set-Acl -Path $FilePath -AclObject $myACL -confirm:$false
}
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
$tI = 0
$suite = "hostkey_fileperm"
@ -6,7 +7,7 @@ Describe "Tests for host keys file permission" -Tags "CI" {
BeforeAll {
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"
@ -19,30 +20,57 @@ Describe "Tests for host keys file permission" -Tags "CI" {
$port = 47003
$ssouser = $OpenSSHTestInfo["SSOUser"]
$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++ }
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" {
BeforeAll {
$systemAccount = New-Object System.Security.Principal.NTAccount("NT AUTHORITY", "SYSTEM")
$adminAccount = New-Object System.Security.Principal.NTAccount("BUILTIN","Administrators")
$objUser = New-Object System.Security.Principal.NTAccount($ssouser)
$currentUser = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME))
$everyone = New-Object System.Security.Principal.NTAccount("EveryOne")
$systemSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::LocalSystemSid)
$adminsSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid)
$currentUserSid = Get-UserSID -User "$($env:USERDOMAIN)\$($env:USERNAME)"
$objUserSid = Get-UserSID -User $ssouser
$everyoneSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::WorldSid)
$hostKeyFilePath = join-path $testDir hostkeyFilePermTest_ed25519_key
if(Test-path $hostKeyFilePath -PathType Leaf) {
Set-FileOwnerAndACL -filepath $hostKeyFilePath
Repair-SshdHostKeyPermission -filepath $hostKeyFilePath -confirm:$false
}
if(Test-path "$hostKeyFilePath.pub" -PathType Leaf){
Set-FileOwnerAndACL -filepath "$hostKeyFilePath.pub"
}
Remove-Item -path "$hostKeyFilePath*" -Force -ErrorAction Ignore
Remove-Item -path "$hostKeyFilePath*" -Force -ErrorAction SilentlyContinue
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
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 {
@ -50,76 +78,59 @@ Describe "Tests for host keys file permission" -Tags "CI" {
}
AfterAll {
if(Test-path $hostKeyFilePath -PathType Leaf){
Adjust-UserKeyFileACL -Filepath $hostKeyFilePath -Owner $systemAccount
}
if(Test-path "$hostKeyFilePath.pub" -PathType Leaf){
Adjust-UserKeyFileACL -Filepath "$hostKeyFilePath.pub" -Owner $systemAccount
if(Test-path $hostKeyFilePath -PathType Leaf) {
Repair-SshdHostKeyPermission -filepath $hostKeyFilePath -confirm:$false
}
$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)" {
Set-FileOwnerAndACL -Filepath $hostKeyFilePath -Owner $adminAccount -OwnerPerms "FullControl"
Add-PermissionToFileACL -FilePath $hostKeyFilePath -User $systemAccount -Perms "FullControl"
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)" {
Repair-FilePermission -Filepath $hostKeyFilePath -Owners $adminsSid -FullAccessNeeded $adminsSid,$systemSid -confirm:$false
Repair-FilePermission -Filepath "$hostKeyFilePath.pub" -Owners $adminsSid -FullAccessNeeded $adminsSid,$systemSid -confirm:$false
#Run
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-h $hostKeyFilePath", "-E $logPath") -NoNewWindow
WaitForValidation -LogPath $logPath -Length 600
#validate file content does not contain unprotected info.
$logPath | Should Not Contain "UNPROTECTED PRIVATE KEY FILE!"
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"
}
It "$tC.$tI-Host keys-positive (both public and private keys are owned by admin groups and pwd user has explicit ACE)" {
Repair-FilePermission -Filepath $hostKeyFilePath -Owners $adminsSid -FullAccessNeeded $adminsSid,$systemSid -ReadAccessNeeded $currentUserSid -confirm:$false
Repair-FilePermission -Filepath "$hostKeyFilePath.pub" -Owners $adminsSid -FullAccessNeeded $adminsSid,$systemSid -ReadAccessNeeded $everyOneSid -confirm:$false
#Run
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.
$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)" {
Set-FileOwnerAndACL -Filepath $hostKeyFilePath -Owner $adminAccount -OwnerPerms "FullControl"
Add-PermissionToFileACL -FilePath $hostKeyFilePath -User $systemAccount -Perms "FullControl"
Add-PermissionToFileACL -FilePath "$hostKeyFilePath.pub" -User $currentUser -Perms "Read"
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 {
Repair-FilePermission -Filepath $hostKeyFilePath -Owners $systemSid -FullAccessNeeded $systemSid,$adminsSid -ReadAccessNeeded $currentUserSid -confirm:$false
Set-FilePermission -Filepath $hostKeyFilePath -UserSid $adminsSid -Action Delete
Repair-FilePermission -Filepath "$hostKeyFilePath.pub" -Owners $systemSid -FullAccessNeeded $systemSid,$adminsSid -ReadAccessNeeded $currentUserSid -confirm:$false
Set-FilePermission -Filepath "$hostKeyFilePath.pub" -UserSid $adminsSid -Action Delete
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
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 } }
#validate file content does not contain unprotected info.
$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)" {
Set-FileOwnerAndACL -Filepath $hostKeyFilePath -Owner $systemAccount -OwnerPerms "FullControl"
Add-PermissionToFileACL -FilePath $hostKeyFilePath -User $adminAccount -Perms "Read"
Set-FileOwnerAndACL -Filepath "$hostKeyFilePath.pub" -Owner $systemAccount -OwnerPerms "FullControl"
Add-PermissionToFileACL -FilePath "$hostKeyFilePath.pub" -User $adminAccount -Perms "Read"
#Run
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.
$logPath | Should Not Contain "UNPROTECTED PRIVATE KEY FILE!"
}
It "$tC.$tI-Host keys-negative (other account can access private key file)" {
Set-FileOwnerAndACL -Filepath $hostKeyFilePath -Owner $systemAccount -OwnerPerms "FullControl"
Add-PermissionToFileACL -FilePath $hostKeyFilePath -User $adminAccount -Perms "FullControl"
Add-PermissionToFileACL -FilePath $hostKeyFilePath -User $objUser -Perms "Read"
Repair-FilePermission -Filepath $hostKeyFilePath -Owners $adminsSid -FullAccessNeeded $systemSid,$adminsSid -ReadAccessNeeded $objUserSid -confirm:$false
Repair-FilePermission -Filepath "$hostKeyFilePath.pub" -Owners $adminsSid -FullAccessNeeded $systemSid,$adminsSid -ReadAccessNeeded $everyOneSid -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
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.
$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)" {
#setup to have ssouser as owner and grant it full control
Set-FileOwnerAndACL -FilePath $hostKeyFilePath -Owner $objUser -OwnerPerms "Read","Write"
Add-PermissionToFileACL -FilePath $hostKeyFilePath -User $adminAccount -Perms "FullControl"
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"
Repair-FilePermission -Filepath $hostKeyFilePath -Owners $objUserSid -FullAccessNeeded $systemSid,$adminsSid,$objUserSid -confirm:$false
Repair-FilePermission -Filepath "$hostKeyFilePath.pub" -Owners $adminsSid -FullAccessNeeded $systemSid,$adminsSid -ReadAccessNeeded $everyOneSid -confirm:$false
#Run
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.
$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
Set-FileOwnerAndACL -FilePath $hostKeyFilePath -Owner $systemAccount -OwnerPerms "FullControl"
Add-PermissionToFileACL -FilePath $hostKeyFilePath -User $adminAccount -Perms "Read"
Set-FileOwnerAndACL -Filepath "$hostKeyFilePath.pub" -Owner $systemAccount -OwnerPerms "FullControl"
Repair-FilePermission -Filepath $hostKeyFilePath -Owners $systemSid -FullAccessNeeded $systemSid,$adminsSid -confirm:$false
Repair-FilePermission -Filepath "$hostKeyFilePath.pub" -Owners $systemSid -FullAccessNeeded $systemSid -confirm:$false
Set-FilePermission -Filepath "$hostKeyFilePath.pub" -UserSid $adminsSid -Action Delete
#Run
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.
$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
$tI = 0
$suite = "keyutils"
@ -7,7 +8,7 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
BeforeAll {
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"
@ -20,48 +21,58 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
$keytypes = @("rsa","dsa","ecdsa","ed25519")
$ssouser = $OpenSSHTestInfo["SSOUser"]
$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))
$everyone = New-Object System.Security.Principal.NTAccount("EveryOne")
$objUser = New-Object System.Security.Principal.NTAccount($ssouser)
$systemSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::LocalSystemSid)
$adminsSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid)
$currentUserSid = Get-UserSID -User "$($env:USERDOMAIN)\$($env:USERNAME)"
$objUserSid = Get-UserSID -User $ssouser
$everyoneSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::WorldSid)
#only validate owner and ACEs of the file
function ValidateKeyFile {
param([string]$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
$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")) {
$myACL.Access.Count | Should Be 4
$identities = @($systemAccount.Value, $adminsAccount.Value, $currentUser.Value, $everyone.Value)
$identities = @($systemSid, $adminsSid, $currentUserSid, $everyoneSid)
}
else {
$myACL.Access.Count | Should Be 3
$identities = @($systemAccount.Value, $adminsAccount.Value, $currentUser.Value)
$identities = @($systemSid, $adminsSid, $currentUserSid)
}
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;
}
$currentUser.Value
$currentUserSid
{
$a.FileSystemRights | Should Be "Write, Read, Synchronize"
([System.UInt32]$a.FileSystemRights.value__) | Should Be $ReadWriteAccessPerm
break;
}
$everyone.Value
$everyoneSid
{
$a.FileSystemRights | Should Be "Read, Synchronize"
([System.UInt32]$a.FileSystemRights.value__) | Should Be $ReadAccessPerm
break;
}
}
@ -106,7 +117,7 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
foreach($type in $keytypes)
{
$keyPath = Join-Path $testDir "id_$type"
remove-item $keyPath -ErrorAction ignore
remove-item $keyPath -ErrorAction SilentlyContinue
ssh-keygen -t $type -P $keypassphrase -f $keyPath
ValidateKeyFile -FilePath $keyPath
ValidateKeyFile -FilePath "$keyPath.pub"
@ -116,7 +127,17 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
# This uses keys generated in above context
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++}
# 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"
ssh-agent
WaitForStatus -ServiceName ssh-agent -Status "Running"
(Get-Service ssh-agent).Status | Should Be "Running"
Stop-Service ssh-agent -Force
WaitForStatus -ServiceName ssh-agent -Status "Stopped"
(Get-Service ssh-agent).Status | Should Be "Stopped"
(Get-Service sshd).Status | Should Be "Stopped"
# this should automatically start both the services
Start-Service sshd
WaitForStatus -ServiceName sshd -Status "Running"
(Get-Service ssh-agent).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"
$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
@ -188,7 +214,7 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
{
$keyPath = Join-Path $testDir "id_$type"
$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 {
$keyFileName = "sshadd_userPermTestkey_ed25519"
$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
#set up SSH_ASKPASS
Add-PasswordSetting -Pass $keypassphrase
@ -209,7 +235,7 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
}
AfterEach {
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
}
}
@ -220,30 +246,30 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
}
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
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $currentUser -OwnerPerms "FullControl"
#setup to have current user as owner and grant it full control
Repair-FilePermission -FilePath $keyFilePath -Owner $currentUserSid -FullAccessNeeded $currentUserSid,$systemSid,$adminsSid -confirm:$false
# for ssh-add to consume SSh_ASKPASS, stdin should not be TTY
cmd /c "ssh-add $keyFilePath < $nullFile 2> nul"
$LASTEXITCODE | Should Be 0
$allkeys = ssh-add -L
$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
cmd /c "ssh-add -d $keyFilePath 2> nul "
}
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
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $adminsAccount -OwnerPerms "FullControl"
#setup to have local admin group as owner and grant it full control
Repair-FilePermission -FilePath $keyFilePath -Owner $adminsSid -FullAccessNeeded $adminsSid,$systemSid -confirm:$false
# for ssh-add to consume SSh_ASKPASS, stdin should not be TTY
cmd /c "ssh-add $keyFilePath < $nullFile 2> nul "
$LASTEXITCODE | Should Be 0
$allkeys = ssh-add -L
$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
cmd /c "ssh-add -d $keyFilePath 2> nul "
@ -251,62 +277,56 @@ 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)" {
#setup to have local admin group as owner and grant it full control
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $adminsAccount -OwnerPerms "FullControl"
Add-PermissionToFileACL -FilePath $keyFilePath -User $currentUser -Perm "Read, Write"
Repair-FilePermission -FilePath $keyFilePath -Owners $adminsSid -FullAccessNeeded $currentUserSid,$adminsSid,$systemSid -confirm:$false
# for ssh-add to consume SSh_ASKPASS, stdin should not be TTY
cmd /c "ssh-add $keyFilePath < $nullFile 2> nul "
$LASTEXITCODE | Should Be 0
$allkeys = ssh-add -L
$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
cmd /c "ssh-add -d $keyFilePath 2> nul "
}
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
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $systemAccount -OwnerPerms "FullControl"
Add-PermissionToFileACL -FilePath $keyFilePath -User $adminsAccount -Perm "FullControl"
#setup to have local admin group as owner and grant it full control
Repair-FilePermission -FilePath $keyFilePath -Owners $systemSid -FullAccessNeeded $systemSid,$adminsSid -confirm:$false
# for ssh-add to consume SSh_ASKPASS, stdin should not be TTY
cmd /c "ssh-add $keyFilePath < $nullFile 2> nul "
$LASTEXITCODE | Should Be 0
$allkeys = ssh-add -L
$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
cmd /c "ssh-add -d $keyFilePath 2> nul "
}
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
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $currentUser -OwnerPerms "FullControl"
#add ssouser to access the private key
Add-PermissionToFileACL -FilePath $keyFilePath -User $objUser -Perm "Read"
#setup to have current user as owner and grant it full control
Repair-FilePermission -FilePath $keyFilePath -Owners $currentUserSid -FullAccessNeeded $currentUserSid,$adminsSid, $systemSid -ReadAccessNeeded $objUserSid -confirm:$false
cmd /c "ssh-add $keyFilePath < $nullFile 2> nul "
$LASTEXITCODE | Should Not Be 0
$allkeys = ssh-add -L
$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)" {
#setup to have ssouser as owner and grant it full control
Set-FileOwnerAndACL -FilePath $keyFilePath -owner $objUser -OwnerPerms "Read, Write"
Add-PermissionToFileACL -FilePath $keyFilePath -User $adminsAccount -Perm "FullControl"
Repair-FilePermission -FilePath $keyFilePath -Owners $objUserSid -FullAccessNeeded $objUserSid,$adminsSid, $systemSid -confirm:$false
cmd /c "ssh-add $keyFilePath < $nullFile 2> nul "
$LASTEXITCODE | Should Not Be 0
$allkeys = ssh-add -L
$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 {
$tI=1
$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 {
$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
$suite = "log_fileperm"
@ -15,38 +17,52 @@ Describe "Tests for log file permission" -Tags "CI" {
$null = New-Item $testDir -ItemType directory -Force -ErrorAction SilentlyContinue
}
$port = 47003
$logName = "log.txt"
$logName = "log.txt"
$systemSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::LocalSystemSid)
$adminsSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid)
$currentUserSid = Get-UserSID -User "$($env:USERDOMAIN)\$($env:USERNAME)"
$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))
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
function ValiLogFilePerm {
function ValidateLogFilePerm {
param([string]$FilePath)
$myACL = Get-ACL $FilePath
$myACL.Owner.Equals($currentUser.Value) | Should Be $true
$myACL.Access | Should Not Be $null
$currentOwnerSid = Get-UserSid -User $myACL.Owner
$currentOwnerSid.Equals($currentUserSid) | Should Be $true
$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
$identities = @($systemAccount.Value, $adminsAccount.Value, $currentUser.Value)
$identities = @($systemSid, $adminsSid, $currentUserSid)
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;
}
$currentUser.Value
$currentUserSid
{
$a.FileSystemRights | Should Be "Write, Read, Synchronize"
([System.UInt32]$a.FileSystemRights.value__) | Should Be $ReadWriteAccessPerm
break;
}
}
@ -63,11 +79,17 @@ Describe "Tests for log file permission" -Tags "CI" {
$logPath = Join-Path $testDir "$tC.$tI.$logName"
}
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" {
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
}
@ -79,8 +101,8 @@ Describe "Tests for log file permission" -Tags "CI" {
#Run
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-E $logPath") -NoNewWindow
Start-sleep 1;
ValiLogFilePerm -FilePath $logPath
Get-Process -Name sshd | % { if($_.SI -ne 0) { Stop-Process $_; Start-sleep 1 } }
ValidateLogFilePerm -FilePath $logPath
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
$suite = "portfwd"
Describe "E2E scenarios for port forwarding" -Tags "CI" {
BeforeAll {
if($OpenSSHTestInfo -eq $null)
{
Throw "`$OpenSSHTestInfo is null. Please run Set-OpenSSHTestEnvironment to set test environments."
}
$testDir = Join-Path $OpenSSHTestInfo["TestDataPath"] $suite
if(-not (Test-Path $testDir))
{
$null = New-Item $testDir -ItemType directory -Force -ErrorAction SilentlyContinue
}
$platform = Get-Platform
$skip = ($platform -eq [PlatformType]::Windows) -and ($PSVersionTable.PSVersion.Major -le 2)
}
BeforeEach {
@ -23,12 +31,12 @@ Describe "E2E scenarios for port forwarding" -Tags "CI" {
AfterAll{$tC++}
#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
$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
$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
#todo: -F, -l and -P should be tested over the network
Describe "Tests for scp command" -Tags "CI" {
BeforeAll {
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"
@ -19,8 +20,8 @@ Describe "Tests for scp command" -Tags "CI" {
$NestedSourceFilePath = Join-Path $NestedSourceDir $fileName2
$null = New-Item $SourceDir -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 $NestedSourceFilePath -force -ErrorAction SilentlyContinue
$null = New-item -path $SourceFilePath -ItemType file -force -ErrorAction SilentlyContinue
$null = New-item -path $NestedSourceFilePath -ItemType file -force -ErrorAction SilentlyContinue
"Test content111" | Set-content -Path $SourceFilePath
"Test content in nested dir" | Set-content -Path $NestedSourceFilePath
$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.
if ($OpenSSHTestInfo['DebugMode'])
{
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction ignore
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction ignore
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction SilentlyContinue
}
function CheckTarget {
@ -110,8 +111,8 @@ Describe "Tests for scp command" -Tags "CI" {
$script:logNum++
# 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\sshd.log" -Force -ErrorAction ignore
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction SilentlyContinue
}
return $false
@ -144,6 +145,7 @@ Describe "Tests for scp command" -Tags "CI" {
AfterEach {
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 | 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 | 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" {
BeforeAll {
$serverDirectory = $null
$clientDirectory = $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"
@ -29,8 +32,11 @@ Describe "SFTP Test Cases" -Tags "CI" {
$ssouser = $OpenSSHTestInfo["SSOUser"]
$script:testId = 1
Remove-item (Join-Path $rootDirectory "*.$outputFileName") -Force -ErrorAction Ignore
Remove-item (Join-Path $rootDirectory "*.$batchFileName") -Force -ErrorAction Ignore
Remove-item (Join-Path $rootDirectory "*.$outputFileName") -Force -ErrorAction SilentlyContinue
Remove-item (Join-Path $rootDirectory "*.$batchFileName") -Force -ErrorAction SilentlyContinue
$platform = Get-Platform
$skip = ($platform -eq [PlatformType]::Windows) -and ($PSVersionTable.PSVersion.Major -le 2)
$testData1 = @(
@{
@ -162,9 +168,9 @@ Describe "SFTP Test Cases" -Tags "CI" {
# for the first time, delete the existing log files.
if ($OpenSSHTestInfo['DebugMode'])
{
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction ignore
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction ignore
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sftp-server.log" -Force -ErrorAction ignore
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction SilentlyContinue
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sftp-server.log" -Force -ErrorAction SilentlyContinue
}
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
# 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\sshd.log" -Force -ErrorAction ignore
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sftp-server.log" -Force -ErrorAction ignore
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction SilentlyContinue
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sftp-server.log" -Force -ErrorAction SilentlyContinue
}
}
}
AfterAll {
Get-ChildItem $serverDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
Get-ChildItem $clientDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
if($serverDirectory) { Get-ChildItem $serverDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue }
if($clientDirectory) { Get-ChildItem $clientDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue }
}
BeforeEach {
Get-ChildItem $serverDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
Get-ChildItem $clientDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
if($serverDirectory) { Get-ChildItem $serverDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue }
if($clientDirectory) { Get-ChildItem $clientDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue }
$outputFilePath = Join-Path $rootDirectory "$($script:testId).$outputFileName"
$batchFilePath = Join-Path $rootDirectory "$($script:testId).$batchFileName"
}
@ -212,6 +218,7 @@ Describe "SFTP Test Cases" -Tags "CI" {
It '<Title>' -TestCases:$testData2 {
param([string]$Title, $Options, $tmpFileName1, $tmpFilePath1, $tmpFileName2, $tmpFilePath2, $tmpDirectoryName1, $tmpDirectoryPath1, $tmpDirectoryName2, $tmpDirectoryPath2)
if($skip) { return }
#rm (remove file)
$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" {
$adminsSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid)
$currentUserSid = Get-UserSID -User "$($env:USERDOMAIN)\$($env:USERNAME)"
$permTestHasAccessFile = "permTestHasAccessFile.txt"
$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
$permTestNoAccessFile = "permTestNoAccessFile.txt"
$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
Set-FileOwnerAndACL -Filepath $permTestNoAccessFilePath -OwnerPerms "Read","Write"
Repair-FilePermission -Filepath $permTestNoAccessFilePath -Owners $currentUserSid -FullAccessNeeded $adminsSid,$currentUserSid -confirm:$false
$Commands = "ls $serverDirectory"
Set-Content $batchFilePath -Encoding UTF8 -value $Commands
@ -282,11 +292,11 @@ Describe "SFTP Test Cases" -Tags "CI" {
#cleanup
$HasAccessPattern = $permTestHasAccessFilePath.Replace("\", "[/\\]")
$matches = $content | select-string -Pattern "^/$HasAccessPattern\s{0,}$"
$matches = @($content | select-string -Pattern "^/$HasAccessPattern\s{0,}$")
$matches.count | Should be 1
$NoAccessPattern = $permTestNoAccessFilePath.Replace("\", "[/\\]")
$matches = $content | select-string -Pattern "^/$NoAccessPattern\s{0,}$"
$matches = @($content | select-string -Pattern "^/$NoAccessPattern\s{0,}$")
$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
$tC = 1
$tI = 0
@ -8,7 +10,7 @@ Describe "E2E scenarios for ssh client" -Tags "CI" {
BeforeAll {
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"]
@ -20,6 +22,8 @@ Describe "E2E scenarios for ssh client" -Tags "CI" {
{
$null = New-Item $testDir -ItemType directory -Force -ErrorAction SilentlyContinue
}
$platform = Get-Platform
$skip = ($platform -eq [PlatformType]::Windows) -and ($PSVersionTable.PSVersion.Major -le 2)
<#$testData = @(
@{
@ -112,7 +116,7 @@ Describe "E2E scenarios for ssh client" -Tags "CI" {
BeforeAll {$tI=1}
AfterAll{$tC++}
It "$tC.$tI - stdout to file" {
It "$tC.$tI - stdout to file" -skip:$skip {
ssh test_target powershell get-process > $stdoutFile
$stdoutFile | Should Contain "ProcessName"
}

View File

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

View File

@ -125,4 +125,5 @@ PubkeyAcceptedKeyTypes ssh-ed25519*
#DenyUsers denyuser1 deny*2 denyuse?3,
#AllowUsers allowuser1 allowu*r2 allow?se?3 allowuser4 localuser1 localu*r2 loc?lu?er3 localadmin
#DenyGroups denygroup1 denygr*p2 deny?rou?3
#AllowGroups allowgroup1 allowg*2 allowg?ou?3 Adm*
#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
$tI = 0
@ -8,7 +9,7 @@ Describe "Tests for user Key file permission" -Tags "CI" {
BeforeAll {
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"
if( -not (Test-path $testDir -PathType Container))
@ -24,13 +25,13 @@ Describe "Tests for user Key file permission" -Tags "CI" {
$server = $OpenSSHTestInfo["Target"]
$userName = "$env:USERNAME@$env:USERDOMAIN"
$keypassphrase = "testpassword"
$systemAccount = New-Object System.Security.Principal.NTAccount("NT AUTHORITY", "SYSTEM")
$adminsAccount = New-Object System.Security.Principal.NTAccount("BUILTIN","Administrators")
$objUser = New-Object System.Security.Principal.NTAccount($ssouser)
$pubKeyUserAccount = New-Object System.Security.Principal.NTAccount($pubKeyUser)
$currentUser = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME))
$everyone = New-Object System.Security.Principal.NTAccount("EveryOne")
$systemSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::LocalSystemSid)
$adminsSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid)
$currentUserSid = Get-UserSID -User "$($env:USERDOMAIN)\$($env:USERNAME)"
$objUserSid = Get-UserSID -User $ssouser
$everyoneSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::WorldSid)
$pubKeyUserAccountSid = Get-UserSID -User $pubKeyUser
Add-PasswordSetting -Pass $keypassphrase
}
@ -48,7 +49,7 @@ Describe "Tests for user Key file permission" -Tags "CI" {
BeforeAll {
$keyFileName = "sshtest_userPermTestkey_ed25519"
$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
$pubKeyUserProfilePath = Join-Path $pubKeyUserProfile .ssh
@ -58,22 +59,22 @@ Describe "Tests for user Key file permission" -Tags "CI" {
$testAuthorizedKeyPath = Join-Path $pubKeyUserProfilePath authorized_keys
Copy-Item "$keyFilePath.pub" $testAuthorizedKeyPath -Force -ErrorAction SilentlyContinue
Adjust-UserKeyFileACL -FilePath $testAuthorizedKeyPath -Owner $pubKeyUserAccount -OwnerPerms "Read, Write"
Add-PermissionToFileACL -FilePath $testAuthorizedKeyPath -User "NT Service\sshd" -Perm "Read"
Repair-AuthorizedKeyPermission -FilePath $testAuthorizedKeyPath -confirm:$false
$tI=1
}
AfterAll {
if(Test-Path $testAuthorizedKeyPath) {
Remove-Item $testAuthorizedKeyPath -Force -ErrorAction Ignore
Remove-Item $testAuthorizedKeyPath -Force -ErrorAction SilentlyContinue
}
if(Test-Path $pubKeyUserProfilePath) {
Remove-Item $pubKeyUserProfilePath -Recurse -Force -ErrorAction Ignore
Remove-Item $pubKeyUserProfilePath -Recurse -Force -ErrorAction SilentlyContinue
}
$tC++
}
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
$o = ssh -p $port -i $keyFilePath $pubKeyUser@$server echo 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)" {
#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
$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)" {
#setup to have local admin group as owner and grant it full control
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $adminsAccount -OwnerPerms "FullControl"
Add-PermissionToFileACL -FilePath $keyFilePath -User $currentUser -Perm "Read"
Repair-FilePermission -FilePath $keyFilePath -Owners $adminsSid -FullAccessNeeded $adminsSid,$systemSid -ReadAccessNeeded $currentUserSid -confirm:$false
#Run
$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)" {
#setup to have local system as owner and grant it full control
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $systemAccount -OwnerPerms "FullControl"
Add-PermissionToFileACL -FilePath $keyFilePath -User $adminsAccount -Perm "Read"
Repair-FilePermission -FilePath $keyFilePath -Owners $systemSid -FullAccessNeeded $adminsSid,$systemSid -confirm:$false
#Run
$o = ssh -p $port -i $keyFilePath $pubKeyUser@$server echo 1234
@ -109,11 +108,8 @@ 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)" {
#setup to have current user as owner and grant it full control
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $currentUser -OwnerPerms "Read, Write"
#add ssouser to access the private key
Add-PermissionToFileACL -FilePath $keyFilePath -User $objUser -Perm "Read"
#setup to have current user as owner and grant it full control
Repair-FilePermission -FilePath $keyFilePath -Owners $currentUserSid -FullAccessNeeded $currentUser,$adminsSid,$systemSid -ReadAccessNeeded $objUserSid -confirm:$false
#Run
$o = ssh -p $port -i $keyFilePath -E $logPath $pubKeyUser@$server echo 1234
@ -123,9 +119,8 @@ Describe "Tests for user Key file permission" -Tags "CI" {
}
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
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $objUser -OwnerPerms "Read, Write"
Add-PermissionToFileACL -FilePath $keyFilePath -User $adminsAccount -Perm "FullControl"
#setup to have ssouser as owner and grant it full control
Repair-FilePermission -FilePath $keyFilePath -Owners $objUserSid -FullAccessNeeded $objUserSid,$adminsSid,$systemSid -ReadAccessNeeded $objUserSid -confirm:$false
$o = ssh -p $port -i $keyFilePath -E $logPath $pubKeyUser@$server echo 1234
$LASTEXITCODE | Should Not Be 0

View File

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

View File

@ -477,6 +477,9 @@ int do_exec_windows(Session *s, const char *command, int pty) {
*cmd = '\0';
}
/* load user profile */
mm_load_profile(s->pw->pw_name, ((INT_PTR)s->authctxt->auth_token) & 0xffffffff);
/* start the process */
{
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.lpDesktop = NULL;
hToken = s->authctxt->methoddata;
hToken = s->authctxt->auth_token;
debug("Executing command: %s", 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)
{
#ifdef WINDOWS
/* execute via system call in Windows*/
if (!*args) {
args = (char *) getenv("ComSpec"); // get name of Windows cmd shell
/* execute via system call in Windows*/
char cmd_path[PATH_MAX] = { 0, };
if (!*args){
if (!GetSystemDirectory(cmd_path, sizeof(cmd_path)))
fatal("GetSystemDirectory failed");
strcat_s(cmd_path, PATH_MAX, "\\cmd.exe");
args = cmd_path;
} else {
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",
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++) {
if (options.host_key_files[i] == NULL)
continue;