mirror of
https://github.com/PowerShell/Win32-OpenSSH.git
synced 2025-07-23 05:55:41 +02:00
Source snapshot from Powershell/openssh-portable:latestw_all
This commit is contained in:
parent
944505e199
commit
7580216f04
21
appveyor.yml
21
appveyor.yml
@ -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
|
@ -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
9
auth.c
@ -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
4
auth.h
@ -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;
|
||||
};
|
||||
|
@ -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",
|
||||
|
9
authfd.h
9
authfd.h
@ -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 */
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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" />
|
||||
|
@ -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">
|
||||
|
@ -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.
@ -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)
|
||||
|
@ -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;
|
||||
|
8
contrib/win32/win32compat/priv-agent.h
Normal file
8
contrib/win32/win32compat/priv-agent.h
Normal 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"
|
@ -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" "));
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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*);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
214
contrib/win32/win32compat/win32_monitor_wrap.c
Normal file
214
contrib/win32/win32compat/win32_monitor_wrap.c
Normal 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;
|
||||
}
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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_ */
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
@ -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"
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -50,7 +50,7 @@
|
||||
$client.AddPasswordSetting($password)
|
||||
}
|
||||
AfterEach {
|
||||
Remove-Item -Path $filePath -Force -ea ignore
|
||||
Remove-Item -Path $filePath -Force -ea SilentlyContinue
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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
11
sftp.c
@ -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
4
sshd.c
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user