mirror of
https://github.com/PowerShell/Win32-OpenSSH.git
synced 2025-07-27 07:54:50 +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
|
image: Visual Studio 2015
|
||||||
|
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- latestw_all
|
- latestw_all
|
||||||
- latestw_all_openssl
|
|
||||||
|
|
||||||
init:
|
init:
|
||||||
- ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
- ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
- ps: |
|
- ps: |
|
||||||
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking
|
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1
|
||||||
Invoke-AppVeyorBuild
|
Invoke-AppVeyorBuild
|
||||||
|
|
||||||
after_build:
|
after_build:
|
||||||
- ps: |
|
- ps: |
|
||||||
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking
|
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1
|
||||||
Install-OpenSSH
|
Install-OpenSSH
|
||||||
|
|
||||||
before_test:
|
before_test:
|
||||||
- ps: |
|
- ps: |
|
||||||
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking
|
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1
|
||||||
Setup-OpenSSHTestEnvironment -Quiet
|
Set-OpenSSHTestEnvironment -Confirm:$false
|
||||||
|
|
||||||
test_script:
|
test_script:
|
||||||
- ps: |
|
- ps: |
|
||||||
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking
|
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1
|
||||||
Run-OpenSSHTests
|
Invoke-OpenSSHTests
|
||||||
|
|
||||||
after_test:
|
after_test:
|
||||||
- ps: |
|
- ps: |
|
||||||
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking
|
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1
|
||||||
Upload-OpenSSHTestResults
|
Publish-OpenSSHTestResults
|
||||||
|
|
||||||
on_finish:
|
on_finish:
|
||||||
- ps: |
|
- ps: |
|
||||||
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking
|
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1
|
||||||
Publish-Artifact
|
Publish-Artifact
|
@ -226,38 +226,45 @@ sys_auth_passwd(Authctxt *authctxt, const char *password)
|
|||||||
|
|
||||||
#elif defined(WINDOWS)
|
#elif defined(WINDOWS)
|
||||||
/*
|
/*
|
||||||
* Authenticate on Windows - Pass credentials to ssh-agent and retrieve token
|
* Authenticate on Windows - Call LogonUser and retrieve user token
|
||||||
* upon successful authentication
|
|
||||||
* TODO - password is sent in plain text over IPC. Consider implications.
|
|
||||||
*/
|
*/
|
||||||
int sys_auth_passwd(Authctxt *authctxt, const char *password)
|
int sys_auth_passwd(Authctxt *authctxt, const char *password)
|
||||||
{
|
{
|
||||||
struct sshbuf *msg = NULL;
|
wchar_t *user_utf16 = NULL, *udom_utf16 = NULL, *pwd_utf16 = NULL, *tmp;
|
||||||
size_t blen = 0;
|
HANDLE token = NULL;
|
||||||
DWORD token = 0;
|
|
||||||
extern int auth_sock;
|
|
||||||
int r = 0;
|
int r = 0;
|
||||||
int ssh_request_reply(int, struct sshbuf *, struct sshbuf *);
|
|
||||||
|
|
||||||
msg = sshbuf_new();
|
if ((user_utf16 = utf8_to_utf16(authctxt->pw->pw_name)) == NULL ||
|
||||||
if (!msg)
|
(pwd_utf16 = utf8_to_utf16(password)) == NULL) {
|
||||||
fatal("%s: out of memory", __func__);
|
fatal("out of memory");
|
||||||
|
|
||||||
if (sshbuf_put_u8(msg, SSH_AGENT_AUTHENTICATE) != 0 ||
|
|
||||||
sshbuf_put_cstring(msg, PASSWD_AUTH_REQUEST) != 0 ||
|
|
||||||
sshbuf_put_cstring(msg, authctxt->pw->pw_name) != 0 ||
|
|
||||||
sshbuf_put_cstring(msg, password) != 0 ||
|
|
||||||
ssh_request_reply(auth_sock, msg, msg) != 0 ||
|
|
||||||
sshbuf_get_u32(msg, &token) != 0) {
|
|
||||||
debug("auth agent did not authorize client %s", authctxt->user);
|
|
||||||
r = 0;
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
authctxt->methoddata = (void*)(INT_PTR)token;
|
|
||||||
|
if ((tmp = wcschr(user_utf16, L'@')) != NULL) {
|
||||||
|
udom_utf16 = tmp + 1;
|
||||||
|
*tmp = L'\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LogonUserW(user_utf16, udom_utf16, pwd_utf16, LOGON32_LOGON_NETWORK_CLEARTEXT,
|
||||||
|
LOGON32_PROVIDER_DEFAULT, &token) == FALSE) {
|
||||||
|
if (GetLastError() == ERROR_PASSWORD_MUST_CHANGE)
|
||||||
|
/*
|
||||||
|
* TODO - need to add support to force password change
|
||||||
|
* by sending back SSH_MSG_USERAUTH_PASSWD_CHANGEREQ
|
||||||
|
*/
|
||||||
|
error("password for user %s has expired", authctxt->pw->pw_name);
|
||||||
|
else
|
||||||
|
debug("failed to logon user: %ls domain: %ls error:%d", user_utf16, udom_utf16, GetLastError());
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
authctxt->auth_token = (void*)(INT_PTR)token;
|
||||||
r = 1;
|
r = 1;
|
||||||
done:
|
done:
|
||||||
if (msg)
|
if (user_utf16)
|
||||||
sshbuf_free(msg);
|
free(user_utf16);
|
||||||
|
if (pwd_utf16)
|
||||||
|
SecureZeroMemory(pwd_utf16, sizeof(wchar_t) * wcslen(pwd_utf16));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
#endif /* WINDOWS */
|
#endif /* WINDOWS */
|
||||||
|
9
auth.c
9
auth.c
@ -405,6 +405,13 @@ expand_authorized_keys(const char *filename, struct passwd *pw)
|
|||||||
file = percent_expand(filename, "h", pw->pw_dir,
|
file = percent_expand(filename, "h", pw->pw_dir,
|
||||||
"u", pw->pw_name, (char *)NULL);
|
"u", pw->pw_name, (char *)NULL);
|
||||||
|
|
||||||
|
#ifdef WINDOWS
|
||||||
|
/* Return if the path is absolute. If not, prepend the '%h\\' */
|
||||||
|
if ((strlen(file) > 1) && (file[1] == ':'))
|
||||||
|
return (file);
|
||||||
|
|
||||||
|
i = snprintf(ret, sizeof(ret), "%s\\%s", pw->pw_dir, file);
|
||||||
|
#else
|
||||||
/*
|
/*
|
||||||
* Ensure that filename starts anchored. If not, be backward
|
* Ensure that filename starts anchored. If not, be backward
|
||||||
* compatible and prepend the '%h/'
|
* compatible and prepend the '%h/'
|
||||||
@ -413,6 +420,8 @@ expand_authorized_keys(const char *filename, struct passwd *pw)
|
|||||||
return (file);
|
return (file);
|
||||||
|
|
||||||
i = snprintf(ret, sizeof(ret), "%s/%s", pw->pw_dir, file);
|
i = snprintf(ret, sizeof(ret), "%s/%s", pw->pw_dir, file);
|
||||||
|
#endif // WINDOWS
|
||||||
|
|
||||||
if (i < 0 || (size_t)i >= sizeof(ret))
|
if (i < 0 || (size_t)i >= sizeof(ret))
|
||||||
fatal("expand_authorized_keys: path too long");
|
fatal("expand_authorized_keys: path too long");
|
||||||
free(file);
|
free(file);
|
||||||
|
4
auth.h
4
auth.h
@ -78,7 +78,9 @@ struct Authctxt {
|
|||||||
#endif
|
#endif
|
||||||
Buffer *loginmsg;
|
Buffer *loginmsg;
|
||||||
void *methoddata;
|
void *methoddata;
|
||||||
|
#ifdef WINDOWS
|
||||||
|
void *auth_token;
|
||||||
|
#endif
|
||||||
struct sshkey **prev_userkeys;
|
struct sshkey **prev_userkeys;
|
||||||
u_int nprev_userkeys;
|
u_int nprev_userkeys;
|
||||||
};
|
};
|
||||||
|
@ -200,54 +200,14 @@ userauth_pubkey(struct ssh *ssh)
|
|||||||
/* test for correct signature */
|
/* test for correct signature */
|
||||||
authenticated = 0;
|
authenticated = 0;
|
||||||
|
|
||||||
#ifdef WINDOWS
|
|
||||||
/* Pass key challenge material to ssh-agent to retrieve token upon successful authentication */
|
|
||||||
{
|
|
||||||
struct sshbuf *msg = NULL;
|
|
||||||
u_char *blob = NULL;
|
|
||||||
size_t blen = 0;
|
|
||||||
DWORD token = 0;
|
|
||||||
extern int auth_sock;
|
|
||||||
int r = 0;
|
|
||||||
int ssh_request_reply(int , struct sshbuf *, struct sshbuf *);
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
msg = sshbuf_new();
|
|
||||||
if (!msg)
|
|
||||||
fatal("%s: out of memory", __func__);
|
|
||||||
if ((r = sshbuf_put_u8(msg, SSH_AGENT_AUTHENTICATE)) != 0 ||
|
|
||||||
(r = sshbuf_put_cstring(msg, PUBKEY_AUTH_REQUEST)) != 0 ||
|
|
||||||
(r = sshkey_to_blob(key, &blob, &blen)) != 0 ||
|
|
||||||
(r = sshbuf_put_string(msg, blob, blen)) != 0 ||
|
|
||||||
(r = sshbuf_put_cstring(msg, authctxt->pw->pw_name)) != 0 ||
|
|
||||||
(r = sshbuf_put_string(msg, sig, slen)) != 0 ||
|
|
||||||
(r = sshbuf_put_string(msg, sshbuf_ptr(b), sshbuf_len(b))) != 0 ||
|
|
||||||
(r = ssh_request_reply(auth_sock, msg, msg)) != 0 ||
|
|
||||||
(r = sshbuf_get_u32(msg, &token)) != 0) {
|
|
||||||
debug("auth agent did not authorize client %s", authctxt->user);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
debug3("auth agent authenticated %s", authctxt->user);
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
if (blob)
|
|
||||||
free(blob);
|
|
||||||
if (msg)
|
|
||||||
sshbuf_free(msg);
|
|
||||||
|
|
||||||
if (token) {
|
|
||||||
authenticated = 1;
|
|
||||||
authctxt->methoddata = (void*)(INT_PTR)token;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* !WINDOWS */
|
|
||||||
if (PRIVSEP(user_key_allowed(authctxt->pw, key, 1)) &&
|
if (PRIVSEP(user_key_allowed(authctxt->pw, key, 1)) &&
|
||||||
|
#ifdef WINDOWS
|
||||||
|
(authctxt->auth_token = mm_auth_pubkey(authctxt->pw->pw_name,
|
||||||
|
key, sig, slen, b)) != NULL) {
|
||||||
|
#else
|
||||||
PRIVSEP(sshkey_verify(key, sig, slen, sshbuf_ptr(b),
|
PRIVSEP(sshkey_verify(key, sig, slen, sshbuf_ptr(b),
|
||||||
sshbuf_len(b), ssh->compat)) == 0) {
|
sshbuf_len(b), ssh->compat)) == 0) {
|
||||||
|
#endif
|
||||||
authenticated = 1;
|
authenticated = 1;
|
||||||
/* Record the successful key to prevent reuse */
|
/* Record the successful key to prevent reuse */
|
||||||
auth2_record_userkey(authctxt, key);
|
auth2_record_userkey(authctxt, key);
|
||||||
@ -255,7 +215,6 @@ userauth_pubkey(struct ssh *ssh)
|
|||||||
}
|
}
|
||||||
sshbuf_free(b);
|
sshbuf_free(b);
|
||||||
free(sig);
|
free(sig);
|
||||||
#endif /* !WINDOWS */
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
debug("%s: test whether pkalg/pkblob are acceptable for %s %s",
|
debug("%s: test whether pkalg/pkblob are acceptable for %s %s",
|
||||||
|
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);
|
const u_char *data, size_t datalen, const char *alg, u_int compat);
|
||||||
|
|
||||||
/* Messages for the authentication agent connection. */
|
/* Messages for the authentication agent connection. */
|
||||||
|
/* Message Id 0 is reserved */
|
||||||
#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
|
#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
|
||||||
#define SSH_AGENT_RSA_IDENTITIES_ANSWER 2
|
#define SSH_AGENT_RSA_IDENTITIES_ANSWER 2
|
||||||
#define SSH_AGENTC_RSA_CHALLENGE 3
|
#define SSH_AGENTC_RSA_CHALLENGE 3
|
||||||
@ -88,12 +89,4 @@ int ssh_agent_sign(int sock, struct sshkey *key,
|
|||||||
#define SSH_AGENT_RSA_SHA2_256 0x02
|
#define SSH_AGENT_RSA_SHA2_256 0x02
|
||||||
#define SSH_AGENT_RSA_SHA2_512 0x04
|
#define SSH_AGENT_RSA_SHA2_512 0x04
|
||||||
|
|
||||||
/*
|
|
||||||
* Following are used in Windows implementation
|
|
||||||
* ssh-agent in Windows also serves user authentication
|
|
||||||
*/
|
|
||||||
#define SSH_AGENT_AUTHENTICATE 200
|
|
||||||
#define PUBKEY_AUTH_REQUEST "pubkey"
|
|
||||||
#define PASSWD_AUTH_REQUEST "password"
|
|
||||||
|
|
||||||
#endif /* AUTHFD_H */
|
#endif /* AUTHFD_H */
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
$ErrorActionPreference = 'Stop'
|
$ErrorActionPreference = 'Stop'
|
||||||
Import-Module $PSScriptRoot\OpenSSHCommonUtils.psm1 -Force -DisableNameChecking
|
Set-StrictMode -Version 2.0
|
||||||
Import-Module $PSScriptRoot\OpenSSHBuildHelper.psm1 -Force -DisableNameChecking
|
If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
|
||||||
Import-Module $PSScriptRoot\OpenSSHTestHelper.psm1 -Force -DisableNameChecking
|
Import-Module $PSScriptRoot\OpenSSHCommonUtils.psm1 -Force
|
||||||
|
Import-Module $PSScriptRoot\OpenSSHBuildHelper.psm1 -Force
|
||||||
|
Import-Module $PSScriptRoot\OpenSSHTestHelper.psm1 -Force
|
||||||
|
|
||||||
$repoRoot = Get-RepositoryRoot
|
$repoRoot = Get-RepositoryRoot
|
||||||
$script:messageFile = join-path $repoRoot.FullName "BuildMessage.log"
|
$script:messageFile = join-path $repoRoot.FullName "BuildMessage.log"
|
||||||
|
|
||||||
# Sets a build variable
|
# Write the build message
|
||||||
Function Write-BuildMessage
|
Function Write-BuildMessage
|
||||||
{
|
{
|
||||||
param(
|
param(
|
||||||
@ -78,11 +80,10 @@ function Invoke-AppVeyorFull
|
|||||||
$env:APPVEYOR_SCHEDULED_BUILD = 'True'
|
$env:APPVEYOR_SCHEDULED_BUILD = 'True'
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Set-OpenSSHTestParams
|
|
||||||
Invoke-AppVeyorBuild
|
Invoke-AppVeyorBuild
|
||||||
Install-OpenSSH
|
Install-OpenSSH
|
||||||
Setup-OpenSSHTestEnvironment
|
Set-OpenSSHTestEnvironment -confirm:$false
|
||||||
Run-OpenSSHTests
|
Invoke-OpenSSHTests
|
||||||
Publish-Artifact
|
Publish-Artifact
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
@ -97,8 +98,8 @@ function Invoke-AppVeyorFull
|
|||||||
function Invoke-AppVeyorBuild
|
function Invoke-AppVeyorBuild
|
||||||
{
|
{
|
||||||
Set-BuildVariable TestPassed True
|
Set-BuildVariable TestPassed True
|
||||||
Build-OpenSSH -Configuration Release -NativeHostArch x64
|
Start-OpenSSHBuild -Configuration Release -NativeHostArch x64
|
||||||
Build-OpenSSH -Configuration Debug -NativeHostArch x86
|
Start-OpenSSHBuild -Configuration Release -NativeHostArch x86
|
||||||
Write-BuildMessage -Message "OpenSSH binaries build success!" -Category Information
|
Write-BuildMessage -Message "OpenSSH binaries build success!" -Category Information
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,6 +137,100 @@ function Add-BuildLog
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<#
|
||||||
|
.Synopsis
|
||||||
|
Deploy all required files to a location and install the binaries
|
||||||
|
#>
|
||||||
|
function Install-OpenSSH
|
||||||
|
{
|
||||||
|
[CmdletBinding()]
|
||||||
|
param
|
||||||
|
(
|
||||||
|
[ValidateSet('Debug', 'Release')]
|
||||||
|
[string]$Configuration = "Release",
|
||||||
|
|
||||||
|
[ValidateSet('x86', 'x64', '')]
|
||||||
|
[string]$NativeHostArch = "",
|
||||||
|
|
||||||
|
[string]$OpenSSHDir = "$env:SystemDrive\OpenSSH"
|
||||||
|
)
|
||||||
|
|
||||||
|
if ($NativeHostArch -eq "")
|
||||||
|
{
|
||||||
|
$NativeHostArch = 'x64'
|
||||||
|
if ($env:PROCESSOR_ARCHITECTURE -eq 'x86') {
|
||||||
|
$NativeHostArch = 'x86'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Start-OpenSSHPackage -NativeHostArch $NativeHostArch -Configuration $Configuration -DestinationPath $OpenSSHDir
|
||||||
|
|
||||||
|
Push-Location $OpenSSHDir
|
||||||
|
& "$OpenSSHDir\install-sshd.ps1"
|
||||||
|
& "$OpenSSHDir\ssh-keygen.exe" -A
|
||||||
|
& "$OpenSSHDir\FixHostFilePermissions.ps1" -Confirm:$false
|
||||||
|
|
||||||
|
#machine will be reboot after Install-openssh anyway
|
||||||
|
$machinePath = [Environment]::GetEnvironmentVariable('Path', 'MACHINE')
|
||||||
|
$newMachineEnvironmentPath = $machinePath
|
||||||
|
if (-not ($machinePath.ToLower().Contains($OpenSSHDir.ToLower())))
|
||||||
|
{
|
||||||
|
$newMachineEnvironmentPath = "$OpenSSHDir;$newMachineEnvironmentPath"
|
||||||
|
$env:Path = "$OpenSSHDir;$env:Path"
|
||||||
|
}
|
||||||
|
# Update machine environment path
|
||||||
|
if ($newMachineEnvironmentPath -ne $machinePath)
|
||||||
|
{
|
||||||
|
[Environment]::SetEnvironmentVariable('Path', $newMachineEnvironmentPath, 'MACHINE')
|
||||||
|
}
|
||||||
|
|
||||||
|
Set-Service sshd -StartupType Automatic
|
||||||
|
Set-Service ssh-agent -StartupType Automatic
|
||||||
|
|
||||||
|
Pop-Location
|
||||||
|
Write-BuildMessage -Message "OpenSSH installed!" -Category Information
|
||||||
|
}
|
||||||
|
|
||||||
|
<#
|
||||||
|
.Synopsis
|
||||||
|
uninstalled sshd
|
||||||
|
#>
|
||||||
|
function UnInstall-OpenSSH
|
||||||
|
{
|
||||||
|
[CmdletBinding()]
|
||||||
|
param
|
||||||
|
(
|
||||||
|
[string]$OpenSSHDir = "$env:SystemDrive\OpenSSH"
|
||||||
|
)
|
||||||
|
|
||||||
|
if (-not (Test-Path $OpenSSHDir -PathType Container))
|
||||||
|
{
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Push-Location $OpenSSHDir
|
||||||
|
if((Get-Service ssh-agent -ErrorAction SilentlyContinue) -ne $null) {
|
||||||
|
Stop-Service ssh-agent -Force
|
||||||
|
}
|
||||||
|
& "$OpenSSHDir\uninstall-sshd.ps1"
|
||||||
|
|
||||||
|
$machinePath = [Environment]::GetEnvironmentVariable('Path', 'MACHINE')
|
||||||
|
$newMachineEnvironmentPath = $machinePath
|
||||||
|
if ($machinePath.ToLower().Contains($OpenSSHDir.ToLower()))
|
||||||
|
{
|
||||||
|
$newMachineEnvironmentPath = $newMachineEnvironmentPath.Replace("$OpenSSHDir;", '')
|
||||||
|
$env:Path = $env:Path.Replace("$OpenSSHDir;", '')
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($newMachineEnvironmentPath -ne $machinePath)
|
||||||
|
{
|
||||||
|
[Environment]::SetEnvironmentVariable('Path', $newMachineEnvironmentPath, 'MACHINE')
|
||||||
|
}
|
||||||
|
|
||||||
|
Pop-Location
|
||||||
|
Remove-Item -Path $OpenSSHDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
|
||||||
<#
|
<#
|
||||||
.Synopsis
|
.Synopsis
|
||||||
Publishes package build artifacts.
|
Publishes package build artifacts.
|
||||||
@ -170,11 +265,11 @@ function Add-Artifact
|
|||||||
function Publish-Artifact
|
function Publish-Artifact
|
||||||
{
|
{
|
||||||
Write-Host -ForegroundColor Yellow "Publishing project artifacts"
|
Write-Host -ForegroundColor Yellow "Publishing project artifacts"
|
||||||
[System.Collections.ArrayList] $artifacts = [System.Collections.ArrayList]::new()
|
[System.Collections.ArrayList] $artifacts = new-object System.Collections.ArrayList
|
||||||
|
|
||||||
# Get the build.log file for each build configuration
|
# Get the build.log file for each build configuration
|
||||||
Add-BuildLog -artifacts $artifacts -buildLog (Get-BuildLogFile -root $repoRoot.FullName -Configuration Release -NativeHostArch x64)
|
Add-BuildLog -artifacts $artifacts -buildLog (Get-BuildLogFile -root $repoRoot.FullName -Configuration Release -NativeHostArch x64)
|
||||||
Add-BuildLog -artifacts $artifacts -buildLog (Get-BuildLogFile -root $repoRoot.FullName -Configuration Debug -NativeHostArch x86)
|
Add-BuildLog -artifacts $artifacts -buildLog (Get-BuildLogFile -root $repoRoot.FullName -Configuration Release -NativeHostArch x86)
|
||||||
|
|
||||||
if($Global:OpenSSHTestInfo)
|
if($Global:OpenSSHTestInfo)
|
||||||
{
|
{
|
||||||
@ -186,7 +281,6 @@ function Publish-Artifact
|
|||||||
foreach ($artifact in $artifacts)
|
foreach ($artifact in $artifacts)
|
||||||
{
|
{
|
||||||
Write-Host "Publishing $artifact as Appveyor artifact"
|
Write-Host "Publishing $artifact as Appveyor artifact"
|
||||||
# NOTE: attempt to publish subsequent artifacts even if the current one fails
|
|
||||||
Push-AppveyorArtifact $artifact -ErrorAction Continue
|
Push-AppveyorArtifact $artifact -ErrorAction Continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -195,10 +289,10 @@ function Publish-Artifact
|
|||||||
.Synopsis
|
.Synopsis
|
||||||
Runs the tests for this repo
|
Runs the tests for this repo
|
||||||
#>
|
#>
|
||||||
function Run-OpenSSHTests
|
function Invoke-OpenSSHTests
|
||||||
{
|
{
|
||||||
Write-Host "Start running unit tests"
|
Write-Host "Start running unit tests"
|
||||||
$unitTestFailed = Run-OpenSSHUnitTest
|
$unitTestFailed = Invoke-OpenSSHUnitTest
|
||||||
|
|
||||||
if($unitTestFailed)
|
if($unitTestFailed)
|
||||||
{
|
{
|
||||||
@ -212,14 +306,14 @@ function Run-OpenSSHTests
|
|||||||
Write-BuildMessage -Message "All Unit tests passed!" -Category Information
|
Write-BuildMessage -Message "All Unit tests passed!" -Category Information
|
||||||
}
|
}
|
||||||
# Run all E2E tests.
|
# Run all E2E tests.
|
||||||
Run-OpenSSHE2ETest
|
Invoke-OpenSSHE2ETest
|
||||||
if (($OpenSSHTestInfo -eq $null) -or (-not (Test-Path $OpenSSHTestInfo["E2ETestResultsFile"])))
|
if (($OpenSSHTestInfo -eq $null) -or (-not (Test-Path $OpenSSHTestInfo["E2ETestResultsFile"])))
|
||||||
{
|
{
|
||||||
Write-Warning "Test result file $OpenSSHTestInfo["E2ETestResultsFile"] not found after tests."
|
Write-Warning "Test result file $OpenSSHTestInfo["E2ETestResultsFile"] not found after tests."
|
||||||
Write-BuildMessage -Message "Test result file $OpenSSHTestInfo["E2ETestResultsFile"] not found after tests." -Category Error
|
Write-BuildMessage -Message "Test result file $OpenSSHTestInfo["E2ETestResultsFile"] not found after tests." -Category Error
|
||||||
Set-BuildVariable TestPassed False
|
Set-BuildVariable TestPassed False
|
||||||
}
|
}
|
||||||
$xml = [xml](Get-Content -raw $OpenSSHTestInfo["E2ETestResultsFile"])
|
$xml = [xml](Get-Content $OpenSSHTestInfo["E2ETestResultsFile"] | out-string)
|
||||||
if ([int]$xml.'test-results'.failures -gt 0)
|
if ([int]$xml.'test-results'.failures -gt 0)
|
||||||
{
|
{
|
||||||
$errorMessage = "$($xml.'test-results'.failures) tests in regress\pesterTests failed. Detail test log is at $($OpenSSHTestInfo["E2ETestResultsFile"])."
|
$errorMessage = "$($xml.'test-results'.failures) tests in regress\pesterTests failed. Detail test log is at $($OpenSSHTestInfo["E2ETestResultsFile"])."
|
||||||
@ -239,7 +333,7 @@ function Run-OpenSSHTests
|
|||||||
.Synopsis
|
.Synopsis
|
||||||
upload OpenSSH pester test results.
|
upload OpenSSH pester test results.
|
||||||
#>
|
#>
|
||||||
function Upload-OpenSSHTestResults
|
function Publish-OpenSSHTestResults
|
||||||
{
|
{
|
||||||
if ($env:APPVEYOR_JOB_ID)
|
if ($env:APPVEYOR_JOB_ID)
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
|
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
|
||||||
param ()
|
param ()
|
||||||
Set-StrictMode -Version 2.0
|
Set-StrictMode -Version 2.0
|
||||||
If (!(Test-Path variable:PSScriptRoot)) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Definition}
|
If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
|
||||||
Import-Module $PSScriptRoot\OpenSSHUtils -Force
|
Import-Module $PSScriptRoot\OpenSSHUtils -Force
|
||||||
|
|
||||||
#check sshd config file
|
#check sshd config file
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
|
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
|
||||||
param ()
|
param ()
|
||||||
Set-StrictMode -Version 2.0
|
Set-StrictMode -Version 2.0
|
||||||
If (!(Test-Path variable:PSScriptRoot)) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Definition}
|
If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
|
||||||
|
|
||||||
Import-Module $PSScriptRoot\OpenSSHUtils -Force
|
Import-Module $PSScriptRoot\OpenSSHUtils -Force
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
Set-StrictMode -Version Latest
|
Set-StrictMode -Version 2.0
|
||||||
|
If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
|
||||||
|
Import-Module $PSScriptRoot\OpenSSHCommonUtils.psm1 -Force
|
||||||
|
|
||||||
Import-Module $PSScriptRoot\OpenSSHCommonUtils.psm1 -force -DisableNameChecking
|
|
||||||
[string] $script:platform = $env:PROCESSOR_ARCHITECTURE
|
|
||||||
[string] $script:vcPath = $null
|
[string] $script:vcPath = $null
|
||||||
[System.IO.DirectoryInfo] $script:OpenSSHRoot = $null
|
[System.IO.DirectoryInfo] $script:OpenSSHRoot = $null
|
||||||
[System.IO.DirectoryInfo] $script:gitRoot = $null
|
[System.IO.DirectoryInfo] $script:gitRoot = $null
|
||||||
@ -83,7 +83,7 @@ function Write-BuildMsg
|
|||||||
[switch] $Silent
|
[switch] $Silent
|
||||||
)
|
)
|
||||||
|
|
||||||
if ($AsVerbose)
|
if($PSBoundParameters.ContainsKey("AsVerbose"))
|
||||||
{
|
{
|
||||||
if ($script:Verbose)
|
if ($script:Verbose)
|
||||||
{
|
{
|
||||||
@ -96,17 +96,24 @@ function Write-BuildMsg
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($AsInfo)
|
if($PSBoundParameters.ContainsKey("AsInfo"))
|
||||||
{
|
{
|
||||||
Write-Log -Message "INFO: $message"
|
Write-Log -Message "INFO: $message"
|
||||||
if (-not $Silent)
|
if (-not $Silent)
|
||||||
{
|
{
|
||||||
Write-Information -MessageData $message -InformationAction Continue
|
if(Get-Command "Write-Information" -ErrorAction SilentlyContinue )
|
||||||
|
{
|
||||||
|
Write-Information -MessageData $message -InformationAction Continue
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Write-Verbose -Message $message -Verbose
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($AsWarning)
|
if($PSBoundParameters.ContainsKey("AsWarning"))
|
||||||
{
|
{
|
||||||
Write-Log -Message "WARNING: $message"
|
Write-Log -Message "WARNING: $message"
|
||||||
if (-not $Silent)
|
if (-not $Silent)
|
||||||
@ -116,7 +123,7 @@ function Write-BuildMsg
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($AsError)
|
if($PSBoundParameters.ContainsKey("AsError"))
|
||||||
{
|
{
|
||||||
Write-Log -Message "ERROR: $message"
|
Write-Log -Message "ERROR: $message"
|
||||||
if (-not $Silent)
|
if (-not $Silent)
|
||||||
@ -137,8 +144,6 @@ function Write-BuildMsg
|
|||||||
function Start-OpenSSHBootstrap
|
function Start-OpenSSHBootstrap
|
||||||
{
|
{
|
||||||
[bool] $silent = -not $script:Verbose
|
[bool] $silent = -not $script:Verbose
|
||||||
|
|
||||||
Set-StrictMode -Version Latest
|
|
||||||
Write-BuildMsg -AsInfo -Message "Checking tools and dependencies" -Silent:$silent
|
Write-BuildMsg -AsInfo -Message "Checking tools and dependencies" -Silent:$silent
|
||||||
|
|
||||||
$machinePath = [Environment]::GetEnvironmentVariable('Path', 'MACHINE')
|
$machinePath = [Environment]::GetEnvironmentVariable('Path', 'MACHINE')
|
||||||
@ -146,7 +151,7 @@ function Start-OpenSSHBootstrap
|
|||||||
|
|
||||||
# Install chocolatey
|
# Install chocolatey
|
||||||
$chocolateyPath = "$env:AllUsersProfile\chocolatey\bin"
|
$chocolateyPath = "$env:AllUsersProfile\chocolatey\bin"
|
||||||
if(Get-Command "choco" -ErrorAction SilentlyContinue)
|
if(Get-Command choco -ErrorAction SilentlyContinue)
|
||||||
{
|
{
|
||||||
Write-BuildMsg -AsVerbose -Message "Chocolatey is already installed. Skipping installation." -Silent:$silent
|
Write-BuildMsg -AsVerbose -Message "Chocolatey is already installed. Skipping installation." -Silent:$silent
|
||||||
}
|
}
|
||||||
@ -156,12 +161,30 @@ function Start-OpenSSHBootstrap
|
|||||||
Invoke-Expression ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1')) 2>&1 >> $script:BuildLogFile
|
Invoke-Expression ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1')) 2>&1 >> $script:BuildLogFile
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (-not ($machinePath.ToLower().Contains($chocolateyPath.ToLower())))
|
||||||
|
{
|
||||||
|
Write-BuildMsg -AsVerbose -Message "Adding $chocolateyPath to Path environment variable" -Silent:$silent
|
||||||
|
$newMachineEnvironmentPath = "$chocolateyPath;$newMachineEnvironmentPath"
|
||||||
|
if(-not ($env:Path.ToLower().Contains($chocolateyPath.ToLower())))
|
||||||
|
{
|
||||||
|
$env:Path = "$chocolateyPath;$env:Path"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Write-BuildMsg -AsVerbose -Message "$chocolateyPath already present in Path environment variable" -Silent:$silent
|
||||||
|
}
|
||||||
|
|
||||||
# Add git\cmd to the path
|
# Add git\cmd to the path
|
||||||
$gitCmdPath = "$env:ProgramFiles\git\cmd"
|
$gitCmdPath = "$env:ProgramFiles\git\cmd"
|
||||||
if (-not ($machinePath.ToLower().Contains($gitCmdPath.ToLower())))
|
if (-not ($machinePath.ToLower().Contains($gitCmdPath.ToLower())))
|
||||||
{
|
{
|
||||||
Write-BuildMsg -AsVerbose -Message "Adding $gitCmdPath to Path environment variable" -Silent:$silent
|
Write-BuildMsg -AsVerbose -Message "Adding $gitCmdPath to Path environment variable" -Silent:$silent
|
||||||
$newMachineEnvironmentPath = "$gitCmdPath;$newMachineEnvironmentPath"
|
$newMachineEnvironmentPath = "$gitCmdPath;$newMachineEnvironmentPath"
|
||||||
|
if(-not ($env:Path.ToLower().Contains($gitCmdPath.ToLower())))
|
||||||
|
{
|
||||||
|
$env:Path = "$gitCmdPath;$env:Path"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -169,7 +192,7 @@ function Start-OpenSSHBootstrap
|
|||||||
}
|
}
|
||||||
|
|
||||||
$nativeMSBuildPath = "${env:ProgramFiles(x86)}\MSBuild\14.0\bin"
|
$nativeMSBuildPath = "${env:ProgramFiles(x86)}\MSBuild\14.0\bin"
|
||||||
if($script:platform -ieq "AMD64")
|
if($env:PROCESSOR_ARCHITECTURE -ieq "AMD64")
|
||||||
{
|
{
|
||||||
$nativeMSBuildPath += "\amd64"
|
$nativeMSBuildPath += "\amd64"
|
||||||
}
|
}
|
||||||
@ -178,7 +201,10 @@ function Start-OpenSSHBootstrap
|
|||||||
{
|
{
|
||||||
Write-BuildMsg -AsVerbose -Message "Adding $nativeMSBuildPath to Path environment variable" -Silent:$silent
|
Write-BuildMsg -AsVerbose -Message "Adding $nativeMSBuildPath to Path environment variable" -Silent:$silent
|
||||||
$newMachineEnvironmentPath += ";$nativeMSBuildPath"
|
$newMachineEnvironmentPath += ";$nativeMSBuildPath"
|
||||||
$env:Path += ";$nativeMSBuildPath"
|
if(-not ($env:Path.ToLower().Contains($nativeMSBuildPath.ToLower())))
|
||||||
|
{
|
||||||
|
$env:Path += ";$nativeMSBuildPath"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -191,42 +217,53 @@ function Start-OpenSSHBootstrap
|
|||||||
[Environment]::SetEnvironmentVariable('Path', $newMachineEnvironmentPath, 'MACHINE')
|
[Environment]::SetEnvironmentVariable('Path', $newMachineEnvironmentPath, 'MACHINE')
|
||||||
}
|
}
|
||||||
|
|
||||||
# Install Visual Studio 2015 Community
|
$VCTargetsPath = "${env:ProgramFiles(x86)}\MSBuild\Microsoft.Cpp\v4.0\V140"
|
||||||
$packageName = "VisualStudio2015Community"
|
if([Environment]::GetEnvironmentVariable('VCTargetsPath', 'MACHINE') -eq $null)
|
||||||
$VSPackageInstalled = Get-ItemProperty "HKLM:\software\WOW6432Node\Microsoft\VisualStudio\14.0\setup\vs" -ErrorAction SilentlyContinue
|
|
||||||
|
|
||||||
if ($null -eq $VSPackageInstalled)
|
|
||||||
{
|
{
|
||||||
Write-BuildMsg -AsInfo -Message "$packageName not present. Installing $packageName."
|
[Environment]::SetEnvironmentVariable('VCTargetsPath', $VCTargetsPath, 'MACHINE')
|
||||||
$adminFilePath = "$script:OpenSSHRoot\contrib\win32\openssh\VSWithBuildTools.xml"
|
|
||||||
choco install $packageName -packageParameters "--AdminFile $adminFilePath" -y --force --limitoutput --execution-timeout 10000 2>&1 >> $script:BuildLogFile
|
|
||||||
}
|
}
|
||||||
else
|
if ($env:VCTargetsPath -eq $null)
|
||||||
{
|
{
|
||||||
Write-BuildMsg -AsVerbose -Message "$packageName present. Skipping installation." -Silent:$silent
|
$env:VCTargetsPath = $VCTargetsPath
|
||||||
}
|
}
|
||||||
|
|
||||||
# Install Windows 8.1 SDK
|
$vcVars = "${env:ProgramFiles(x86)}\Microsoft Visual Studio 14.0\Common7\Tools\vsvars32.bat"
|
||||||
$packageName = "windows-sdk-8.1"
|
|
||||||
$sdkPath = "${env:ProgramFiles(x86)}\Windows Kits\8.1\bin\x86\register_app.vbs"
|
$sdkPath = "${env:ProgramFiles(x86)}\Windows Kits\8.1\bin\x86\register_app.vbs"
|
||||||
|
$packageName = "vcbuildtools"
|
||||||
if (-not (Test-Path -Path $sdkPath))
|
If ((-not (Test-Path $nativeMSBuildPath)) -or (-not (Test-Path $VcVars)) -or (-not (Test-Path $sdkPath))) {
|
||||||
{
|
Write-BuildMsg -AsInfo -Message "$packageName not present. Installing $packageName ..."
|
||||||
Write-BuildMsg -AsInfo -Message "Windows 8.1 SDK not present. Installing $packageName."
|
choco install $packageName -ia "/InstallSelectableItems VisualCppBuildTools_ATLMFC_SDK;VisualCppBuildTools_NETFX_SDK;Win81SDK_CppBuildSKUV1" -y --force --limitoutput --execution-timeout 10000 2>&1 >> $script:BuildLogFile
|
||||||
choco install $packageName -y --limitoutput --force 2>&1 >> $script:BuildLogFile
|
$errorCode = $LASTEXITCODE
|
||||||
|
if ($errorCode -eq 3010)
|
||||||
|
{
|
||||||
|
Write-Host "The recent package changes indicate a reboot is necessary. please reboot the machine, open a new powershell window and call Start-SSHBuild or Start-OpenSSHBootstrap again." -ForegroundColor Black -BackgroundColor Yellow
|
||||||
|
Do {
|
||||||
|
$input = Read-Host -Prompt "Reboot the machine? [Yes] Y; [No] N (default is `"Y`")"
|
||||||
|
if([string]::IsNullOrEmpty($input))
|
||||||
|
{
|
||||||
|
$input = 'Y'
|
||||||
|
}
|
||||||
|
} until ($input -match "^(y(es)?|N(o)?)$")
|
||||||
|
[string]$ret = $Matches[0]
|
||||||
|
if ($ret.ToLower().Startswith('y'))
|
||||||
|
{
|
||||||
|
Write-BuildMsg -AsWarning -Message "restarting machine ..."
|
||||||
|
Restart-Computer -Force
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Write-BuildMsg -AsError -ErrorAction Stop -Message "User choose not to restart the machine to apply the changes."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Write-BuildMsg -AsError -ErrorAction Stop -Message "$packageName installation failed with error code $errorCode"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Write-BuildMsg -AsInfo -Message "$packageName present. Skipping installation." -Silent:$silent
|
Write-BuildMsg -AsVerbose -Message 'VC++ 2015 Build Tools already present.'
|
||||||
}
|
|
||||||
|
|
||||||
# Require restarting PowerShell session
|
|
||||||
if ($null -eq $VSPackageInstalled)
|
|
||||||
{
|
|
||||||
Write-Host "To apply changes, please close this PowerShell window, open a new one and call Start-SSHBuild or Start-DscBootstrap again." -ForegroundColor Black -BackgroundColor Yellow
|
|
||||||
Write-Host -NoNewLine 'Press any key to close this PowerShell window...' -ForegroundColor Black -BackgroundColor Yellow
|
|
||||||
$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
|
|
||||||
exit
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Ensure the VS C toolset is installed
|
# Ensure the VS C toolset is installed
|
||||||
@ -241,11 +278,11 @@ function Start-OpenSSHBootstrap
|
|||||||
Write-BuildMsg -AsVerbose -Message "vcPath: $script:vcPath" -Silent:$silent
|
Write-BuildMsg -AsVerbose -Message "vcPath: $script:vcPath" -Silent:$silent
|
||||||
if ((Test-Path -Path "$script:vcPath\vcvarsall.bat") -eq $false)
|
if ((Test-Path -Path "$script:vcPath\vcvarsall.bat") -eq $false)
|
||||||
{
|
{
|
||||||
Write-BuildMsg -AsError -ErrorAction Stop -Message "Could not find Visual Studio vcvarsall.bat at$script:vcPath, which means some required develop kits are missing on the machine."
|
Write-BuildMsg -AsError -ErrorAction Stop -Message "Could not find Visual Studio vcvarsall.bat at $script:vcPath, which means some required develop kits are missing on the machine."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Clone-Win32OpenSSH
|
function Get-Win32OpenSSHRepo
|
||||||
{
|
{
|
||||||
[bool] $silent = -not $script:Verbose
|
[bool] $silent = -not $script:Verbose
|
||||||
|
|
||||||
@ -264,7 +301,7 @@ function Clone-Win32OpenSSH
|
|||||||
Pop-Location
|
Pop-Location
|
||||||
}
|
}
|
||||||
|
|
||||||
function Delete-Win32OpenSSH
|
function Remove-Win32OpenSSHRepo
|
||||||
{
|
{
|
||||||
Remove-Item -Path $script:win32OpenSSHPath -Recurse -Force -ErrorAction SilentlyContinue
|
Remove-Item -Path $script:win32OpenSSHPath -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
@ -282,7 +319,7 @@ function Copy-LibreSSLSDK
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Package-OpenSSH
|
function Start-OpenSSHPackage
|
||||||
{
|
{
|
||||||
[CmdletBinding(SupportsShouldProcess=$false)]
|
[CmdletBinding(SupportsShouldProcess=$false)]
|
||||||
param
|
param
|
||||||
@ -290,7 +327,7 @@ function Package-OpenSSH
|
|||||||
[ValidateSet('x86', 'x64')]
|
[ValidateSet('x86', 'x64')]
|
||||||
[string]$NativeHostArch = "x64",
|
[string]$NativeHostArch = "x64",
|
||||||
|
|
||||||
[ValidateSet('Debug', 'Release', '')]
|
[ValidateSet('Debug', 'Release')]
|
||||||
[string]$Configuration = "Release",
|
[string]$Configuration = "Release",
|
||||||
|
|
||||||
# Copy payload to DestinationPath instead of packaging
|
# Copy payload to DestinationPath instead of packaging
|
||||||
@ -315,7 +352,7 @@ function Package-OpenSSH
|
|||||||
if ($NativeHostArch -ieq 'x86') {
|
if ($NativeHostArch -ieq 'x86') {
|
||||||
$packageName = "OpenSSH-Win32"
|
$packageName = "OpenSSH-Win32"
|
||||||
}
|
}
|
||||||
while((($service = Get-Service ssh-agent -ErrorAction Ignore) -ne $null) -and ($service.Status -ine 'Stopped'))
|
while((($service = Get-Service ssh-agent -ErrorAction SilentlyContinue) -ne $null) -and ($service.Status -ine 'Stopped'))
|
||||||
{
|
{
|
||||||
Stop-Service ssh-agent -Force
|
Stop-Service ssh-agent -Force
|
||||||
#sleep to wait the servicelog file write
|
#sleep to wait the servicelog file write
|
||||||
@ -361,25 +398,38 @@ function Package-OpenSSH
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Remove-Item ($packageDir + '.zip') -Force -ErrorAction SilentlyContinue
|
Remove-Item ($packageDir + '.zip') -Force -ErrorAction SilentlyContinue
|
||||||
Compress-Archive -Path $packageDir -DestinationPath ($packageDir + '.zip')
|
if(get-command Compress-Archive -ErrorAction SilentlyContinue)
|
||||||
Write-BuildMsg -AsInfo -Message "Packaged Payload - '$packageDir'.zip"
|
{
|
||||||
|
Compress-Archive -Path $packageDir -DestinationPath ($packageDir + '.zip')
|
||||||
|
Write-BuildMsg -AsInfo -Message "Packaged Payload - '$packageDir.zip'"
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Write-BuildMsg -AsInfo -Message "Packaged Payload not compressed."
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Remove-Item $packageDir -Recurse -Force -ErrorAction SilentlyContinue
|
Remove-Item $packageDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
|
||||||
if ($DestinationPath -ne "") {
|
if ($DestinationPath -ne "") {
|
||||||
Copy-Item -Path $symbolsDir\* -Destination $DestinationPath -Force -Recurse
|
Copy-Item -Path $symbolsDir\* -Destination $DestinationPath -Force -Recurse
|
||||||
Write-BuildMsg -AsInfo -Message "Copied symbols to $DestinationPath"
|
Write-BuildMsg -AsInfo -Message "Copied symbols to $DestinationPath"
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Remove-Item ($symbolsDir + '.zip') -Force -ErrorAction SilentlyContinue
|
Remove-Item ($symbolsDir + '.zip') -Force -ErrorAction SilentlyContinue
|
||||||
Compress-Archive -Path $symbolsDir -DestinationPath ($symbolsDir + '.zip')
|
if(get-command Compress-Archive -ErrorAction SilentlyContinue)
|
||||||
Write-BuildMsg -AsInfo -Message "Packaged Symbols - '$symbolsDir'.zip"
|
{
|
||||||
|
Compress-Archive -Path $symbolsDir -DestinationPath ($symbolsDir + '.zip')
|
||||||
|
Write-BuildMsg -AsInfo -Message "Packaged Symbols - '$symbolsDir.zip'"
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Write-BuildMsg -AsInfo -Message "Packaged Symbols not compressed."
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Remove-Item $symbolsDir -Recurse -Force -ErrorAction SilentlyContinue
|
Remove-Item $symbolsDir -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
function Build-OpenSSH
|
function Start-OpenSSHBuild
|
||||||
{
|
{
|
||||||
[CmdletBinding(SupportsShouldProcess=$false)]
|
[CmdletBinding(SupportsShouldProcess=$false)]
|
||||||
param
|
param
|
||||||
@ -387,12 +437,11 @@ function Build-OpenSSH
|
|||||||
[ValidateSet('x86', 'x64')]
|
[ValidateSet('x86', 'x64')]
|
||||||
[string]$NativeHostArch = "x64",
|
[string]$NativeHostArch = "x64",
|
||||||
|
|
||||||
[ValidateSet('Debug', 'Release', '')]
|
[ValidateSet('Debug', 'Release')]
|
||||||
[string]$Configuration = "Release",
|
[string]$Configuration = "Release",
|
||||||
|
|
||||||
[switch]$NoOpenSSL
|
[switch]$NoOpenSSL
|
||||||
)
|
)
|
||||||
Set-StrictMode -Version Latest
|
|
||||||
$script:BuildLogFile = $null
|
$script:BuildLogFile = $null
|
||||||
|
|
||||||
[System.IO.DirectoryInfo] $repositoryRoot = Get-RepositoryRoot
|
[System.IO.DirectoryInfo] $repositoryRoot = Get-RepositoryRoot
|
||||||
@ -420,9 +469,9 @@ function Build-OpenSSH
|
|||||||
$script:win32OpenSSHPath = join-path $script:gitRoot "Win32-OpenSSH"
|
$script:win32OpenSSHPath = join-path $script:gitRoot "Win32-OpenSSH"
|
||||||
if (-not (Test-Path (Join-Path $PSScriptRoot LibreSSLSDK)))
|
if (-not (Test-Path (Join-Path $PSScriptRoot LibreSSLSDK)))
|
||||||
{
|
{
|
||||||
Clone-Win32OpenSSH
|
Get-Win32OpenSSHRepo
|
||||||
Copy-LibreSSLSDK
|
Copy-LibreSSLSDK
|
||||||
Delete-Win32OpenSSH
|
Remove-Win32OpenSSHRepo
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($NoOpenSSL)
|
if ($NoOpenSSL)
|
||||||
@ -465,7 +514,7 @@ function Get-BuildLogFile
|
|||||||
[ValidateSet('x86', 'x64')]
|
[ValidateSet('x86', 'x64')]
|
||||||
[string]$NativeHostArch = "x64",
|
[string]$NativeHostArch = "x64",
|
||||||
|
|
||||||
[ValidateSet('Debug', 'Release', '')]
|
[ValidateSet('Debug', 'Release')]
|
||||||
[string]$Configuration = "Release"
|
[string]$Configuration = "Release"
|
||||||
|
|
||||||
)
|
)
|
||||||
@ -483,122 +532,6 @@ function Get-SolutionFile
|
|||||||
return Join-Path -Path $root -ChildPath "contrib\win32\openssh\Win32-OpenSSH.sln"
|
return Join-Path -Path $root -ChildPath "contrib\win32\openssh\Win32-OpenSSH.sln"
|
||||||
}
|
}
|
||||||
|
|
||||||
<#
|
|
||||||
.Synopsis
|
|
||||||
Deploy all required files to a location and install the binaries
|
|
||||||
#>
|
|
||||||
function Install-OpenSSH
|
|
||||||
{
|
|
||||||
[CmdletBinding()]
|
|
||||||
param
|
|
||||||
(
|
|
||||||
[ValidateSet('Debug', 'Release', '')]
|
|
||||||
[string]$Configuration = "",
|
|
||||||
|
|
||||||
[ValidateSet('x86', 'x64', '')]
|
|
||||||
[string]$NativeHostArch = "",
|
|
||||||
|
|
||||||
[string]$OpenSSHDir = "$env:SystemDrive\OpenSSH"
|
Export-ModuleMember -Function Start-OpenSSHBuild, Get-BuildLogFile, Start-OpenSSHPackage
|
||||||
)
|
|
||||||
|
|
||||||
if ($Configuration -eq "")
|
|
||||||
{
|
|
||||||
$Configuration = 'Release'
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($NativeHostArch -eq "")
|
|
||||||
{
|
|
||||||
$NativeHostArch = 'x64'
|
|
||||||
if ($env:PROCESSOR_ARCHITECTURE -eq 'x86') {
|
|
||||||
$NativeHostArch = 'x86'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Package-OpenSSH -NativeHostArch $NativeHostArch -Configuration $Configuration -DestinationPath $OpenSSHDir
|
|
||||||
|
|
||||||
Push-Location $OpenSSHDir
|
|
||||||
& "$OpenSSHDir\install-sshd.ps1"
|
|
||||||
& "$OpenSSHDir\ssh-keygen.exe" -A
|
|
||||||
|
|
||||||
$keyFiles = Get-ChildItem "$OpenSSHDir\ssh_host_*_key*" | % {
|
|
||||||
Adjust-HostKeyFileACL -FilePath $_.FullName
|
|
||||||
}
|
|
||||||
|
|
||||||
#machine will be reboot after Install-openssh anyway
|
|
||||||
$machinePath = [Environment]::GetEnvironmentVariable('Path', 'MACHINE')
|
|
||||||
$newMachineEnvironmentPath = $machinePath
|
|
||||||
if (-not ($machinePath.ToLower().Contains($OpenSSHDir.ToLower())))
|
|
||||||
{
|
|
||||||
$newMachineEnvironmentPath = "$OpenSSHDir;$newMachineEnvironmentPath"
|
|
||||||
$env:Path = "$OpenSSHDir;$env:Path"
|
|
||||||
}
|
|
||||||
# Update machine environment path
|
|
||||||
if ($newMachineEnvironmentPath -ne $machinePath)
|
|
||||||
{
|
|
||||||
[Environment]::SetEnvironmentVariable('Path', $newMachineEnvironmentPath, 'MACHINE')
|
|
||||||
}
|
|
||||||
|
|
||||||
Set-Service sshd -StartupType Automatic
|
|
||||||
Set-Service ssh-agent -StartupType Automatic
|
|
||||||
|
|
||||||
Pop-Location
|
|
||||||
Write-Log -Message "OpenSSH installed!"
|
|
||||||
}
|
|
||||||
|
|
||||||
<#
|
|
||||||
.Synopsis
|
|
||||||
uninstalled sshd and sshla
|
|
||||||
#>
|
|
||||||
function UnInstall-OpenSSH
|
|
||||||
{
|
|
||||||
[CmdletBinding()]
|
|
||||||
param
|
|
||||||
(
|
|
||||||
[string]$OpenSSHDir = "$env:SystemDrive\OpenSSH"
|
|
||||||
)
|
|
||||||
|
|
||||||
if (-not (Test-Path $OpenSSHDir))
|
|
||||||
{
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
Push-Location $OpenSSHDir
|
|
||||||
if((Get-Service ssh-agent -ErrorAction Ignore) -ne $null) {
|
|
||||||
Stop-Service ssh-agent -Force
|
|
||||||
}
|
|
||||||
&( "$OpenSSHDir\uninstall-sshd.ps1")
|
|
||||||
|
|
||||||
$machinePath = [Environment]::GetEnvironmentVariable('Path', 'MACHINE')
|
|
||||||
$newMachineEnvironmentPath = $machinePath
|
|
||||||
if ($machinePath.ToLower().Contains($OpenSSHDir.ToLower()))
|
|
||||||
{
|
|
||||||
$newMachineEnvironmentPath = $newMachineEnvironmentPath.Replace("$OpenSSHDir;", '')
|
|
||||||
$env:Path = $env:Path.Replace("$OpenSSHDir;", '')
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Test-Path -Path $OpenSSHDir)
|
|
||||||
{
|
|
||||||
Push-Location $OpenSSHDir
|
|
||||||
&( "$OpenSSHDir\uninstall-sshd.ps1")
|
|
||||||
|
|
||||||
$machinePath = [Environment]::GetEnvironmentVariable('Path', 'MACHINE')
|
|
||||||
$newMachineEnvironmentPath = $machinePath
|
|
||||||
if ($machinePath.ToLower().Contains($OpenSSHDir.ToLower()))
|
|
||||||
{
|
|
||||||
$newMachineEnvironmentPath.Replace("$OpenSSHDir;", '')
|
|
||||||
$env:Path = $env:Path.Replace("$OpenSSHDir;", '')
|
|
||||||
}
|
|
||||||
|
|
||||||
# Update machine environment path
|
|
||||||
# machine will be reboot after Uninstall-OpenSSH
|
|
||||||
if ($newMachineEnvironmentPath -ne $machinePath)
|
|
||||||
{
|
|
||||||
[Environment]::SetEnvironmentVariable('Path', $newMachineEnvironmentPath, 'MACHINE')
|
|
||||||
}
|
|
||||||
Pop-Location
|
|
||||||
|
|
||||||
Remove-Item -Path $OpenSSHDir -Recurse -Force -ErrorAction SilentlyContinue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Export-ModuleMember -Function Build-OpenSSH, Get-BuildLogFile, Install-OpenSSH, UnInstall-OpenSSH, Package-OpenSSH
|
|
||||||
|
@ -1,20 +1,18 @@
|
|||||||
<#
|
If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
|
||||||
|
Import-Module $PSScriptRoot\OpenSSHUtils -Force
|
||||||
|
<#
|
||||||
.Synopsis
|
.Synopsis
|
||||||
Finds the root of the git repository
|
Finds the root of the git repository
|
||||||
|
|
||||||
.Outputs
|
.Outputs
|
||||||
A System.IO.DirectoryInfo for the location of the root.
|
A System.IO.DirectoryInfo for the location of the root if root is found; otherwise, script root.
|
||||||
|
|
||||||
.Inputs
|
.Inputs
|
||||||
None
|
None
|
||||||
|
|
||||||
.Notes
|
|
||||||
FileNotFoundException is thrown if the current directory does not contain a CMakeLists.txt file.
|
|
||||||
#>
|
#>
|
||||||
function Get-RepositoryRoot
|
function Get-RepositoryRoot
|
||||||
{
|
{
|
||||||
$currentDir = (Get-Item -Path $PSCommandPath).Directory
|
$start = $currentDir = (Get-Item -Path $PSScriptRoot)
|
||||||
|
|
||||||
while ($null -ne $currentDir.Parent)
|
while ($null -ne $currentDir.Parent)
|
||||||
{
|
{
|
||||||
$path = Join-Path -Path $currentDir.FullName -ChildPath '.git'
|
$path = Join-Path -Path $currentDir.FullName -ChildPath '.git'
|
||||||
@ -24,147 +22,7 @@ function Get-RepositoryRoot
|
|||||||
}
|
}
|
||||||
$currentDir = $currentDir.Parent
|
$currentDir = $currentDir.Parent
|
||||||
}
|
}
|
||||||
|
return $start
|
||||||
throw new-object System.IO.DirectoryNotFoundException("Could not find the root of the GIT repository")
|
|
||||||
}
|
|
||||||
|
|
||||||
<#
|
|
||||||
.Synopsis
|
|
||||||
Set owner of the file to by LOCALSYSTEM account
|
|
||||||
Set private host key be fully controlled by LOCALSYSTEM and Administrators
|
|
||||||
Set public host key be fully controlled by LOCALSYSTEM and Administrators, read access by everyone
|
|
||||||
|
|
||||||
.Outputs
|
|
||||||
N/A
|
|
||||||
|
|
||||||
.Inputs
|
|
||||||
FilePath - The path to the file
|
|
||||||
#>
|
|
||||||
function Adjust-HostKeyFileACL
|
|
||||||
{
|
|
||||||
param (
|
|
||||||
[parameter(Mandatory=$true)]
|
|
||||||
[string]$FilePath
|
|
||||||
)
|
|
||||||
|
|
||||||
$myACL = Get-ACL $FilePath
|
|
||||||
$myACL.SetAccessRuleProtection($True, $FALSE)
|
|
||||||
Set-Acl -Path $FilePath -AclObject $myACL
|
|
||||||
|
|
||||||
$systemAccount = New-Object System.Security.Principal.NTAccount("NT AUTHORITY", "SYSTEM")
|
|
||||||
$adminAccount = New-Object System.Security.Principal.NTAccount("BUILTIN","Administrators")
|
|
||||||
$everyoneAccount = New-Object System.Security.Principal.NTAccount("EveryOne")
|
|
||||||
$myACL = Get-ACL $FilePath
|
|
||||||
|
|
||||||
$myACL.SetOwner($systemAccount)
|
|
||||||
|
|
||||||
if($myACL.Access)
|
|
||||||
{
|
|
||||||
$myACL.Access | % {
|
|
||||||
if(-not ($myACL.RemoveAccessRule($_)))
|
|
||||||
{
|
|
||||||
throw "failed to remove access of $($_.IdentityReference.Value) rule in setup "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$adminACE = New-Object System.Security.AccessControl.FileSystemAccessRule `
|
|
||||||
($adminAccount, "FullControl", "None", "None", "Allow")
|
|
||||||
$myACL.AddAccessRule($adminACE)
|
|
||||||
|
|
||||||
$systemACE = New-Object System.Security.AccessControl.FileSystemAccessRule `
|
|
||||||
($systemAccount, "FullControl", "None", "None", "Allow")
|
|
||||||
$myACL.AddAccessRule($systemACE)
|
|
||||||
|
|
||||||
if($FilePath.EndsWith(".pub"))
|
|
||||||
{
|
|
||||||
$everyoneAce = New-Object System.Security.AccessControl.FileSystemAccessRule `
|
|
||||||
("Everyone", "Read", "None", "None", "Allow")
|
|
||||||
$myACL.AddAccessRule($everyoneAce)
|
|
||||||
}
|
|
||||||
|
|
||||||
Set-Acl -Path $FilePath -AclObject $myACL
|
|
||||||
}
|
|
||||||
|
|
||||||
<#
|
|
||||||
.Synopsis
|
|
||||||
Set owner of the user key file
|
|
||||||
Set ACL to have private user key be fully controlled by LOCALSYSTEM and Administrators, Read, write access by owner
|
|
||||||
Set public user key be fully controlled by LOCALSYSTEM and Administrators, Read, write access by owner, read access by everyone
|
|
||||||
|
|
||||||
.Outputs
|
|
||||||
N/A
|
|
||||||
|
|
||||||
.Inputs
|
|
||||||
FilePath - The path to the file
|
|
||||||
Owner - owner of the file
|
|
||||||
OwnerPerms - the permissions grant to the owner
|
|
||||||
#>
|
|
||||||
function Adjust-UserKeyFileACL
|
|
||||||
{
|
|
||||||
param (
|
|
||||||
[parameter(Mandatory=$true)]
|
|
||||||
[string]$FilePath,
|
|
||||||
[System.Security.Principal.NTAccount] $Owner = $null,
|
|
||||||
[System.Security.AccessControl.FileSystemRights[]] $OwnerPerms = $null
|
|
||||||
)
|
|
||||||
|
|
||||||
$myACL = Get-ACL $FilePath
|
|
||||||
$myACL.SetAccessRuleProtection($True, $FALSE)
|
|
||||||
Set-Acl -Path $FilePath -AclObject $myACL
|
|
||||||
|
|
||||||
$systemAccount = New-Object System.Security.Principal.NTAccount("NT AUTHORITY", "SYSTEM")
|
|
||||||
$adminAccount = New-Object System.Security.Principal.NTAccount("BUILTIN","Administrators")
|
|
||||||
$everyoneAccount = New-Object System.Security.Principal.NTAccount("EveryOne")
|
|
||||||
$myACL = Get-ACL $FilePath
|
|
||||||
|
|
||||||
$actualOwner = $null
|
|
||||||
if($Owner -eq $null)
|
|
||||||
{
|
|
||||||
$actualOwner = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME))
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$actualOwner = $Owner
|
|
||||||
}
|
|
||||||
|
|
||||||
$myACL.SetOwner($actualOwner)
|
|
||||||
|
|
||||||
if($myACL.Access)
|
|
||||||
{
|
|
||||||
$myACL.Access | % {
|
|
||||||
if(-not ($myACL.RemoveAccessRule($_)))
|
|
||||||
{
|
|
||||||
throw "failed to remove access of $($_.IdentityReference.Value) rule in setup "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$adminACE = New-Object System.Security.AccessControl.FileSystemAccessRule `
|
|
||||||
($adminAccount, "FullControl", "None", "None", "Allow")
|
|
||||||
$myACL.AddAccessRule($adminACE)
|
|
||||||
|
|
||||||
$systemACE = New-Object System.Security.AccessControl.FileSystemAccessRule `
|
|
||||||
($systemAccount, "FullControl", "None", "None", "Allow")
|
|
||||||
$myACL.AddAccessRule($systemACE)
|
|
||||||
|
|
||||||
if($OwnerPerms)
|
|
||||||
{
|
|
||||||
$OwnerPerms | % {
|
|
||||||
$ownerACE = New-Object System.Security.AccessControl.FileSystemAccessRule `
|
|
||||||
($actualOwner, $_, "None", "None", "Allow")
|
|
||||||
$myACL.AddAccessRule($ownerACE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if($FilePath.EndsWith(".pub"))
|
|
||||||
{
|
|
||||||
$everyoneAce = New-Object System.Security.AccessControl.FileSystemAccessRule `
|
|
||||||
("Everyone", "Read", "None", "None", "Allow")
|
|
||||||
$myACL.AddAccessRule($everyoneAce)
|
|
||||||
}
|
|
||||||
|
|
||||||
Set-Acl -Path $FilePath -AclObject $myACL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
<#
|
<#
|
||||||
@ -177,7 +35,7 @@ function Adjust-UserKeyFileACL
|
|||||||
.Inputs
|
.Inputs
|
||||||
FilePath - The path to the file
|
FilePath - The path to the file
|
||||||
User - account name
|
User - account name
|
||||||
Perm - The permission to grant.
|
Perms - The permission to grant.
|
||||||
#>
|
#>
|
||||||
function Add-PermissionToFileACL
|
function Add-PermissionToFileACL
|
||||||
{
|
{
|
||||||
@ -200,8 +58,8 @@ function Add-PermissionToFileACL
|
|||||||
$myACL.AddAccessRule($userACE)
|
$myACL.AddAccessRule($userACE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Enable-Privilege SeRestorePrivilege | out-null
|
||||||
Set-Acl -Path $FilePath -AclObject $myACL
|
Set-Acl -Path $FilePath -AclObject $myACL
|
||||||
}
|
}
|
||||||
|
|
||||||
Export-ModuleMember -Function Get-RepositoryRoot, Add-PermissionToFileACL, Adjust-HostKeyFileACL, Adjust-UserKeyFileACL
|
Export-ModuleMember -Function Get-RepositoryRoot, Add-PermissionToFileACL
|
@ -1,5 +1,7 @@
|
|||||||
$ErrorActionPreference = 'Stop'
|
$ErrorActionPreference = 'Stop'
|
||||||
Import-Module $PSScriptRoot\OpenSSHCommonUtils.psm1 -DisableNameChecking -Force
|
If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
|
||||||
|
Import-Module $PSScriptRoot\OpenSSHCommonUtils.psm1 -Force
|
||||||
|
Import-Module $PSScriptRoot\OpenSSHUtils -Force
|
||||||
|
|
||||||
[System.IO.DirectoryInfo] $repositoryRoot = Get-RepositoryRoot
|
[System.IO.DirectoryInfo] $repositoryRoot = Get-RepositoryRoot
|
||||||
# test environment parameters initialized with defaults
|
# test environment parameters initialized with defaults
|
||||||
@ -17,23 +19,28 @@ $Script:E2ETestResultsFile = Join-Path $TestDataPath $E2ETestResultsFileName
|
|||||||
$Script:UnitTestResultsFile = Join-Path $TestDataPath $UnitTestResultsFileName
|
$Script:UnitTestResultsFile = Join-Path $TestDataPath $UnitTestResultsFileName
|
||||||
$Script:TestSetupLogFile = Join-Path $TestDataPath $TestSetupLogFileName
|
$Script:TestSetupLogFile = Join-Path $TestDataPath $TestSetupLogFileName
|
||||||
$Script:E2ETestDirectory = Join-Path $repositoryRoot.FullName -ChildPath "regress\pesterTests"
|
$Script:E2ETestDirectory = Join-Path $repositoryRoot.FullName -ChildPath "regress\pesterTests"
|
||||||
|
$Script:WindowsInBox = $false
|
||||||
|
|
||||||
<#
|
<#
|
||||||
.Synopsis
|
.Synopsis
|
||||||
Setup-OpenSSHTestEnvironment
|
Set-OpenSSHTestEnvironment
|
||||||
TODO - split these steps into client and server side
|
TODO - split these steps into client and server side
|
||||||
#>
|
#>
|
||||||
function Setup-OpenSSHTestEnvironment
|
function Set-OpenSSHTestEnvironment
|
||||||
{
|
{
|
||||||
[CmdletBinding()]
|
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
|
||||||
param
|
param
|
||||||
(
|
(
|
||||||
[switch] $Quiet,
|
|
||||||
[string] $OpenSSHBinPath,
|
[string] $OpenSSHBinPath,
|
||||||
[string] $TestDataPath = "$env:SystemDrive\OpenSSHTests",
|
[string] $TestDataPath = "$env:SystemDrive\OpenSSHTests",
|
||||||
[Boolean] $DebugMode = $false
|
[Boolean] $DebugMode = $false
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if($PSBoundParameters.ContainsKey("Verbose"))
|
||||||
|
{
|
||||||
|
$verboseInfo = ($PSBoundParameters['Verbose']).IsPresent
|
||||||
|
}
|
||||||
|
|
||||||
if($Global:OpenSSHTestInfo -ne $null)
|
if($Global:OpenSSHTestInfo -ne $null)
|
||||||
{
|
{
|
||||||
$Global:OpenSSHTestInfo.Clear()
|
$Global:OpenSSHTestInfo.Clear()
|
||||||
@ -65,41 +72,30 @@ function Setup-OpenSSHTestEnvironment
|
|||||||
#if user does not set path, pick it up
|
#if user does not set path, pick it up
|
||||||
if([string]::IsNullOrEmpty($OpenSSHBinPath))
|
if([string]::IsNullOrEmpty($OpenSSHBinPath))
|
||||||
{
|
{
|
||||||
$sshcmd = get-command ssh.exe -ErrorAction Ignore
|
$sshcmd = get-command ssh.exe -ErrorAction SilentlyContinue
|
||||||
if($sshcmd -eq $null)
|
if($sshcmd -eq $null)
|
||||||
{
|
{
|
||||||
Throw "Cannot find ssh.exe. Please specify -OpenSSHBinPath to the OpenSSH installed location."
|
Throw "Cannot find ssh.exe. Please specify -OpenSSHBinPath to the OpenSSH installed location."
|
||||||
}
|
}
|
||||||
elseif($Quiet)
|
|
||||||
{
|
|
||||||
$dirToCheck = split-path $sshcmd.Path
|
|
||||||
$script:OpenSSHBinPath = $dirToCheck
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$dirToCheck = split-path $sshcmd.Path
|
$dirToCheck = split-path $sshcmd.Path
|
||||||
$message = "Do you want to test openssh installed at $($dirToCheck)? [Yes] Y; [No] N (default is `"Y`")"
|
$description = "Pick up ssh.exe from $dirToCheck."
|
||||||
$response = Read-Host -Prompt $message
|
$prompt = "Are you sure you want to pick up ssh.exe from $($dirToCheck)?"
|
||||||
if( ($response -eq "") -or ($response -ieq "Y") -or ($response -ieq "Yes") )
|
$caption = "Found ssh.exe from $dirToCheck"
|
||||||
{
|
if(-not $pscmdlet.ShouldProcess($description, $prompt, $caption))
|
||||||
$script:OpenSSHBinPath = $dirToCheck
|
|
||||||
}
|
|
||||||
elseif( ($response -ieq "N") -or ($response -ieq "No") )
|
|
||||||
{
|
{
|
||||||
Write-Host "User decided not to pick up ssh.exe from $dirToCheck. Please specify -OpenSSHBinPath to the OpenSSH installed location."
|
Write-Host "User decided not to pick up ssh.exe from $dirToCheck. Please specify -OpenSSHBinPath to the OpenSSH installed location."
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
else
|
$script:OpenSSHBinPath = $dirToCheck
|
||||||
{
|
|
||||||
Throw "User entered invalid option ($response). Please specify -OpenSSHBinPath to the OpenSSH installed location"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (-not (Test-Path (Join-Path $OpenSSHBinPath ssh.exe) -PathType Leaf))
|
if (-not (Test-Path (Join-Path $OpenSSHBinPath ssh.exe) -PathType Leaf))
|
||||||
{
|
{
|
||||||
Throw "Cannot find OpenSSH binaries under $OpenSSHBinPath. Please specify -OpenSSHBinPathto the OpenSSH installed location"
|
Throw "Cannot find OpenSSH binaries under $OpenSSHBinPath. Please specify -OpenSSHBinPath to the OpenSSH installed location"
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -113,7 +109,15 @@ function Setup-OpenSSHTestEnvironment
|
|||||||
$env:Path = "$($script:OpenSSHBinPath);$($env:path)"
|
$env:Path = "$($script:OpenSSHBinPath);$($env:path)"
|
||||||
}
|
}
|
||||||
|
|
||||||
$warning = @"
|
$acl = get-acl (join-path $script:OpenSSHBinPath "ssh.exe")
|
||||||
|
|
||||||
|
if($acl.Owner -ieq "NT SERVICE\TrustedInstaller")
|
||||||
|
{
|
||||||
|
$Script:WindowsInBox = $true
|
||||||
|
$Global:OpenSSHTestInfo.Add("WindowsInBox", $true)
|
||||||
|
}
|
||||||
|
|
||||||
|
$description = @"
|
||||||
WARNING: Following changes will be made to OpenSSH configuration
|
WARNING: Following changes will be made to OpenSSH configuration
|
||||||
- sshd_config will be backed up as sshd_config.ori
|
- sshd_config will be backed up as sshd_config.ori
|
||||||
- will be replaced with a test sshd_config
|
- will be replaced with a test sshd_config
|
||||||
@ -125,21 +129,15 @@ WARNING: Following changes will be made to OpenSSH configuration
|
|||||||
- $HOME\.ssh\known_hosts will be modified with test host key entry
|
- $HOME\.ssh\known_hosts will be modified with test host key entry
|
||||||
- test accounts - ssouser, pubkeyuser, and passwduser will be added
|
- test accounts - ssouser, pubkeyuser, and passwduser will be added
|
||||||
- Setup single signon for ssouser
|
- Setup single signon for ssouser
|
||||||
- To cleanup - Run Cleanup-OpenSSHTestEnvironment
|
- To cleanup - Run Clear-OpenSSHTestEnvironment
|
||||||
"@
|
"@
|
||||||
|
|
||||||
if (-not $Quiet) {
|
$prompt = "Are you sure you want to perform the above operations?"
|
||||||
Write-Warning $warning
|
$caption = $description
|
||||||
$continue = Read-Host -Prompt "Do you want to continue with the above changes? [Yes] Y; [No] N (default is `"Y`")"
|
if(-not $pscmdlet.ShouldProcess($description, $prompt, $caption))
|
||||||
if( ($continue -ieq "N") -or ($continue -ieq "No") )
|
{
|
||||||
{
|
Write-Host "User decided not to make the changes."
|
||||||
Write-Host "User decided not to make the changes."
|
return
|
||||||
return
|
|
||||||
}
|
|
||||||
elseif(($continue -ne "") -and ($continue -ine "Y") -and ($continue -ine "Yes"))
|
|
||||||
{
|
|
||||||
Throw "User entered invalid option ($continue). Exit now."
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Install-OpenSSHTestDependencies
|
Install-OpenSSHTestDependencies
|
||||||
@ -154,9 +152,15 @@ WARNING: Following changes will be made to OpenSSH configuration
|
|||||||
if (-not (Test-Path $backupConfigPath -PathType Leaf)) {
|
if (-not (Test-Path $backupConfigPath -PathType Leaf)) {
|
||||||
Copy-Item (Join-Path $script:OpenSSHBinPath sshd_config) $backupConfigPath -Force
|
Copy-Item (Join-Path $script:OpenSSHBinPath sshd_config) $backupConfigPath -Force
|
||||||
}
|
}
|
||||||
|
$targetsshdConfig = Join-Path $script:OpenSSHBinPath sshd_config
|
||||||
# copy new sshd_config
|
# copy new sshd_config
|
||||||
Copy-Item (Join-Path $Script:E2ETestDirectory sshd_config) (Join-Path $script:OpenSSHBinPath sshd_config) -Force
|
if($Script:WindowsInBox -and (Test-Path $targetsshdConfig))
|
||||||
|
{
|
||||||
|
$currentUser = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME))
|
||||||
|
Add-PermissionToFileACL -FilePath $targetsshdConfig -User $currentUser -Perm "Read,Write"
|
||||||
|
}
|
||||||
|
|
||||||
|
Copy-Item (Join-Path $Script:E2ETestDirectory sshd_config) $targetsshdConfig -Force
|
||||||
|
|
||||||
Start-Service ssh-agent
|
Start-Service ssh-agent
|
||||||
|
|
||||||
@ -164,11 +168,17 @@ WARNING: Following changes will be made to OpenSSH configuration
|
|||||||
Copy-Item "$($Script:E2ETestDirectory)\sshtest*hostkey*" $script:OpenSSHBinPath -Force
|
Copy-Item "$($Script:E2ETestDirectory)\sshtest*hostkey*" $script:OpenSSHBinPath -Force
|
||||||
Get-ChildItem "$($script:OpenSSHBinPath)\sshtest*hostkey*"| % {
|
Get-ChildItem "$($script:OpenSSHBinPath)\sshtest*hostkey*"| % {
|
||||||
#workaround for the cariggage new line added by git before copy them
|
#workaround for the cariggage new line added by git before copy them
|
||||||
(Get-Content $_.FullName -Raw).Replace("`r`n","`n") | Set-Content $_.FullName -Force
|
$filePath = "$($_.FullName)"
|
||||||
Adjust-HostKeyFileACL -FilePath $_.FullName
|
$con = (Get-Content $filePath | Out-String).Replace("`r`n","`n")
|
||||||
if (-not ($_.Name.EndsWith(".pub"))) {
|
Set-Content -Path $filePath -Value "$con"
|
||||||
#register private key with agent
|
if (-not ($_.Name.EndsWith(".pub")))
|
||||||
ssh-add-hostkey.ps1 $_.FullName
|
{
|
||||||
|
Repair-SshdHostKeyPermission -FilePath $_.FullName -confirm:$false
|
||||||
|
if($psversiontable.BuildVersion.Major -gt 6)
|
||||||
|
{
|
||||||
|
#register private key with agent
|
||||||
|
ssh-add-hostkey.ps1 $_.FullName
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,7 +202,7 @@ WARNING: Following changes will be made to OpenSSH configuration
|
|||||||
Copy-Item $sshConfigFilePath (Join-Path $dotSshDirectoryPath config.ori) -Force
|
Copy-Item $sshConfigFilePath (Join-Path $dotSshDirectoryPath config.ori) -Force
|
||||||
}
|
}
|
||||||
Copy-Item (Join-Path $Script:E2ETestDirectory ssh_config) $sshConfigFilePath -Force
|
Copy-Item (Join-Path $Script:E2ETestDirectory ssh_config) $sshConfigFilePath -Force
|
||||||
Adjust-UserKeyFileACL -FilePath $sshConfigFilePath -OwnerPerms "Read,Write"
|
Repair-UserSshConfigPermission -FilePath $sshConfigFilePath -confirm:$false
|
||||||
|
|
||||||
# create test accounts
|
# create test accounts
|
||||||
#TODO - this is Windows specific. Need to be in PAL
|
#TODO - this is Windows specific. Need to be in PAL
|
||||||
@ -219,12 +229,13 @@ WARNING: Following changes will be made to OpenSSH configuration
|
|||||||
$authorizedKeyPath = Join-Path $ssouserProfile .ssh\authorized_keys
|
$authorizedKeyPath = Join-Path $ssouserProfile .ssh\authorized_keys
|
||||||
$testPubKeyPath = Join-Path $Script:E2ETestDirectory sshtest_userssokey_ed25519.pub
|
$testPubKeyPath = Join-Path $Script:E2ETestDirectory sshtest_userssokey_ed25519.pub
|
||||||
Copy-Item $testPubKeyPath $authorizedKeyPath -Force -ErrorAction SilentlyContinue
|
Copy-Item $testPubKeyPath $authorizedKeyPath -Force -ErrorAction SilentlyContinue
|
||||||
$owner = New-Object System.Security.Principal.NTAccount($SSOUser)
|
Repair-AuthorizedKeyPermission -FilePath $authorizedKeyPath -confirm:$false
|
||||||
Adjust-UserKeyFileACL -FilePath $authorizedKeyPath -Owner $owner -OwnerPerms "Read","Write"
|
|
||||||
Add-PermissionToFileACL -FilePath $authorizedKeyPath -User "NT Service\sshd" -Perm "Read"
|
|
||||||
$testPriKeypath = Join-Path $Script:E2ETestDirectory sshtest_userssokey_ed25519
|
$testPriKeypath = Join-Path $Script:E2ETestDirectory sshtest_userssokey_ed25519
|
||||||
(Get-Content $testPriKeypath -Raw).Replace("`r`n","`n") | Set-Content $testPriKeypath -Force
|
$con = (Get-Content $testPriKeypath | Out-String).Replace("`r`n","`n")
|
||||||
Adjust-UserKeyFileACL -FilePath $testPriKeypath -OwnerPerms "Read, Write"
|
Set-Content -Path $testPriKeypath -Value "$con"
|
||||||
|
cmd /c "ssh-add -D 2>&1 >> $Script:TestSetupLogFile"
|
||||||
|
Repair-UserKeyPermission -FilePath $testPriKeypath -confirm:$false
|
||||||
cmd /c "ssh-add $testPriKeypath 2>&1 >> $Script:TestSetupLogFile"
|
cmd /c "ssh-add $testPriKeypath 2>&1 >> $Script:TestSetupLogFile"
|
||||||
Backup-OpenSSHTestInfo
|
Backup-OpenSSHTestInfo
|
||||||
}
|
}
|
||||||
@ -257,6 +268,19 @@ function Install-OpenSSHTestDependencies
|
|||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param ()
|
param ()
|
||||||
|
|
||||||
|
#$isOpenSSHUtilsAvailable = Get-Module 'OpenSSHUtils' -ListAvailable
|
||||||
|
#if (-not ($isOpenSSHUtilsAvailable))
|
||||||
|
#{
|
||||||
|
Write-Log -Message "Installing Module OpenSSHUtils..."
|
||||||
|
Install-OpenSSHUtilsModule -SourceDir $PSScriptRoot
|
||||||
|
#}
|
||||||
|
Import-Module OpensshUtils -Force
|
||||||
|
|
||||||
|
if($Script:WindowsInBox)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
# Install chocolatey
|
# Install chocolatey
|
||||||
if(-not (Get-Command "choco" -ErrorAction SilentlyContinue))
|
if(-not (Get-Command "choco" -ErrorAction SilentlyContinue))
|
||||||
{
|
{
|
||||||
@ -267,10 +291,66 @@ function Install-OpenSSHTestDependencies
|
|||||||
$isModuleAvailable = Get-Module 'Pester' -ListAvailable
|
$isModuleAvailable = Get-Module 'Pester' -ListAvailable
|
||||||
if (-not ($isModuleAvailable))
|
if (-not ($isModuleAvailable))
|
||||||
{
|
{
|
||||||
Write-Log -Message "Installing Pester..."
|
Write-Log -Message "Installing Pester..."
|
||||||
choco install Pester -y --force --limitoutput 2>&1 >> $Script:TestSetupLogFile
|
choco install Pester -y --force --limitoutput 2>&1 >> $Script:TestSetupLogFile
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Install-OpenSSHUtilsModule
|
||||||
|
{
|
||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[string]$TargetDir = (Join-Path -Path $env:ProgramFiles -ChildPath "WindowsPowerShell\Modules\OpenSSHUtils"),
|
||||||
|
[string]$SourceDir)
|
||||||
|
|
||||||
|
$manifestFile = Join-Path -Path $SourceDir -ChildPath OpenSSHUtils.psd1
|
||||||
|
$moduleFile = Join-Path -Path $SourceDir -ChildPath OpenSSHUtils.psm1
|
||||||
|
$targetDirectory = $TargetDir
|
||||||
|
$manifest = Test-ModuleManifest -Path $manifestFile -WarningAction SilentlyContinue -ErrorAction Stop
|
||||||
|
if ($PSVersionTable.PSVersion.Major -ge 5)
|
||||||
|
{
|
||||||
|
$targetDirectory = Join-Path -Path $targetDir -ChildPath $manifest.Version.ToString()
|
||||||
|
}
|
||||||
|
|
||||||
|
$modulePath = Join-Path -Path $env:ProgramFiles -ChildPath WindowsPowerShell\Modules
|
||||||
|
if(-not (Test-Path $targetDirectory -PathType Container))
|
||||||
|
{
|
||||||
|
New-Item -ItemType Directory -Path $targetDirectory -Force -ErrorAction SilentlyContinue | out-null
|
||||||
|
}
|
||||||
|
Copy-item $manifestFile -Destination $targetDirectory -Force -ErrorAction SilentlyContinue | out-null
|
||||||
|
Copy-item $moduleFile -Destination $targetDirectory -Force -ErrorAction SilentlyContinue | out-null
|
||||||
|
|
||||||
|
if ($PSVersionTable.PSVersion.Major -lt 4)
|
||||||
|
{
|
||||||
|
$modulePaths = [Environment]::GetEnvironmentVariable('PSModulePath', 'Machine') -split ';'
|
||||||
|
if ($modulePaths -notcontains $modulePath)
|
||||||
|
{
|
||||||
|
Write-Verbose -Message "Adding '$modulePath' to PSModulePath."
|
||||||
|
|
||||||
|
$modulePaths = @(
|
||||||
|
$modulePath
|
||||||
|
$modulePaths
|
||||||
|
)
|
||||||
|
|
||||||
|
$newModulePath = $modulePaths -join ';'
|
||||||
|
|
||||||
|
[Environment]::SetEnvironmentVariable('PSModulePath', $newModulePath, 'Machine')
|
||||||
|
$env:PSModulePath += ";$modulePath"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Uninstall-OpenSSHUtilsModule
|
||||||
|
{
|
||||||
|
[CmdletBinding()]
|
||||||
|
param([string]$TargetDir = (Join-Path -Path $env:ProgramFiles -ChildPath "WindowsPowerShell\Modules\OpenSSHUtils"))
|
||||||
|
|
||||||
|
if(Test-Path $TargetDir -PathType Container)
|
||||||
|
{
|
||||||
|
Remove-item $TargetDir -Recurse -Force -ErrorAction SilentlyContinue | out-null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
<#
|
<#
|
||||||
.Synopsis
|
.Synopsis
|
||||||
Get-UserSID
|
Get-UserSID
|
||||||
@ -296,12 +376,12 @@ function Get-UserSID
|
|||||||
|
|
||||||
<#
|
<#
|
||||||
.Synopsis
|
.Synopsis
|
||||||
Cleanup-OpenSSHTestEnvironment
|
Clear-OpenSSHTestEnvironment
|
||||||
#>
|
#>
|
||||||
function Cleanup-OpenSSHTestEnvironment
|
function Clear-OpenSSHTestEnvironment
|
||||||
{
|
{
|
||||||
if($Global:OpenSSHTestInfo -eq $null) {
|
if($Global:OpenSSHTestInfo -eq $null) {
|
||||||
throw "OpenSSHTestInfo is not set. Did you run Setup-OpenSShTestEnvironment?"
|
throw "OpenSSHTestInfo is not set. Did you run Set-OpenSShTestEnvironment?"
|
||||||
}
|
}
|
||||||
|
|
||||||
$sshBinPath = $Global:OpenSSHTestInfo["OpenSSHBinPath"]
|
$sshBinPath = $Global:OpenSSHTestInfo["OpenSSHBinPath"]
|
||||||
@ -356,6 +436,13 @@ function Cleanup-OpenSSHTestEnvironment
|
|||||||
$Global:OpenSSHTestInfo.Clear()
|
$Global:OpenSSHTestInfo.Clear()
|
||||||
$Global:OpenSSHTestInfo = $null
|
$Global:OpenSSHTestInfo = $null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$isOpenSSHUtilsAvailable = Get-Module 'OpenSSHUtils' -ListAvailable
|
||||||
|
if ($isOpenSSHUtilsAvailable)
|
||||||
|
{
|
||||||
|
Write-Log -Message "Uninstalling Module OpenSSHUtils..."
|
||||||
|
Uninstall-OpenSSHUtilsModule
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
<#
|
<#
|
||||||
@ -418,12 +505,13 @@ function Get-UnitTestDirectory
|
|||||||
.Synopsis
|
.Synopsis
|
||||||
Run OpenSSH pester tests.
|
Run OpenSSH pester tests.
|
||||||
#>
|
#>
|
||||||
function Run-OpenSSHE2ETest
|
function Invoke-OpenSSHE2ETest
|
||||||
{
|
{
|
||||||
# Discover all CI tests and run them.
|
# Discover all CI tests and run them.
|
||||||
|
Import-Module pester -force -global
|
||||||
Push-Location $Script:E2ETestDirectory
|
Push-Location $Script:E2ETestDirectory
|
||||||
Write-Log -Message "Running OpenSSH E2E tests..."
|
Write-Log -Message "Running OpenSSH E2E tests..."
|
||||||
$testFolders = Get-ChildItem *.tests.ps1 -Recurse | ForEach-Object{ Split-Path $_.FullName} | Sort-Object -Unique
|
$testFolders = @(Get-ChildItem *.tests.ps1 -Recurse | ForEach-Object{ Split-Path $_.FullName} | Sort-Object -Unique)
|
||||||
Invoke-Pester $testFolders -OutputFormat NUnitXml -OutputFile $Script:E2ETestResultsFile -Tag 'CI'
|
Invoke-Pester $testFolders -OutputFormat NUnitXml -OutputFile $Script:E2ETestResultsFile -Tag 'CI'
|
||||||
Pop-Location
|
Pop-Location
|
||||||
}
|
}
|
||||||
@ -432,35 +520,45 @@ function Run-OpenSSHE2ETest
|
|||||||
.Synopsis
|
.Synopsis
|
||||||
Run openssh unit tests.
|
Run openssh unit tests.
|
||||||
#>
|
#>
|
||||||
function Run-OpenSSHUnitTest
|
function Invoke-OpenSSHUnitTest
|
||||||
{
|
{
|
||||||
# Discover all CI tests and run them.
|
# Discover all CI tests and run them.
|
||||||
|
if([string]::Isnullorempty($Script:UnitTestDirectory))
|
||||||
|
{
|
||||||
|
$Script:UnitTestDirectory = $OpenSSHTestInfo["UnitTestDirectory"]
|
||||||
|
}
|
||||||
Push-Location $Script:UnitTestDirectory
|
Push-Location $Script:UnitTestDirectory
|
||||||
Write-Log -Message "Running OpenSSH unit tests..."
|
Write-Log -Message "Running OpenSSH unit tests..."
|
||||||
if (Test-Path $Script:UnitTestResultsFile)
|
if (Test-Path $Script:UnitTestResultsFile)
|
||||||
{
|
{
|
||||||
$null = Remove-Item -Path $Script:UnitTestResultsFile -Force -ErrorAction SilentlyContinue
|
$null = Remove-Item -Path $Script:UnitTestResultsFile -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
$testFolders = Get-ChildItem unittest-*.exe -Recurse -Exclude unittest-sshkey.exe,unittest-kex.exe |
|
$testFolders = Get-ChildItem -filter unittest-*.exe -Recurse -Exclude unittest-sshkey.exe,unittest-kex.exe |
|
||||||
ForEach-Object{ Split-Path $_.FullName} |
|
ForEach-Object{ Split-Path $_.FullName} |
|
||||||
Sort-Object -Unique
|
Sort-Object -Unique
|
||||||
$testfailed = $false
|
$testfailed = $false
|
||||||
if ($testFolders -ne $null)
|
if ($testFolders -ne $null)
|
||||||
{
|
{
|
||||||
$testFolders | % {
|
$testFolders | % {
|
||||||
Push-Location $_
|
|
||||||
$unittestFile = "$(Split-Path $_ -Leaf).exe"
|
$unittestFile = "$(Split-Path $_ -Leaf).exe"
|
||||||
Write-log "Running OpenSSH unit $unittestFile ..."
|
$unittestFilePath = join-path $_ $unittestFile
|
||||||
& .\$unittestFile >> $Script:UnitTestResultsFile
|
$Error.clear()
|
||||||
|
$LASTEXITCODE=0
|
||||||
|
if(Test-Path $unittestFilePath -pathtype leaf)
|
||||||
|
{
|
||||||
|
Push-Location $_
|
||||||
|
Write-Log "Running OpenSSH unit $unittestFile ..."
|
||||||
|
& "$unittestFilePath" >> $Script:UnitTestResultsFile
|
||||||
|
Pop-Location
|
||||||
|
}
|
||||||
|
|
||||||
$errorCode = $LASTEXITCODE
|
$errorCode = $LASTEXITCODE
|
||||||
if ($errorCode -ne 0)
|
if ($errorCode -ne 0)
|
||||||
{
|
{
|
||||||
$testfailed = $true
|
$testfailed = $true
|
||||||
$errorMessage = "$($_.FullName) test failed for OpenSSH.`nExitCode: $errorCode. Detail test log is at $($Script:UnitTestResultsFile)."
|
$errorMessage = "$_ test failed for OpenSSH.`nExitCode: $errorCode. Detail test log is at $($Script:UnitTestResultsFile)."
|
||||||
Write-Warning $errorMessage
|
Write-Warning $errorMessage
|
||||||
}
|
}
|
||||||
Pop-Location
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Pop-Location
|
Pop-Location
|
||||||
@ -475,7 +573,7 @@ function Backup-OpenSSHTestInfo
|
|||||||
)
|
)
|
||||||
|
|
||||||
if ($Global:OpenSSHTestInfo -eq $null) {
|
if ($Global:OpenSSHTestInfo -eq $null) {
|
||||||
Throw "`$OpenSSHTestInfo is null. Did you run Setup-OpenSSHTestEnvironment yet?"
|
Throw "`$OpenSSHTestInfo is null. Did you run Set-OpenSSHTestEnvironment yet?"
|
||||||
}
|
}
|
||||||
|
|
||||||
$testInfo = $Global:OpenSSHTestInfo
|
$testInfo = $Global:OpenSSHTestInfo
|
||||||
@ -492,7 +590,7 @@ function Backup-OpenSSHTestInfo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Recover-OpenSSHTestInfo
|
function Restore-OpenSSHTestInfo
|
||||||
{
|
{
|
||||||
param
|
param
|
||||||
(
|
(
|
||||||
@ -538,4 +636,4 @@ function Write-Log
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Export-ModuleMember -Function Setup-OpenSSHTestEnvironment, Cleanup-OpenSSHTestEnvironment, Run-OpenSSHUnitTest, Run-OpenSSHE2ETest, Backup-OpenSSHTestInfo, Recover-OpenSSHTestInfo
|
Export-ModuleMember -Function Set-OpenSSHTestEnvironment, Clear-OpenSSHTestEnvironment, Invoke-OpenSSHUnitTest, Invoke-OpenSSHE2ETest, Backup-OpenSSHTestInfo, Restore-OpenSSHTestInfo
|
||||||
|
@ -1,9 +1,49 @@
|
|||||||
Set-StrictMode -Version 2.0
|
Set-StrictMode -Version 2.0
|
||||||
$systemAccount = New-Object System.Security.Principal.NTAccount("NT AUTHORITY", "SYSTEM")
|
|
||||||
$adminsAccount = New-Object System.Security.Principal.NTAccount("BUILTIN","Administrators")
|
<#
|
||||||
$currentUser = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME))
|
.Synopsis
|
||||||
$everyone = New-Object System.Security.Principal.NTAccount("EveryOne")
|
Get-UserSID
|
||||||
$sshdAccount = New-Object System.Security.Principal.NTAccount("NT SERVICE","sshd")
|
#>
|
||||||
|
function Get-UserSID
|
||||||
|
{
|
||||||
|
[CmdletBinding(DefaultParameterSetName='User')]
|
||||||
|
param
|
||||||
|
( [parameter(Mandatory=$true, ParameterSetName="User")]
|
||||||
|
[ValidateNotNull()]
|
||||||
|
[System.Security.Principal.NTAccount]$User,
|
||||||
|
[parameter(Mandatory=$true, ParameterSetName="WellKnownSidType")]
|
||||||
|
[ValidateNotNull()]
|
||||||
|
[System.Security.Principal.WellKnownSidType]$WellKnownSidType
|
||||||
|
)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if($PSBoundParameters.ContainsKey("User"))
|
||||||
|
{
|
||||||
|
$sid = $User.Translate([System.Security.Principal.SecurityIdentifier])
|
||||||
|
}
|
||||||
|
elseif($PSBoundParameters.ContainsKey("WellKnownSidType"))
|
||||||
|
{
|
||||||
|
$sid = New-Object System.Security.Principal.SecurityIdentifier($WellKnownSidType, $null)
|
||||||
|
}
|
||||||
|
$sid
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
return $null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# get the local System user
|
||||||
|
$systemSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::LocalSystemSid)
|
||||||
|
|
||||||
|
# get the Administrators group
|
||||||
|
$adminsSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid)
|
||||||
|
|
||||||
|
# get the everyone
|
||||||
|
$everyoneSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::WorldSid)
|
||||||
|
|
||||||
|
$sshdSid = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-80-3847866527-469524349-687026318-516638107-1125189541")
|
||||||
|
|
||||||
|
$currentUserSid = Get-UserSID -User "$($env:USERDOMAIN)\$($env:USERNAME)"
|
||||||
|
|
||||||
#Taken from P/Invoke.NET with minor adjustments.
|
#Taken from P/Invoke.NET with minor adjustments.
|
||||||
$definition = @'
|
$definition = @'
|
||||||
@ -72,7 +112,7 @@ function Repair-SshdConfigPermission
|
|||||||
[ValidateNotNullOrEmpty()]
|
[ValidateNotNullOrEmpty()]
|
||||||
[string]$FilePath)
|
[string]$FilePath)
|
||||||
|
|
||||||
Repair-FilePermission -Owners $systemAccount,$adminsAccount -ReadAccessNeeded $sshdAccount @psBoundParameters
|
Repair-FilePermission -Owners $systemSid,$adminsSid -ReadAccessNeeded $sshdSid @psBoundParameters
|
||||||
}
|
}
|
||||||
|
|
||||||
<#
|
<#
|
||||||
@ -94,10 +134,10 @@ function Repair-SshdHostKeyPermission
|
|||||||
$PSBoundParameters["FilePath"] = $PSBoundParameters["FilePath"].Replace(".pub", "")
|
$PSBoundParameters["FilePath"] = $PSBoundParameters["FilePath"].Replace(".pub", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
Repair-FilePermission -Owners $systemAccount,$adminsAccount -ReadAccessNeeded $sshdAccount @psBoundParameters
|
Repair-FilePermission -Owners $systemSid,$adminsSid -ReadAccessNeeded $sshdSid @psBoundParameters
|
||||||
|
|
||||||
$PSBoundParameters["FilePath"] += ".pub"
|
$PSBoundParameters["FilePath"] += ".pub"
|
||||||
Repair-FilePermission -Owners $systemAccount,$adminsAccount -ReadAccessOK $everyone -ReadAccessNeeded $sshdAccount @psBoundParameters
|
Repair-FilePermission -Owners $systemSid,$adminsSid -ReadAccessOK $everyoneSid -ReadAccessNeeded $sshdSid @psBoundParameters
|
||||||
}
|
}
|
||||||
|
|
||||||
<#
|
<#
|
||||||
@ -127,20 +167,14 @@ function Repair-AuthorizedKeyPermission
|
|||||||
{
|
{
|
||||||
$userProfilePath = $properties.ProfileImagePath
|
$userProfilePath = $properties.ProfileImagePath
|
||||||
}
|
}
|
||||||
$fullPath -ieq "$userProfilePath\.ssh\authorized_keys"
|
$userProfilePath = $userProfilePath.Replace("\", "\\")
|
||||||
|
$fullPath -match "^$userProfilePath[\\|\W|\w]+authorized_keys$"
|
||||||
}
|
}
|
||||||
if($profileItem)
|
if($profileItem)
|
||||||
{
|
{
|
||||||
$userSid = $profileItem.PSChildName
|
$userSid = $profileItem.PSChildName
|
||||||
$account = Get-UserAccount -UserSid $userSid
|
Repair-FilePermission -Owners $userSid,$adminsSid,$systemSid -AnyAccessOK $userSid -ReadAccessNeeded $sshdSid @psBoundParameters
|
||||||
if($account)
|
|
||||||
{
|
|
||||||
Repair-FilePermission -Owners $account,$adminsAccount,$systemAccount -AnyAccessOK $account -ReadAccessNeeded $sshdAccount @psBoundParameters
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Write-host "Can't translate $userSid to an account. skip checking $fullPath..." -ForegroundColor Yellow
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -162,16 +196,16 @@ function Repair-UserKeyPermission
|
|||||||
[parameter(Mandatory=$true, Position = 0)]
|
[parameter(Mandatory=$true, Position = 0)]
|
||||||
[ValidateNotNullOrEmpty()]
|
[ValidateNotNullOrEmpty()]
|
||||||
[string]$FilePath,
|
[string]$FilePath,
|
||||||
[System.Security.Principal.NTAccount] $User = $currentUser)
|
[System.Security.Principal.SecurityIdentifier] $UserSid = $currentUserSid)
|
||||||
|
|
||||||
if($PSBoundParameters["FilePath"].EndsWith(".pub"))
|
if($PSBoundParameters["FilePath"].EndsWith(".pub"))
|
||||||
{
|
{
|
||||||
$PSBoundParameters["FilePath"] = $PSBoundParameters["FilePath"].Replace(".pub", "")
|
$PSBoundParameters["FilePath"] = $PSBoundParameters["FilePath"].Replace(".pub", "")
|
||||||
}
|
}
|
||||||
Repair-FilePermission -Owners $User, $adminsAccount,$systemAccount -AnyAccessOK $User @psBoundParameters
|
Repair-FilePermission -Owners $UserSid, $adminsSid,$systemSid -AnyAccessOK $UserSid @psBoundParameters
|
||||||
|
|
||||||
$PSBoundParameters["FilePath"] += ".pub"
|
$PSBoundParameters["FilePath"] += ".pub"
|
||||||
Repair-FilePermission -Owners $User, $adminsAccount,$systemAccount -AnyAccessOK $User -ReadAccessOK $everyone @psBoundParameters
|
Repair-FilePermission -Owners $UserSid, $adminsSid,$systemSid -AnyAccessOK $UserSid -ReadAccessOK $everyoneSid @psBoundParameters
|
||||||
}
|
}
|
||||||
|
|
||||||
<#
|
<#
|
||||||
@ -185,8 +219,9 @@ function Repair-UserSshConfigPermission
|
|||||||
param (
|
param (
|
||||||
[parameter(Mandatory=$true)]
|
[parameter(Mandatory=$true)]
|
||||||
[ValidateNotNullOrEmpty()]
|
[ValidateNotNullOrEmpty()]
|
||||||
[string]$FilePath)
|
[string]$FilePath,
|
||||||
Repair-FilePermission -Owners $currentUser,$adminsAccount,$systemAccount -AnyAccessOK $currentUser @psBoundParameters
|
[System.Security.Principal.SecurityIdentifier] $UserSid = $currentUserSid)
|
||||||
|
Repair-FilePermission -Owners $UserSid,$adminsSid,$systemSid -AnyAccessOK $UserSid @psBoundParameters
|
||||||
}
|
}
|
||||||
|
|
||||||
<#
|
<#
|
||||||
@ -202,10 +237,11 @@ function Repair-FilePermission
|
|||||||
[ValidateNotNullOrEmpty()]
|
[ValidateNotNullOrEmpty()]
|
||||||
[string]$FilePath,
|
[string]$FilePath,
|
||||||
[ValidateNotNull()]
|
[ValidateNotNull()]
|
||||||
[System.Security.Principal.NTAccount[]] $Owners = $currentUser,
|
[System.Security.Principal.SecurityIdentifier[]] $Owners = $currentUserSid,
|
||||||
[System.Security.Principal.NTAccount[]] $AnyAccessOK,
|
[System.Security.Principal.SecurityIdentifier[]] $AnyAccessOK = $null,
|
||||||
[System.Security.Principal.NTAccount[]] $ReadAccessOK,
|
[System.Security.Principal.SecurityIdentifier[]] $FullAccessNeeded = $null,
|
||||||
[System.Security.Principal.NTAccount[]] $ReadAccessNeeded
|
[System.Security.Principal.SecurityIdentifier[]] $ReadAccessOK = $null,
|
||||||
|
[System.Security.Principal.SecurityIdentifier[]] $ReadAccessNeeded = $null
|
||||||
)
|
)
|
||||||
|
|
||||||
if(-not (Test-Path $FilePath -PathType Leaf))
|
if(-not (Test-Path $FilePath -PathType Leaf))
|
||||||
@ -235,10 +271,11 @@ function Repair-FilePermissionInternal {
|
|||||||
[ValidateNotNullOrEmpty()]
|
[ValidateNotNullOrEmpty()]
|
||||||
[string]$FilePath,
|
[string]$FilePath,
|
||||||
[ValidateNotNull()]
|
[ValidateNotNull()]
|
||||||
[System.Security.Principal.NTAccount[]] $Owners = $currentUser,
|
[System.Security.Principal.SecurityIdentifier[]] $Owners = $currentUserSid,
|
||||||
[System.Security.Principal.NTAccount[]] $AnyAccessOK,
|
[System.Security.Principal.SecurityIdentifier[]] $AnyAccessOK = $null,
|
||||||
[System.Security.Principal.NTAccount[]] $ReadAccessOK,
|
[System.Security.Principal.SecurityIdentifier[]] $FullAccessNeeded = $null,
|
||||||
[System.Security.Principal.NTAccount[]] $ReadAccessNeeded
|
[System.Security.Principal.SecurityIdentifier[]] $ReadAccessOK = $null,
|
||||||
|
[System.Security.Principal.SecurityIdentifier[]] $ReadAccessNeeded = $null
|
||||||
)
|
)
|
||||||
|
|
||||||
$acl = Get-Acl $FilePath
|
$acl = Get-Acl $FilePath
|
||||||
@ -247,25 +284,18 @@ function Repair-FilePermissionInternal {
|
|||||||
$paras = @{}
|
$paras = @{}
|
||||||
$PSBoundParameters.GetEnumerator() | % { if((-not $_.key.Contains("Owners")) -and (-not $_.key.Contains("Access"))) { $paras.Add($_.key,$_.Value) } }
|
$PSBoundParameters.GetEnumerator() | % { if((-not $_.key.Contains("Owners")) -and (-not $_.key.Contains("Access"))) { $paras.Add($_.key,$_.Value) } }
|
||||||
|
|
||||||
$validOwner = $owners | ? { $_.equals([System.Security.Principal.NTAccount]$acl.owner)}
|
$currentOwnerSid = Get-UserSid -User $acl.owner
|
||||||
if($validOwner -eq $null)
|
if($owners -notcontains $currentOwnerSid)
|
||||||
{
|
{
|
||||||
$caption = "Current owner: '$($acl.Owner)'. '$($Owners[0])' should own '$FilePath'."
|
$newOwner = Get-UserAccount -User $Owners[0]
|
||||||
|
$caption = "Current owner: '$($acl.Owner)'. '$newOwner' should own '$FilePath'."
|
||||||
$prompt = "Shall I set the file owner?"
|
$prompt = "Shall I set the file owner?"
|
||||||
$description = "Set '$($Owners[0])' as owner of '$FilePath'."
|
$description = "Set '$newOwner' as owner of '$FilePath'."
|
||||||
if($pscmdlet.ShouldProcess($description, $prompt, $caption))
|
if($pscmdlet.ShouldProcess($description, $prompt, $caption))
|
||||||
{
|
{
|
||||||
Enable-Privilege SeRestorePrivilege | out-null
|
Enable-Privilege SeRestorePrivilege | out-null
|
||||||
$acl.SetOwner($Owners[0])
|
$acl.SetOwner($newOwner)
|
||||||
Set-Acl -Path $FilePath -AclObject $acl -ErrorVariable e -Confirm:$false
|
Set-Acl -Path $FilePath -AclObject $acl -Confirm:$false
|
||||||
if($e)
|
|
||||||
{
|
|
||||||
Write-Warning "Set owner failed with error: $($e[0].ToString())."
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Write-Host "'$($Owners[0])' now owns '$FilePath'. " -ForegroundColor Green
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -279,38 +309,112 @@ function Repair-FilePermissionInternal {
|
|||||||
|
|
||||||
$ReadAccessPerm = ([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Read.value__) -bor `
|
$ReadAccessPerm = ([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Read.value__) -bor `
|
||||||
([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Synchronize.value__)
|
([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Synchronize.value__)
|
||||||
|
$FullControlPerm = [System.UInt32] [System.Security.AccessControl.FileSystemRights]::FullControl.value__
|
||||||
|
|
||||||
#system and admin groups can have any access to the file; plus the account in the AnyAccessOK list
|
#system and admin groups can have any access to the file; plus the account in the AnyAccessOK list
|
||||||
$realAnyAccessOKList = $AnyAccessOK + @($systemAccount, $adminsAccount)
|
$realAnyAccessOKList = @($systemSid, $adminsSid)
|
||||||
|
if($AnyAccessOK)
|
||||||
|
{
|
||||||
|
$realAnyAccessOKList += $AnyAccessOK
|
||||||
|
}
|
||||||
|
|
||||||
#if accounts in the ReadAccessNeeded already part of dacl, they are okay; need to make sure they have read access only
|
$realFullAccessNeeded = $FullAccessNeeded
|
||||||
$realReadAcessOKList = $ReadAccessOK + $ReadAccessNeeded
|
|
||||||
|
|
||||||
#this is orginal list requested by the user, the account will be removed from the list if they already part of the dacl
|
|
||||||
$realReadAccessNeeded = $ReadAccessNeeded
|
$realReadAccessNeeded = $ReadAccessNeeded
|
||||||
|
if($realFullAccessNeeded -contains $everyoneSid)
|
||||||
|
{
|
||||||
|
$realFullAccessNeeded = @($everyoneSid)
|
||||||
|
$realReadAccessNeeded = $null
|
||||||
|
}
|
||||||
|
|
||||||
#'APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES'- can't translate fully qualified name. it is a win32 API bug.
|
if($realReadAccessNeeded -contains $everyoneSid)
|
||||||
#'ALL APPLICATION PACKAGES' exists only on Win2k12 and Win2k16 and 'ALL RESTRICTED APPLICATION PACKAGES' exists only in Win2k16
|
{
|
||||||
$specialIdRefs = "ALL APPLICATION PACKAGES","ALL RESTRICTED APPLICATION PACKAGES"
|
$realReadAccessNeeded = @($everyoneSid)
|
||||||
|
}
|
||||||
|
#this is orginal list requested by the user, the account will be removed from the list if they already part of the dacl
|
||||||
|
if($realReadAccessNeeded)
|
||||||
|
{
|
||||||
|
$realReadAccessNeeded = $realReadAccessNeeded | ? { ($_ -ne $null) -and ($realFullAccessNeeded -notcontains $_) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#if accounts in the ReadAccessNeeded or $realFullAccessNeeded already part of dacl, they are okay;
|
||||||
|
#need to make sure they have read access only
|
||||||
|
$realReadAcessOKList = $ReadAccessOK + $realReadAccessNeeded
|
||||||
|
|
||||||
foreach($a in $acl.Access)
|
foreach($a in $acl.Access)
|
||||||
{
|
{
|
||||||
if($realAnyAccessOKList -and (($realAnyAccessOKList | ? { $_.equals($a.IdentityReference)}) -ne $null))
|
$IdentityReferenceSid = Get-UserSid -User $a.IdentityReference
|
||||||
|
if($IdentityReferenceSid -eq $null)
|
||||||
|
{
|
||||||
|
$idRefShortValue = ($a.IdentityReference.Value).split('\')[-1]
|
||||||
|
$IdentityReferenceSid = Get-UserSID -User $idRefShortValue
|
||||||
|
if($IdentityReferenceSid -eq $null)
|
||||||
|
{
|
||||||
|
Write-Warning "Can't translate '$idRefShortValue'. "
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($realFullAccessNeeded -contains ($IdentityReferenceSid))
|
||||||
|
{
|
||||||
|
$realFullAccessNeeded = $realFullAccessNeeded | ? { ($_ -ne $null) -and (-not $_.Equals($IdentityReferenceSid)) }
|
||||||
|
if($realReadAccessNeeded)
|
||||||
|
{
|
||||||
|
$realReadAccessNeeded = $realReadAccessNeeded | ? { ($_ -ne $null) -and (-not $_.Equals($IdentityReferenceSid)) }
|
||||||
|
}
|
||||||
|
if (($a.AccessControlType.Equals([System.Security.AccessControl.AccessControlType]::Allow)) -and `
|
||||||
|
((([System.UInt32]$a.FileSystemRights.value__) -band $FullControlPerm) -eq $FullControlPerm))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#update the account to full control
|
||||||
|
if($a.IsInherited)
|
||||||
|
{
|
||||||
|
if($needChange)
|
||||||
|
{
|
||||||
|
Enable-Privilege SeRestorePrivilege | out-null
|
||||||
|
Set-Acl -Path $FilePath -AclObject $acl -Confirm:$false
|
||||||
|
}
|
||||||
|
|
||||||
|
return Remove-RuleProtection @paras
|
||||||
|
}
|
||||||
|
$caption = "'$($a.IdentityReference)' has the following access to '$FilePath': '$($a.AccessControlType)'-'$($a.FileSystemRights)'."
|
||||||
|
$prompt = "Shall I make it Allow FullControl?"
|
||||||
|
$description = "Grant '$($a.IdentityReference)' FullControl access to '$FilePath'. "
|
||||||
|
|
||||||
|
if($pscmdlet.ShouldProcess($description, $prompt, $caption))
|
||||||
|
{
|
||||||
|
$needChange = $true
|
||||||
|
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
|
||||||
|
($IdentityReferenceSid, "FullControl", "None", "None", "Allow")
|
||||||
|
|
||||||
|
$acl.SetAccessRule($ace)
|
||||||
|
Write-Host "'$($a.IdentityReference)' now has FullControl access to '$FilePath'. " -ForegroundColor Green
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$health = $false
|
||||||
|
if(-not $PSBoundParameters.ContainsKey("WhatIf"))
|
||||||
|
{
|
||||||
|
Write-Host "'$($a.IdentityReference)' still has these access to '$FilePath': '$($a.AccessControlType)'-'$($a.FileSystemRights)'." -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif(($realAnyAccessOKList -contains $everyoneSid) -or ($realAnyAccessOKList -contains $IdentityReferenceSid))
|
||||||
{
|
{
|
||||||
#ignore those accounts listed in the AnyAccessOK list.
|
#ignore those accounts listed in the AnyAccessOK list.
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
#If everyone is in the ReadAccessOK list, any user can have read access;
|
#If everyone is in the ReadAccessOK list, any user can have read access;
|
||||||
# below block make sure they are granted Read access only
|
# below block make sure they are granted Read access only
|
||||||
elseif($realReadAcessOKList -and ((($realReadAcessOKList | ? { $_.Equals($everyone)}) -ne $null) -or `
|
elseif(($realReadAcessOKList -contains $everyoneSid) -or ($realReadAcessOKList -contains $IdentityReferenceSid))
|
||||||
(($realReadAcessOKList | ? { $_.equals($a.IdentityReference)}) -ne $null)))
|
|
||||||
{
|
{
|
||||||
if($realReadAccessNeeded -and ($a.IdentityReference.Equals($everyone)))
|
if($realReadAccessNeeded -and ($IdentityReferenceSid.Equals($everyoneSid)))
|
||||||
{
|
{
|
||||||
$realReadAccessNeeded=@()
|
$realReadAccessNeeded= $null
|
||||||
}
|
}
|
||||||
elseif($realReadAccessNeeded)
|
elseif($realReadAccessNeeded)
|
||||||
{
|
{
|
||||||
$realReadAccessNeeded = $realReadAccessNeeded | ? { -not $_.Equals($a.IdentityReference) }
|
$realReadAccessNeeded = $realReadAccessNeeded | ? { ($_ -ne $null ) -and (-not $_.Equals($IdentityReferenceSid)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not ($a.AccessControlType.Equals([System.Security.AccessControl.AccessControlType]::Allow)) -or `
|
if (-not ($a.AccessControlType.Equals([System.Security.AccessControl.AccessControlType]::Allow)) -or `
|
||||||
@ -324,11 +428,7 @@ function Repair-FilePermissionInternal {
|
|||||||
if($needChange)
|
if($needChange)
|
||||||
{
|
{
|
||||||
Enable-Privilege SeRestorePrivilege | out-null
|
Enable-Privilege SeRestorePrivilege | out-null
|
||||||
Set-Acl -Path $FilePath -AclObject $acl -ErrorVariable e -Confirm:$false
|
Set-Acl -Path $FilePath -AclObject $acl -Confirm:$false
|
||||||
if($e)
|
|
||||||
{
|
|
||||||
Write-Warning "Repair permission failed with error: $($e[0].ToString())."
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Remove-RuleProtection @paras
|
return Remove-RuleProtection @paras
|
||||||
@ -340,28 +440,11 @@ function Repair-FilePermissionInternal {
|
|||||||
if($pscmdlet.ShouldProcess($description, $prompt, $caption))
|
if($pscmdlet.ShouldProcess($description, $prompt, $caption))
|
||||||
{
|
{
|
||||||
$needChange = $true
|
$needChange = $true
|
||||||
$idRefShortValue = ($a.IdentityReference.Value).split('\')[-1]
|
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
|
||||||
if ($specialIdRefs -icontains $idRefShortValue )
|
($IdentityReferenceSid, "Read", "None", "None", "Allow")
|
||||||
{
|
|
||||||
$ruleIdentity = Get-UserSID -User (New-Object Security.Principal.NTAccount $idRefShortValue)
|
|
||||||
if($ruleIdentity)
|
|
||||||
{
|
|
||||||
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
|
|
||||||
($ruleIdentity, "Read", "None", "None", "Allow")
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Write-Warning "Can't translate '$idRefShortValue'. "
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
|
|
||||||
($a.IdentityReference, "Read", "None", "None", "Allow")
|
|
||||||
}
|
|
||||||
$acl.SetAccessRule($ace)
|
$acl.SetAccessRule($ace)
|
||||||
Write-Host "'$($a.IdentityReference)' now has Read access to '$FilePath'. " -ForegroundColor Green
|
Write-Host "'$($a.IdentityReference)' now has Read access to '$FilePath'. " -ForegroundColor Green
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -381,11 +464,7 @@ function Repair-FilePermissionInternal {
|
|||||||
if($needChange)
|
if($needChange)
|
||||||
{
|
{
|
||||||
Enable-Privilege SeRestorePrivilege | out-null
|
Enable-Privilege SeRestorePrivilege | out-null
|
||||||
Set-Acl -Path $FilePath -AclObject $acl -ErrorVariable e -Confirm:$false
|
Set-Acl -Path $FilePath -AclObject $acl -Confirm:$false
|
||||||
if($e)
|
|
||||||
{
|
|
||||||
Write-Warning "Repair permission failed with error: $($e[0].ToString())."
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return Remove-RuleProtection @paras
|
return Remove-RuleProtection @paras
|
||||||
}
|
}
|
||||||
@ -396,22 +475,8 @@ function Repair-FilePermissionInternal {
|
|||||||
if($pscmdlet.ShouldProcess($description, $prompt, "$caption."))
|
if($pscmdlet.ShouldProcess($description, $prompt, "$caption."))
|
||||||
{
|
{
|
||||||
$needChange = $true
|
$needChange = $true
|
||||||
$ace = $a
|
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
|
||||||
$idRefShortValue = ($a.IdentityReference.Value).split('\')[-1]
|
($IdentityReferenceSid, $a.FileSystemRights, $a.InheritanceFlags, $a.PropagationFlags, $a.AccessControlType)
|
||||||
if ($specialIdRefs -icontains $idRefShortValue)
|
|
||||||
{
|
|
||||||
$ruleIdentity = Get-UserSID -User (New-Object Security.Principal.NTAccount $idRefShortValue)
|
|
||||||
if($ruleIdentity)
|
|
||||||
{
|
|
||||||
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
|
|
||||||
($ruleIdentity, $a.FileSystemRights, $a.InheritanceFlags, $a.PropagationFlags, $a.AccessControlType)
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Write-Warning "Can't translate '$idRefShortValue'. "
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(-not ($acl.RemoveAccessRule($ace)))
|
if(-not ($acl.RemoveAccessRule($ace)))
|
||||||
{
|
{
|
||||||
@ -433,19 +498,54 @@ function Repair-FilePermissionInternal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($realFullAccessNeeded)
|
||||||
|
{
|
||||||
|
$realFullAccessNeeded | % {
|
||||||
|
$account = Get-UserAccount -UserSid $_
|
||||||
|
if($account -eq $null)
|
||||||
|
{
|
||||||
|
Write-Warning "'$_' needs FullControl access to '$FilePath', but it can't be translated on the machine."
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$caption = "'$account' needs FullControl access to '$FilePath'."
|
||||||
|
$prompt = "Shall I make the above change?"
|
||||||
|
$description = "Set '$account' FullControl access to '$FilePath'. "
|
||||||
|
|
||||||
|
if($pscmdlet.ShouldProcess($description, $prompt, $caption))
|
||||||
|
{
|
||||||
|
$needChange = $true
|
||||||
|
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
|
||||||
|
($_, "FullControl", "None", "None", "Allow")
|
||||||
|
$acl.AddAccessRule($ace)
|
||||||
|
Write-Host "'$account' now has FullControl to '$FilePath'." -ForegroundColor Green
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$health = $false
|
||||||
|
if(-not $PSBoundParameters.ContainsKey("WhatIf"))
|
||||||
|
{
|
||||||
|
Write-Host "'$account' does not have FullControl to '$FilePath'." -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#This is the real account list we need to add read access to the file
|
#This is the real account list we need to add read access to the file
|
||||||
if($realReadAccessNeeded)
|
if($realReadAccessNeeded)
|
||||||
{
|
{
|
||||||
$realReadAccessNeeded | % {
|
$realReadAccessNeeded | % {
|
||||||
if((Get-UserSID -User $_) -eq $null)
|
$account = Get-UserAccount -UserSid $_
|
||||||
|
if($account -eq $null)
|
||||||
{
|
{
|
||||||
Write-Warning "'$_' needs Read access to '$FilePath', but it can't be translated on the machine."
|
Write-Warning "'$_' needs Read access to '$FilePath', but it can't be translated on the machine."
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$caption = "'$_' needs Read access to '$FilePath'."
|
$caption = "'$account' needs Read access to '$FilePath'."
|
||||||
$prompt = "Shall I make the above change?"
|
$prompt = "Shall I make the above change?"
|
||||||
$description = "Set '$_' Read only access to '$FilePath'. "
|
$description = "Set '$account' Read only access to '$FilePath'. "
|
||||||
|
|
||||||
if($pscmdlet.ShouldProcess($description, $prompt, $caption))
|
if($pscmdlet.ShouldProcess($description, $prompt, $caption))
|
||||||
{
|
{
|
||||||
@ -453,14 +553,14 @@ function Repair-FilePermissionInternal {
|
|||||||
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
|
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
|
||||||
($_, "Read", "None", "None", "Allow")
|
($_, "Read", "None", "None", "Allow")
|
||||||
$acl.AddAccessRule($ace)
|
$acl.AddAccessRule($ace)
|
||||||
Write-Host "'$_' now has Read access to '$FilePath'." -ForegroundColor Green
|
Write-Host "'$account' now has Read access to '$FilePath'." -ForegroundColor Green
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$health = $false
|
$health = $false
|
||||||
if(-not $PSBoundParameters.ContainsKey("WhatIf"))
|
if(-not $PSBoundParameters.ContainsKey("WhatIf"))
|
||||||
{
|
{
|
||||||
Write-Host "'$_' does not have Read access to '$FilePath'." -ForegroundColor Yellow
|
Write-Host "'$account' does not have Read access to '$FilePath'." -ForegroundColor Yellow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -470,11 +570,7 @@ function Repair-FilePermissionInternal {
|
|||||||
if($needChange)
|
if($needChange)
|
||||||
{
|
{
|
||||||
Enable-Privilege SeRestorePrivilege | out-null
|
Enable-Privilege SeRestorePrivilege | out-null
|
||||||
Set-Acl -Path $FilePath -AclObject $acl -ErrorVariable e -Confirm:$false
|
Set-Acl -Path $FilePath -AclObject $acl -Confirm:$false
|
||||||
if($e)
|
|
||||||
{
|
|
||||||
Write-Warning "Repair permission failed with error: $($e[0].ToString())."
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if($health)
|
if($health)
|
||||||
{
|
{
|
||||||
@ -525,41 +621,44 @@ function Remove-RuleProtection
|
|||||||
return $false
|
return $false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
<#
|
<#
|
||||||
.Synopsis
|
.Synopsis
|
||||||
Get-UserAccount
|
Get-UserAccount
|
||||||
#>
|
#>
|
||||||
function Get-UserAccount
|
function Get-UserAccount
|
||||||
{
|
{
|
||||||
|
[CmdletBinding(DefaultParameterSetName='Sid')]
|
||||||
param
|
param
|
||||||
( [parameter(Mandatory=$true)]
|
( [parameter(Mandatory=$true, ParameterSetName="Sid")]
|
||||||
[string]$UserSid
|
[ValidateNotNull()]
|
||||||
|
[System.Security.Principal.SecurityIdentifier]$UserSid,
|
||||||
|
[parameter(Mandatory=$true, ParameterSetName="WellKnownSidType")]
|
||||||
|
[ValidateNotNull()]
|
||||||
|
[System.Security.Principal.WellKnownSidType]$WellKnownSidType
|
||||||
)
|
)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$objSID = New-Object System.Security.Principal.SecurityIdentifier($UserSid)
|
if($PSBoundParameters.ContainsKey("UserSid"))
|
||||||
$objUser = $objSID.Translate( [System.Security.Principal.NTAccount])
|
{
|
||||||
|
$objUser = $UserSid.Translate([System.Security.Principal.NTAccount])
|
||||||
|
}
|
||||||
|
elseif($PSBoundParameters.ContainsKey("WellKnownSidType"))
|
||||||
|
{
|
||||||
|
$objSID = New-Object System.Security.Principal.SecurityIdentifier($WellKnownSidType, $null)
|
||||||
|
$objUser = $objSID.Translate( [System.Security.Principal.NTAccount])
|
||||||
|
}
|
||||||
$objUser
|
$objUser
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
|
return $null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
<#
|
<#
|
||||||
.Synopsis
|
.Synopsis
|
||||||
Get-UserSID
|
Enable-Privilege
|
||||||
#>
|
#>
|
||||||
function Get-UserSID
|
|
||||||
{
|
|
||||||
param ([System.Security.Principal.NTAccount]$User)
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$User.Translate([System.Security.Principal.SecurityIdentifier])
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function Enable-Privilege {
|
function Enable-Privilege {
|
||||||
param(
|
param(
|
||||||
#The privilege to adjust. This set is taken from
|
#The privilege to adjust. This set is taken from
|
||||||
@ -584,4 +683,4 @@ function Enable-Privilege {
|
|||||||
$type[0]::EnablePrivilege($Privilege, $Disable)
|
$type[0]::EnablePrivilege($Privilege, $Disable)
|
||||||
}
|
}
|
||||||
|
|
||||||
Export-ModuleMember -Function Repair-FilePermission, Repair-SshdConfigPermission, Repair-SshdHostKeyPermission, Repair-AuthorizedKeyPermission, Repair-UserKeyPermission, Repair-UserSshConfigPermission
|
Export-ModuleMember -Function Repair-FilePermission, Repair-SshdConfigPermission, Repair-SshdHostKeyPermission, Repair-AuthorizedKeyPermission, Repair-UserKeyPermission, Repair-UserSshConfigPermission, Enable-Privilege, Get-UserAccount, Get-UserSID
|
||||||
|
@ -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)sshlogin.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32_sshpty.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32_sshpty.c" />
|
||||||
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\wmain_sshd.c" />
|
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\wmain_sshd.c" />
|
||||||
|
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32_monitor_wrap.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="version.rc" />
|
<ResourceCompile Include="version.rc" />
|
||||||
|
@ -150,6 +150,9 @@
|
|||||||
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32_sshpty.c">
|
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32_sshpty.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\win32_monitor_wrap.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="version.rc">
|
<ResourceCompile Include="version.rc">
|
||||||
|
@ -120,3 +120,4 @@ Subsystem sftp sftp-server.exe
|
|||||||
# AllowTcpForwarding no
|
# AllowTcpForwarding no
|
||||||
# ForceCommand cvs server
|
# ForceCommand cvs server
|
||||||
# PubkeyAcceptedKeyTypes ssh-ed25519*
|
# PubkeyAcceptedKeyTypes ssh-ed25519*
|
||||||
|
hostkeyagent \\.\pipe\openssh-ssh-agent
|
Binary file not shown.
@ -114,9 +114,8 @@ int
|
|||||||
fileio_connect(struct w32_io* pio, char* name)
|
fileio_connect(struct w32_io* pio, char* name)
|
||||||
{
|
{
|
||||||
wchar_t* name_w = NULL;
|
wchar_t* name_w = NULL;
|
||||||
wchar_t pipe_name[PATH_MAX];
|
|
||||||
HANDLE h = INVALID_HANDLE_VALUE;
|
HANDLE h = INVALID_HANDLE_VALUE;
|
||||||
int ret = 0, r;
|
int ret = 0;
|
||||||
|
|
||||||
if (pio->handle != 0 && pio->handle != INVALID_HANDLE_VALUE) {
|
if (pio->handle != 0 && pio->handle != INVALID_HANDLE_VALUE) {
|
||||||
debug3("fileio_connect called in unexpected state, pio = %p", pio);
|
debug3("fileio_connect called in unexpected state, pio = %p", pio);
|
||||||
@ -129,16 +128,9 @@ fileio_connect(struct w32_io* pio, char* name)
|
|||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
r = _snwprintf_s(pipe_name, PATH_MAX, PATH_MAX, L"\\\\.\\pipe\\%ls", name_w);
|
|
||||||
if (r < 0 || r >= PATH_MAX) {
|
|
||||||
debug3("cannot create pipe name with %s", name);
|
|
||||||
errno = EOTHER;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
h = CreateFileW(pipe_name, GENERIC_READ | GENERIC_WRITE, 0,
|
h = CreateFileW(name_w, GENERIC_READ | GENERIC_WRITE, 0,
|
||||||
NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED | SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION, NULL);
|
NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED | SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION, NULL);
|
||||||
|
|
||||||
if (h != INVALID_HANDLE_VALUE)
|
if (h != INVALID_HANDLE_VALUE)
|
||||||
|
@ -478,11 +478,23 @@ strmode(mode_t mode, char *p)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The below code is commented as the group, other is not applicable on the windows.
|
/* group, other are not applicable on the windows */
|
||||||
* As of now we are keeping "*" for everything.
|
|
||||||
* TODO - figure out if there is a better option
|
/* usr */
|
||||||
*/
|
if (mode & S_IREAD)
|
||||||
const char *permissions = "********* ";
|
*p++ = 'r';
|
||||||
|
else
|
||||||
|
*p++ = '-';
|
||||||
|
if (mode & S_IWRITE)
|
||||||
|
*p++ = 'w';
|
||||||
|
else
|
||||||
|
*p++ = '-';
|
||||||
|
if (mode & S_IEXEC)
|
||||||
|
*p++ = 'x';
|
||||||
|
else
|
||||||
|
*p++ = '-';
|
||||||
|
|
||||||
|
const char *permissions = "****** ";
|
||||||
for(int i = 0; i < strlen(permissions); i++)
|
for(int i = 0; i < strlen(permissions); i++)
|
||||||
*p++ = permissions[i];
|
*p++ = permissions[i];
|
||||||
|
|
||||||
@ -950,7 +962,8 @@ w32_strerror(int errnum)
|
|||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
readpassphrase(const char *prompt, char *outBuf, size_t outBufLen, int flags) {
|
readpassphrase(const char *prompt, char *outBuf, size_t outBufLen, int flags)
|
||||||
|
{
|
||||||
int current_index = 0;
|
int current_index = 0;
|
||||||
char ch;
|
char ch;
|
||||||
wchar_t* wtmp = NULL;
|
wchar_t* wtmp = NULL;
|
||||||
|
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[B", VK_DOWN, 0 , 0},
|
||||||
{ L"\x1b[C", VK_RIGHT, 0 , 0},
|
{ L"\x1b[C", VK_RIGHT, 0 , 0},
|
||||||
{ L"\x1b[D", VK_LEFT, 0 , 0},
|
{ L"\x1b[D", VK_LEFT, 0 , 0},
|
||||||
|
{ L"\x1b[F", VK_END, 0 , 0 }, /* KeyPad END */
|
||||||
|
{ L"\x1b[H", VK_HOME, 0 , 0 }, /* KeyPad HOME */
|
||||||
|
{ L"\x1b[Z", 0, 0 , 0 }, /* ignore Shift+TAB */
|
||||||
{ L"\x1b[1~", VK_HOME, 0 , 0},
|
{ L"\x1b[1~", VK_HOME, 0 , 0},
|
||||||
{ L"\x1b[2~", VK_INSERT, 0 , 0},
|
{ L"\x1b[2~", VK_INSERT, 0 , 0},
|
||||||
{ L"\x1b[3~", VK_DELETE, 0 , 0},
|
{ L"\x1b[3~", VK_DELETE, 0 , 0},
|
||||||
@ -120,11 +123,17 @@ struct key_translation keys[] = {
|
|||||||
{ L"\x1b[21~", VK_F10, 0 , 0},
|
{ L"\x1b[21~", VK_F10, 0 , 0},
|
||||||
{ L"\x1b[23~", VK_F11, 0 , 0},
|
{ L"\x1b[23~", VK_F11, 0 , 0},
|
||||||
{ L"\x1b[24~", VK_F12, 0 , 0},
|
{ L"\x1b[24~", VK_F12, 0 , 0},
|
||||||
|
{ L"\x1bOP", VK_F1, 0 , 0 },
|
||||||
|
{ L"\x1bOQ", VK_F2, 0 , 0 },
|
||||||
|
{ L"\x1bOR", VK_F3, 0 , 0 },
|
||||||
|
{ L"\x1bOS", VK_F4, 0 , 0 },
|
||||||
{ L"\x1b", VK_ESCAPE, L'\x1b' , 0}
|
{ L"\x1b", VK_ESCAPE, L'\x1b' , 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
static SHORT lastX = 0;
|
static SHORT lastX = 0;
|
||||||
static SHORT lastY = 0;
|
static SHORT lastY = 0;
|
||||||
|
static wchar_t cmd_exe_path[PATH_MAX];
|
||||||
|
|
||||||
SHORT currentLine = 0;
|
SHORT currentLine = 0;
|
||||||
consoleEvent* head = NULL;
|
consoleEvent* head = NULL;
|
||||||
consoleEvent* tail = NULL;
|
consoleEvent* tail = NULL;
|
||||||
@ -939,6 +948,19 @@ cleanup:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wchar_t *
|
||||||
|
w32_cmd_path()
|
||||||
|
{
|
||||||
|
ZeroMemory(cmd_exe_path, PATH_MAX);
|
||||||
|
if (!GetSystemDirectory(cmd_exe_path, sizeof(cmd_exe_path))) {
|
||||||
|
printf("GetSystemDirectory failed");
|
||||||
|
exit(255);
|
||||||
|
}
|
||||||
|
|
||||||
|
wcscat_s(cmd_exe_path, sizeof(cmd_exe_path), L"\\cmd.exe");
|
||||||
|
return cmd_exe_path;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
start_with_pty(wchar_t *command)
|
start_with_pty(wchar_t *command)
|
||||||
{
|
{
|
||||||
@ -1004,9 +1026,8 @@ start_with_pty(wchar_t *command)
|
|||||||
/* disable inheritance on pipe_in*/
|
/* disable inheritance on pipe_in*/
|
||||||
GOTO_CLEANUP_ON_FALSE(SetHandleInformation(pipe_in, HANDLE_FLAG_INHERIT, 0));
|
GOTO_CLEANUP_ON_FALSE(SetHandleInformation(pipe_in, HANDLE_FLAG_INHERIT, 0));
|
||||||
|
|
||||||
/*TODO - pick this up from system32*/
|
|
||||||
cmd[0] = L'\0';
|
cmd[0] = L'\0';
|
||||||
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L"cmd.exe"));
|
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, w32_cmd_path()));
|
||||||
|
|
||||||
if (command) {
|
if (command) {
|
||||||
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L" /c"));
|
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L" /c"));
|
||||||
@ -1179,9 +1200,8 @@ start_withno_pty(wchar_t *command)
|
|||||||
|
|
||||||
/* if above failed with FILE_NOT_FOUND, try running the provided command under cmd*/
|
/* if above failed with FILE_NOT_FOUND, try running the provided command under cmd*/
|
||||||
if (run_under_cmd) {
|
if (run_under_cmd) {
|
||||||
/*TODO - pick this up from system32*/
|
|
||||||
cmd[0] = L'\0';
|
cmd[0] = L'\0';
|
||||||
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L"cmd.exe"));
|
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, w32_cmd_path()));
|
||||||
if (command) {
|
if (command) {
|
||||||
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L" /c"));
|
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L" /c"));
|
||||||
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L" "));
|
GOTO_CLEANUP_ON_ERR(wcscat_s(cmd, MAX_CMD_LEN, L" "));
|
||||||
|
@ -16,6 +16,6 @@ int process_request_identities(struct sshbuf*, struct sshbuf*, struct agent_conn
|
|||||||
int process_sign_request(struct sshbuf*, struct sshbuf*, struct agent_connection*);
|
int process_sign_request(struct sshbuf*, struct sshbuf*, struct agent_connection*);
|
||||||
int process_remove_key(struct sshbuf*, struct sshbuf*, struct agent_connection*);
|
int process_remove_key(struct sshbuf*, struct sshbuf*, struct agent_connection*);
|
||||||
int process_remove_all(struct sshbuf*, struct sshbuf*, struct agent_connection*);
|
int process_remove_all(struct sshbuf*, struct sshbuf*, struct agent_connection*);
|
||||||
int process_authagent_request(struct sshbuf*, struct sshbuf*, struct agent_connection*);
|
int process_privagent_request(struct sshbuf*, struct sshbuf*, struct agent_connection*);
|
||||||
|
|
||||||
/* auth */
|
/* auth */
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
static HANDLE ioc_port = NULL;
|
static HANDLE ioc_port = NULL;
|
||||||
static BOOL debug_mode = FALSE;
|
static BOOL debug_mode = FALSE;
|
||||||
|
|
||||||
#define AGENT_PIPE_ID L"\\\\.\\pipe\\ssh-agent"
|
#define AGENT_PIPE_ID L"\\\\.\\pipe\\openssh-ssh-agent"
|
||||||
|
|
||||||
static HANDLE event_stop_agent;
|
static HANDLE event_stop_agent;
|
||||||
static OVERLAPPED ol;
|
static OVERLAPPED ol;
|
||||||
@ -168,12 +168,14 @@ agent_cleanup_connection(struct agent_connection* con)
|
|||||||
{
|
{
|
||||||
debug("connection %p clean up", con);
|
debug("connection %p clean up", con);
|
||||||
CloseHandle(con->pipe_handle);
|
CloseHandle(con->pipe_handle);
|
||||||
if (con->hProfile)
|
if (con->profile_handle)
|
||||||
UnloadUserProfile(con->auth_token, con->hProfile);
|
UnloadUserProfile(con->profile_token, con->profile_handle);
|
||||||
if (con->auth_token)
|
if (con->profile_token)
|
||||||
CloseHandle(con->auth_token);
|
CloseHandle(con->profile_token);
|
||||||
if (con->client_impersonation_token)
|
if (con->client_impersonation_token)
|
||||||
CloseHandle(con->client_impersonation_token);
|
CloseHandle(con->client_impersonation_token);
|
||||||
|
if (con->client_process_handle)
|
||||||
|
CloseHandle(con->client_process_handle);
|
||||||
free(con);
|
free(con);
|
||||||
CloseHandle(ioc_port);
|
CloseHandle(ioc_port);
|
||||||
ioc_port = NULL;
|
ioc_port = NULL;
|
||||||
@ -251,13 +253,13 @@ get_con_client_info(struct agent_connection* con)
|
|||||||
DWORD sshd_sid_len = 0;
|
DWORD sshd_sid_len = 0;
|
||||||
PSID sshd_sid = NULL;
|
PSID sshd_sid = NULL;
|
||||||
SID_NAME_USE nuse;
|
SID_NAME_USE nuse;
|
||||||
HANDLE client_primary_token = NULL, client_impersonation_token = NULL, client_proc_handle = NULL;
|
HANDLE client_primary_token = NULL, client_impersonation_token = NULL, client_process_handle = NULL;
|
||||||
TOKEN_USER* info = NULL;
|
TOKEN_USER* info = NULL;
|
||||||
BOOL isMember = FALSE;
|
BOOL isMember = FALSE;
|
||||||
|
|
||||||
if (GetNamedPipeClientProcessId(con->pipe_handle, &client_pid) == FALSE ||
|
if (GetNamedPipeClientProcessId(con->pipe_handle, &client_pid) == FALSE ||
|
||||||
(client_proc_handle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, client_pid)) == NULL ||
|
(client_process_handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_DUP_HANDLE, FALSE, client_pid)) == NULL ||
|
||||||
OpenProcessToken(client_proc_handle, TOKEN_QUERY | TOKEN_DUPLICATE, &client_primary_token) == FALSE ||
|
OpenProcessToken(client_process_handle, TOKEN_QUERY | TOKEN_DUPLICATE, &client_primary_token) == FALSE ||
|
||||||
DuplicateToken(client_primary_token, SecurityImpersonation, &client_impersonation_token) == FALSE) {
|
DuplicateToken(client_primary_token, SecurityImpersonation, &client_impersonation_token) == FALSE) {
|
||||||
error("cannot retrieve client impersonatin token");
|
error("cannot retrieve client impersonatin token");
|
||||||
goto done;
|
goto done;
|
||||||
@ -341,15 +343,19 @@ done:
|
|||||||
free(ref_dom);
|
free(ref_dom);
|
||||||
if (info)
|
if (info)
|
||||||
free(info);
|
free(info);
|
||||||
if (client_proc_handle)
|
|
||||||
CloseHandle(client_proc_handle);
|
|
||||||
if (client_primary_token)
|
if (client_primary_token)
|
||||||
CloseHandle(client_primary_token);
|
CloseHandle(client_primary_token);
|
||||||
|
|
||||||
if (r == 0)
|
if (r == 0) {
|
||||||
|
con->client_process_handle = client_process_handle;
|
||||||
con->client_impersonation_token = client_impersonation_token;
|
con->client_impersonation_token = client_impersonation_token;
|
||||||
else if (client_impersonation_token)
|
}
|
||||||
CloseHandle(client_impersonation_token);
|
else {
|
||||||
|
if (client_process_handle)
|
||||||
|
CloseHandle(client_process_handle);
|
||||||
|
if (client_impersonation_token)
|
||||||
|
CloseHandle(client_impersonation_token);
|
||||||
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -4,17 +4,18 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#define MAX_MESSAGE_SIZE 256 * 1024
|
#define MAX_MESSAGE_SIZE 256 * 1024
|
||||||
|
|
||||||
#define SSH_ROOT L"SOFTWARE\\SSH"
|
#define SSH_ROOT L"SOFTWARE\\OpenSSH"
|
||||||
#define SSH_AGENT_ROOT SSH_ROOT L"\\Agent"
|
#define SSH_AGENT_ROOT SSH_ROOT L"\\Agent"
|
||||||
#define SSH_KEYS_KEY L"Keys"
|
#define SSH_KEYS_KEY L"Keys"
|
||||||
#define SSH_KEYS_ROOT SSH_ROOT L"\\" SSH_KEYS_KEY
|
#define SSH_KEYS_ROOT SSH_AGENT_ROOT L"\\" SSH_KEYS_KEY
|
||||||
|
|
||||||
#define HEADER_SIZE 4
|
#define HEADER_SIZE 4
|
||||||
|
|
||||||
struct agent_connection {
|
struct agent_connection {
|
||||||
OVERLAPPED ol;
|
OVERLAPPED ol;
|
||||||
HANDLE pipe_handle;
|
HANDLE pipe_handle;
|
||||||
HANDLE client_impersonation_token;
|
HANDLE client_impersonation_token;
|
||||||
|
HANDLE client_process_handle;
|
||||||
struct {
|
struct {
|
||||||
DWORD num_bytes;
|
DWORD num_bytes;
|
||||||
DWORD transferred;
|
DWORD transferred;
|
||||||
@ -36,8 +37,9 @@ struct agent_connection {
|
|||||||
SYSTEM, /* client is running as System */
|
SYSTEM, /* client is running as System */
|
||||||
SERVICE, /* client is running as LS or NS */
|
SERVICE, /* client is running as LS or NS */
|
||||||
} client_type;
|
} client_type;
|
||||||
HANDLE auth_token;
|
/* user profile related members */
|
||||||
HANDLE hProfile;
|
HANDLE profile_token;
|
||||||
|
HANDLE profile_handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
void agent_connection_on_io(struct agent_connection*, DWORD, OVERLAPPED*);
|
void agent_connection_on_io(struct agent_connection*, DWORD, OVERLAPPED*);
|
||||||
|
@ -72,6 +72,12 @@ mm_user_key_allowed(struct passwd *pw, Key *k, int i)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* mm_auth_pubkey(const char* user_name, const struct sshkey *key,
|
||||||
|
const u_char *sig, size_t slen, struct sshbuf* b)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
kexgex_server(struct ssh * sh) {
|
kexgex_server(struct ssh * sh) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include "agent-request.h"
|
#include "agent-request.h"
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
#include "inc\utf.h"
|
#include "inc\utf.h"
|
||||||
|
#include "..\priv-agent.h"
|
||||||
|
|
||||||
#pragma warning(push, 3)
|
#pragma warning(push, 3)
|
||||||
|
|
||||||
@ -83,9 +84,11 @@ done:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
static HANDLE
|
||||||
LoadProfile(struct agent_connection* con, wchar_t* user, wchar_t* domain) {
|
LoadProfile(HANDLE user_token, wchar_t* user, wchar_t* domain) {
|
||||||
PROFILEINFOW profileInfo;
|
PROFILEINFOW profileInfo;
|
||||||
|
HANDLE ret = NULL;
|
||||||
|
|
||||||
profileInfo.dwFlags = PI_NOUI;
|
profileInfo.dwFlags = PI_NOUI;
|
||||||
profileInfo.lpProfilePath = NULL;
|
profileInfo.lpProfilePath = NULL;
|
||||||
profileInfo.lpUserName = user;
|
profileInfo.lpUserName = user;
|
||||||
@ -96,12 +99,16 @@ LoadProfile(struct agent_connection* con, wchar_t* user, wchar_t* domain) {
|
|||||||
profileInfo.dwSize = sizeof(profileInfo);
|
profileInfo.dwSize = sizeof(profileInfo);
|
||||||
EnablePrivilege("SeBackupPrivilege", 1);
|
EnablePrivilege("SeBackupPrivilege", 1);
|
||||||
EnablePrivilege("SeRestorePrivilege", 1);
|
EnablePrivilege("SeRestorePrivilege", 1);
|
||||||
if (LoadUserProfileW(con->auth_token, &profileInfo) == FALSE)
|
if (LoadUserProfileW(user_token, &profileInfo) == FALSE) {
|
||||||
debug("Loading user (%ls,%ls) profile failed ERROR: %d", user, domain, GetLastError());
|
debug("Loading user (%ls,%ls) profile failed ERROR: %d", user, domain, GetLastError());
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
con->hProfile = profileInfo.hProfile;
|
ret = profileInfo.hProfile;
|
||||||
|
done:
|
||||||
EnablePrivilege("SeBackupPrivilege", 0);
|
EnablePrivilege("SeBackupPrivilege", 0);
|
||||||
EnablePrivilege("SeRestorePrivilege", 0);
|
EnablePrivilege("SeRestorePrivilege", 0);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_USER_LEN 64
|
#define MAX_USER_LEN 64
|
||||||
@ -238,73 +245,13 @@ done:
|
|||||||
return dup_t;
|
return dup_t;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO - SecureZeroMemory password */
|
|
||||||
int process_passwordauth_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
|
|
||||||
char *user = NULL, *domain = NULL, *pwd = NULL;
|
|
||||||
size_t user_len, pwd_len;
|
|
||||||
wchar_t *user_utf16 = NULL, *udom_utf16 = NULL, *pwd_utf16 = NULL, *tmp;
|
|
||||||
int r = -1;
|
|
||||||
HANDLE token = 0, dup_token;
|
|
||||||
|
|
||||||
if (sshbuf_get_cstring(request, &user, &user_len) != 0 ||
|
|
||||||
sshbuf_get_cstring(request, &pwd, &pwd_len) != 0 ||
|
|
||||||
user_len == 0 ||
|
|
||||||
pwd_len == 0 ||
|
|
||||||
user_len > MAX_USER_LEN + MAX_FQDN_LEN ||
|
|
||||||
pwd_len > MAX_PW_LEN) {
|
|
||||||
debug("bad password auth request");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((user_utf16 = utf8_to_utf16(user)) == NULL ||
|
|
||||||
(pwd_utf16 = utf8_to_utf16(pwd)) == NULL) {
|
|
||||||
debug("out of memory");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((tmp = wcschr(user_utf16, L'@') ) != NULL ) {
|
|
||||||
udom_utf16 = tmp + 1;
|
|
||||||
*tmp = L'\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LogonUserW(user_utf16, udom_utf16, pwd_utf16, LOGON32_LOGON_NETWORK_CLEARTEXT, LOGON32_PROVIDER_DEFAULT, &token) == FALSE) {
|
|
||||||
debug("failed to logon user: %ls domain: %ls", user_utf16, udom_utf16);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((dup_token = duplicate_token_for_client(con, token)) == NULL)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
if (sshbuf_put_u32(response, (int)(intptr_t)dup_token) != 0)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
con->auth_token = token;
|
|
||||||
LoadProfile(con, user_utf16, udom_utf16);
|
|
||||||
r = 0;
|
|
||||||
done:
|
|
||||||
/* TODO Fix this hacky protocol*/
|
|
||||||
if ((r == -1) && (sshbuf_put_u8(response, SSH_AGENT_FAILURE) == 0))
|
|
||||||
r = 0;
|
|
||||||
|
|
||||||
if (user)
|
|
||||||
free(user);
|
|
||||||
if (pwd)
|
|
||||||
free(pwd);
|
|
||||||
if (user_utf16)
|
|
||||||
free(user_utf16);
|
|
||||||
if (pwd_utf16)
|
|
||||||
free(pwd_utf16);
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
int process_pubkeyauth_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
|
int process_pubkeyauth_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
|
||||||
int r = -1;
|
int r = -1;
|
||||||
char *key_blob, *user, *sig, *blob;
|
char *key_blob, *user, *sig, *blob;
|
||||||
size_t key_blob_len, user_len, sig_len, blob_len;
|
size_t key_blob_len, user_len, sig_len, blob_len;
|
||||||
struct sshkey *key = NULL;
|
struct sshkey *key = NULL;
|
||||||
HANDLE token = NULL, dup_token = NULL;
|
HANDLE token = NULL, dup_token = NULL;
|
||||||
wchar_t *user_utf16 = NULL, *udom_utf16 = NULL, *tmp;
|
wchar_t *user_utf16 = NULL;
|
||||||
PWSTR wuser_home = NULL;
|
PWSTR wuser_home = NULL;
|
||||||
|
|
||||||
|
|
||||||
@ -346,14 +293,6 @@ int process_pubkeyauth_request(struct sshbuf* request, struct sshbuf* response,
|
|||||||
if (sshbuf_put_u32(response, (int)(intptr_t)dup_token) != 0)
|
if (sshbuf_put_u32(response, (int)(intptr_t)dup_token) != 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
con->auth_token = token;
|
|
||||||
token = NULL;
|
|
||||||
if ((tmp = wcschr(user_utf16, L'@')) != NULL) {
|
|
||||||
udom_utf16 = tmp + 1;
|
|
||||||
*tmp = L'\0';
|
|
||||||
}
|
|
||||||
LoadProfile(con, user_utf16, udom_utf16);
|
|
||||||
|
|
||||||
r = 0;
|
r = 0;
|
||||||
done:
|
done:
|
||||||
/* TODO Fix this hacky protocol*/
|
/* TODO Fix this hacky protocol*/
|
||||||
@ -373,7 +312,60 @@ done:
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int process_authagent_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
|
int process_loadprofile_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
|
||||||
|
int r = 0, success = 0;
|
||||||
|
char *user;
|
||||||
|
size_t user_len;
|
||||||
|
u_int32_t user_token_int = 0;
|
||||||
|
HANDLE user_token = NULL;
|
||||||
|
wchar_t *user_utf16 = NULL, *dom_utf16 = NULL, *tmp;
|
||||||
|
|
||||||
|
/* is profile already loaded */
|
||||||
|
if (con->profile_handle) {
|
||||||
|
success = 1;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sshbuf_get_cstring(request, &user, &user_len) != 0 ||
|
||||||
|
user_len > MAX_USER_LEN ||
|
||||||
|
sshbuf_get_u32(request, &user_token_int) != 0){
|
||||||
|
debug("invalid loadprofile request");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DuplicateHandle(con->client_process_handle, (HANDLE)(INT_PTR)user_token_int, GetCurrentProcess(),
|
||||||
|
&user_token, TOKEN_QUERY | TOKEN_IMPERSONATE | TOKEN_DUPLICATE, FALSE, 0) == FALSE) {
|
||||||
|
debug("cannot duplicate user token, error: %d", GetLastError());
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((user_utf16 = utf8_to_utf16(user)) == NULL) {
|
||||||
|
debug("out of memory");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* split user and domain */
|
||||||
|
if ((tmp = wcschr(user_utf16, L'@')) != NULL) {
|
||||||
|
dom_utf16 = tmp + 1;
|
||||||
|
*tmp = L'\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((con->profile_handle = LoadProfile(user_token, user_utf16, dom_utf16)) == NULL)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
con->profile_token = user_token;
|
||||||
|
user_token = NULL;
|
||||||
|
success = 1;
|
||||||
|
done:
|
||||||
|
if (sshbuf_put_u8(response, success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE) != 0)
|
||||||
|
r = -1;
|
||||||
|
|
||||||
|
if (user_token)
|
||||||
|
CloseHandle(user_token);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int process_privagent_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) {
|
||||||
char *opn;
|
char *opn;
|
||||||
size_t opn_len;
|
size_t opn_len;
|
||||||
if (sshbuf_get_string_direct(request, &opn, &opn_len) != 0) {
|
if (sshbuf_get_string_direct(request, &opn, &opn_len) != 0) {
|
||||||
@ -383,14 +375,14 @@ int process_authagent_request(struct sshbuf* request, struct sshbuf* response, s
|
|||||||
|
|
||||||
/* allow only admins and NT Service\sshd to send auth requests */
|
/* allow only admins and NT Service\sshd to send auth requests */
|
||||||
if (con->client_type != SSHD_SERVICE && con->client_type != ADMIN_USER) {
|
if (con->client_type != SSHD_SERVICE && con->client_type != ADMIN_USER) {
|
||||||
error("cannot authenticate: client process is not admin or sshd");
|
error("cannot process request: client process is not admin or sshd");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (memcmp(opn, PUBKEY_AUTH_REQUEST, opn_len) == 0)
|
if (memcmp(opn, PUBKEY_AUTH_REQUEST, opn_len) == 0)
|
||||||
return process_pubkeyauth_request(request, response, con);
|
return process_pubkeyauth_request(request, response, con);
|
||||||
else if (memcmp(opn, PASSWD_AUTH_REQUEST, opn_len) == 0)
|
else if (memcmp(opn, LOAD_USER_PROFILE_REQUEST, opn_len) == 0)
|
||||||
return process_passwordauth_request(request, response, con);
|
return process_loadprofile_request(request, response, con);
|
||||||
else {
|
else {
|
||||||
debug("unknown auth request: %s", opn);
|
debug("unknown auth request: %s", opn);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "agent.h"
|
#include "agent.h"
|
||||||
#include "agent-request.h"
|
#include "agent-request.h"
|
||||||
|
#include "..\priv-agent.h"
|
||||||
|
|
||||||
#pragma warning(push, 3)
|
#pragma warning(push, 3)
|
||||||
|
|
||||||
@ -168,8 +169,8 @@ process_request(struct agent_connection* con)
|
|||||||
case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
|
case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
|
||||||
r = process_remove_all(request, response, con);
|
r = process_remove_all(request, response, con);
|
||||||
break;
|
break;
|
||||||
case SSH_AGENT_AUTHENTICATE:
|
case SSH_PRIV_AGENT_MSG_ID:
|
||||||
r = process_authagent_request(request, response, con);
|
r = process_privagent_request(request, response, con);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
debug("unknown agent request %d", type);
|
debug("unknown agent request %d", type);
|
||||||
|
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)
|
if (getenv("SSH_AUTH_SOCK") == NULL)
|
||||||
_putenv("SSH_AUTH_SOCK=ssh-agent");
|
_putenv("SSH_AUTH_SOCK=\\\\.\\pipe\\openssh-ssh-agent");
|
||||||
|
|
||||||
w32posix_initialize();
|
w32posix_initialize();
|
||||||
|
|
||||||
|
@ -108,9 +108,6 @@ int sshd_main(int argc, wchar_t **wargv) {
|
|||||||
argv[i] = utf16_to_utf8(wargv[i]);
|
argv[i] = utf16_to_utf8(wargv[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getenv("SSH_AUTH_SOCK") == NULL)
|
|
||||||
_putenv("SSH_AUTH_SOCK=ssh-agent");
|
|
||||||
|
|
||||||
w32posix_initialize();
|
w32posix_initialize();
|
||||||
if (getenv("SSHD_REMSOC"))
|
if (getenv("SSHD_REMSOC"))
|
||||||
is_child = 1;
|
is_child = 1;
|
||||||
|
@ -98,4 +98,9 @@ int mm_bsdauth_respond(void *, u_int, char **);
|
|||||||
int mm_skey_query(void *, char **, char **, u_int *, char ***, u_int **);
|
int mm_skey_query(void *, char **, char **, u_int *, char ***, u_int **);
|
||||||
int mm_skey_respond(void *, u_int, char **);
|
int mm_skey_respond(void *, u_int, char **);
|
||||||
|
|
||||||
|
/* Windows specific */
|
||||||
|
void* mm_auth_pubkey(const char*, const struct sshkey *, const u_char *, size_t,
|
||||||
|
struct sshbuf*);
|
||||||
|
int mm_load_profile(const char*, u_int );
|
||||||
|
|
||||||
#endif /* _MM_WRAP_H_ */
|
#endif /* _MM_WRAP_H_ */
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force -DisableNameChecking
|
If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
|
||||||
|
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force
|
||||||
|
Import-Module OpenSSHUtils -Force
|
||||||
$tC = 1
|
$tC = 1
|
||||||
$tI = 0
|
$tI = 0
|
||||||
$suite = "authorized_keys_fileperm"
|
$suite = "authorized_keys_fileperm"
|
||||||
@ -6,7 +8,7 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
|
|||||||
BeforeAll {
|
BeforeAll {
|
||||||
if($OpenSSHTestInfo -eq $null)
|
if($OpenSSHTestInfo -eq $null)
|
||||||
{
|
{
|
||||||
Throw "`$OpenSSHTestInfo is null. Please run Setup-OpenSSHTestEnvironment to setup test environment."
|
Throw "`$OpenSSHTestInfo is null. Please run Set-OpenSSHTestEnvironment to set test environments."
|
||||||
}
|
}
|
||||||
|
|
||||||
$testDir = "$($OpenSSHTestInfo["TestDataPath"])\$suite"
|
$testDir = "$($OpenSSHTestInfo["TestDataPath"])\$suite"
|
||||||
@ -22,17 +24,31 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
|
|||||||
$ssouser = $OpenSSHTestInfo["SSOUser"]
|
$ssouser = $OpenSSHTestInfo["SSOUser"]
|
||||||
$PwdUser = $OpenSSHTestInfo["PasswdUser"]
|
$PwdUser = $OpenSSHTestInfo["PasswdUser"]
|
||||||
$ssouserProfile = $OpenSSHTestInfo["SSOUserProfile"]
|
$ssouserProfile = $OpenSSHTestInfo["SSOUserProfile"]
|
||||||
Remove-Item -Path (Join-Path $testDir "*$fileName") -Force -ErrorAction ignore
|
Remove-Item -Path (Join-Path $testDir "*$fileName") -Force -ErrorAction SilentlyContinue
|
||||||
|
$platform = Get-Platform
|
||||||
|
$skip = ($platform -eq [PlatformType]::Windows) -and ($PSVersionTable.PSVersion.Major -le 2)
|
||||||
|
if(($platform -eq [PlatformType]::Windows) -and ($psversiontable.BuildVersion.Major -le 6))
|
||||||
|
{
|
||||||
|
#suppress the firewall blocking dialogue on win7
|
||||||
|
netsh advfirewall firewall add rule name="sshd" program="$($OpenSSHTestInfo['OpenSSHBinPath'])\sshd.exe" protocol=any action=allow dir=in
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AfterEach { $tI++ }
|
AfterEach { $tI++ }
|
||||||
|
|
||||||
|
AfterAll {
|
||||||
|
if(($platform -eq [PlatformType]::Windows) -and ($psversiontable.BuildVersion.Major -le 6))
|
||||||
|
{
|
||||||
|
netsh advfirewall firewall delete rule name="sshd" program="$($OpenSSHTestInfo['OpenSSHBinPath'])\sshd.exe" protocol=any dir=in
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Context "Authorized key file permission" {
|
Context "Authorized key file permission" {
|
||||||
BeforeAll {
|
BeforeAll {
|
||||||
$systemAccount = New-Object System.Security.Principal.NTAccount("NT AUTHORITY", "SYSTEM")
|
$systemSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::LocalSystemSid)
|
||||||
$adminAccount = New-Object System.Security.Principal.NTAccount("BUILTIN","Administrators")
|
$adminsSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid)
|
||||||
$objUser = New-Object System.Security.Principal.NTAccount($ssouser)
|
$currentUserSid = Get-UserSID -User "$($env:USERDOMAIN)\$($env:USERNAME)"
|
||||||
$currentUser = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME))
|
$objUserSid = Get-UserSID -User $ssouser
|
||||||
|
|
||||||
$ssouserSSHProfilePath = Join-Path $ssouserProfile .testssh
|
$ssouserSSHProfilePath = Join-Path $ssouserProfile .testssh
|
||||||
if(-not (Test-Path $ssouserSSHProfilePath -PathType Container)) {
|
if(-not (Test-Path $ssouserSSHProfilePath -PathType Container)) {
|
||||||
@ -43,21 +59,22 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
|
|||||||
$testknownhosts = Join-path $PSScriptRoot testdata\test_known_hosts
|
$testknownhosts = Join-path $PSScriptRoot testdata\test_known_hosts
|
||||||
Copy-Item $Source $ssouserSSHProfilePath -Force -ErrorAction Stop
|
Copy-Item $Source $ssouserSSHProfilePath -Force -ErrorAction Stop
|
||||||
|
|
||||||
Adjust-UserKeyFileACL -Filepath $authorizedkeyPath -Owner $objUser -OwnerPerms "Read, Write"
|
Repair-AuthorizedKeyPermission -Filepath $authorizedkeyPath -confirm:$false
|
||||||
|
|
||||||
Get-Process -Name sshd | Where-Object {$_.SI -ne 0} | Stop-process
|
Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
|
||||||
#add wrong password so ssh does not prompt password if failed with authorized keys
|
#add wrong password so ssh does not prompt password if failed with authorized keys
|
||||||
Add-PasswordSetting -Pass "WrongPass"
|
Add-PasswordSetting -Pass "WrongPass"
|
||||||
$tI=1
|
$tI=1
|
||||||
}
|
}
|
||||||
|
|
||||||
AfterAll {
|
AfterAll {
|
||||||
|
Repair-AuthorizedKeyPermission -Filepath $authorizedkeyPath -confirm:$false
|
||||||
if(Test-Path $authorizedkeyPath) {
|
if(Test-Path $authorizedkeyPath) {
|
||||||
Adjust-UserKeyFileACL -Filepath $authorizedkeyPath -Owner $objUser -OwnerPerms "Read, Write"
|
Repair-AuthorizedKeyPermission -Filepath $authorizedkeyPath -confirm:$false
|
||||||
Remove-Item $authorizedkeyPath -Force -ErrorAction Ignore
|
Remove-Item $authorizedkeyPath -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
if(Test-Path $ssouserSSHProfilePath) {
|
if(Test-Path $ssouserSSHProfilePath) {
|
||||||
Remove-Item $ssouserSSHProfilePath -Force -ErrorAction Ignore -Recurse
|
Remove-Item $ssouserSSHProfilePath -Force -ErrorAction SilentlyContinue -Recurse
|
||||||
}
|
}
|
||||||
Remove-PasswordSetting
|
Remove-PasswordSetting
|
||||||
$tC++
|
$tC++
|
||||||
@ -66,11 +83,12 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
|
|||||||
BeforeEach {
|
BeforeEach {
|
||||||
$filePath = Join-Path $testDir "$tC.$tI.$fileName"
|
$filePath = Join-Path $testDir "$tC.$tI.$fileName"
|
||||||
$logPath = Join-Path $testDir "$tC.$tI.$logName"
|
$logPath = Join-Path $testDir "$tC.$tI.$logName"
|
||||||
|
Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
It "$tC.$tI-authorized_keys-positive(pwd user is the owner and running process can access to the file)" {
|
It "$tC.$tI-authorized_keys-positive(pwd user is the owner and running process can access to the file)" {
|
||||||
#setup to have ssouser as owner and grant ssouser read and write, admins group, and local system full control
|
#setup to have ssouser as owner and grant ssouser read and write, admins group, and local system full control
|
||||||
Adjust-UserKeyFileACL -Filepath $authorizedkeyPath -Owner $objUser -OwnerPerms "Read, Write"
|
Repair-FilePermission -Filepath $authorizedkeyPath -Owners $objUserSid -FullAccessNeeded $adminsSid,$systemSid,$objUserSid -confirm:$false
|
||||||
|
|
||||||
#Run
|
#Run
|
||||||
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow
|
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow
|
||||||
@ -78,14 +96,12 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
|
|||||||
$o | Should Be "1234"
|
$o | Should Be "1234"
|
||||||
|
|
||||||
#Cleanup
|
#Cleanup
|
||||||
Get-Process -Name sshd | % { if($_.SI -ne 0) { Start-sleep 1; Stop-Process $_; Start-sleep 1 } }
|
Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
It "$tC.$tI-authorized_keys-positive(authorized_keys is owned by local system)" {
|
It "$tC.$tI-authorized_keys-positive(authorized_keys is owned by local system)" {
|
||||||
#setup to have system as owner and grant it full control
|
#setup to have system as owner and grant it full control
|
||||||
Set-FileOwnerAndACL -Filepath $authorizedkeyPath -Owner $systemAccount -OwnerPerms "FullControl"
|
Repair-FilePermission -Filepath $authorizedkeyPath -Owner $systemSid -FullAccessNeeded $adminsSid,$systemSid,$objUserSid -confirm:$false
|
||||||
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $adminAccount -Perms "FullControl"
|
|
||||||
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $objUser -Perms "Read, Write"
|
|
||||||
|
|
||||||
#Run
|
#Run
|
||||||
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow
|
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow
|
||||||
@ -93,14 +109,12 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
|
|||||||
$o | Should Be "1234"
|
$o | Should Be "1234"
|
||||||
|
|
||||||
#Cleanup
|
#Cleanup
|
||||||
Get-Process -Name sshd | % { if($_.SI -ne 0) { Start-sleep 1; Stop-Process $_; Start-sleep 1 } }
|
Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
It "$tC.$tI-authorized_keys-positive(authorized_keys is owned by admins group and pwd does not have explict ACE)" {
|
It "$tC.$tI-authorized_keys-positive(authorized_keys is owned by admins group and pwd does not have explict ACE)" {
|
||||||
#setup to have admin group as owner and grant it full control
|
#setup to have admin group as owner and grant it full control
|
||||||
|
Repair-FilePermission -Filepath $authorizedkeyPath -Owner $adminsSid -FullAccessNeeded $adminsSid,$systemSid -confirm:$false
|
||||||
Set-FileOwnerAndACL -Filepath $authorizedkeyPath -Owner $adminAccount -OwnerPerms "FullControl"
|
|
||||||
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $systemAccount -Perms "FullControl"
|
|
||||||
|
|
||||||
#Run
|
#Run
|
||||||
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow
|
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow
|
||||||
@ -108,15 +122,12 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
|
|||||||
$o | Should Be "1234"
|
$o | Should Be "1234"
|
||||||
|
|
||||||
#Cleanup
|
#Cleanup
|
||||||
Get-Process -Name sshd | % { if($_.SI -ne 0) { Start-sleep 1; Stop-Process $_; Start-sleep 1 } }
|
Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
It "$tC.$tI-authorized_keys-positive(authorized_keys is owned by admins group and pwd have explict ACE)" {
|
It "$tC.$tI-authorized_keys-positive(authorized_keys is owned by admins group and pwd have explict ACE)" {
|
||||||
#setup to have admin group as owner and grant it full control
|
#setup to have admin group as owner and grant it full control
|
||||||
|
Repair-FilePermission -Filepath $authorizedkeyPath -Owner $adminsSid -FullAccessNeeded $adminsSid,$systemSid,$objUserSid -confirm:$false
|
||||||
Set-FileOwnerAndACL -Filepath $authorizedkeyPath -Owner $adminAccount -OwnerPerms "FullControl"
|
|
||||||
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $systemAccount -Perms "FullControl"
|
|
||||||
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $objUser -Perms "Read, Write"
|
|
||||||
|
|
||||||
#Run
|
#Run
|
||||||
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow
|
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow
|
||||||
@ -124,14 +135,12 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
|
|||||||
$o | Should Be "1234"
|
$o | Should Be "1234"
|
||||||
|
|
||||||
#Cleanup
|
#Cleanup
|
||||||
Get-Process -Name sshd | % { if($_.SI -ne 0) { Start-sleep 1; Stop-Process $_; Start-sleep 1 } }
|
Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
It "$tC.$tI-authorized_keys-negative(authorized_keys is owned by other admin user)" {
|
It "$tC.$tI-authorized_keys-negative(authorized_keys is owned by other admin user)" {
|
||||||
#setup to have current user (admin user) as owner and grant it full control
|
#setup to have current user (admin user) as owner and grant it full control
|
||||||
Set-FileOwnerAndACL -Filepath $authorizedkeyPath -Owner $currentUser -OwnerPerms "Read","Write"
|
Repair-FilePermission -Filepath $authorizedkeyPath -Owner $currentUserSid -FullAccessNeeded $adminsSid,$systemSid -confirm:$false
|
||||||
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $systemAccount -Perms "FullControl"
|
|
||||||
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $adminAccount -Perms "FullControl"
|
|
||||||
|
|
||||||
#Run
|
#Run
|
||||||
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow
|
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow
|
||||||
@ -141,18 +150,16 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
|
|||||||
$matches.Count | Should BeGreaterThan 2
|
$matches.Count | Should BeGreaterThan 2
|
||||||
|
|
||||||
#Cleanup
|
#Cleanup
|
||||||
Get-Process -Name sshd | % { if($_.SI -ne 0) { Start-sleep 1; Stop-Process $_; Start-sleep 1 } }
|
Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
It "$tC.$tI-authorized_keys-negative(other account can access private key file)" {
|
It "$tC.$tI-authorized_keys-negative(other account can access private key file)" {
|
||||||
#setup to have current user as owner and grant it full control
|
#setup to have current user as owner and grant it full control
|
||||||
Set-FileOwnerAndACL -Filepath $authorizedkeyPath -Owner $objUser -OwnerPerms "Read","Write"
|
Repair-FilePermission -Filepath $authorizedkeyPath -Owner $objUserSid -FullAccessNeeded $adminsSid,$systemSid,$objUserSid -confirm:$false
|
||||||
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $systemAccount -Perms "FullControl"
|
|
||||||
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $adminAccount -Perms "FullControl"
|
|
||||||
|
|
||||||
#add $PwdUser to access the file authorized_keys
|
#add $PwdUser to access the file authorized_keys
|
||||||
$objPwdUser = New-Object System.Security.Principal.NTAccount($PwdUser)
|
$objPwdUserSid = Get-UserSid -User $PwdUser
|
||||||
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $objPwdUser -Perm "Read"
|
Set-FilePermission -FilePath $authorizedkeyPath -User $objPwdUserSid -Perm "Read"
|
||||||
|
|
||||||
#Run
|
#Run
|
||||||
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow
|
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow
|
||||||
@ -162,15 +169,13 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
|
|||||||
$matches.Count | Should BeGreaterThan 2
|
$matches.Count | Should BeGreaterThan 2
|
||||||
|
|
||||||
#Cleanup
|
#Cleanup
|
||||||
Get-Process -Name sshd | % { if($_.SI -ne 0) { Start-sleep 1; Stop-Process $_; Start-sleep 1 } }
|
Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
It "$tC.$tI-authorized_keys-negative(authorized_keys is owned by other non-admin user)" {
|
It "$tC.$tI-authorized_keys-negative(authorized_keys is owned by other non-admin user)" {
|
||||||
#setup to have PwdUser as owner and grant it full control
|
#setup to have PwdUser as owner and grant it full control
|
||||||
$objPwdUser = New-Object System.Security.Principal.NTAccount($PwdUser)
|
$objPwdUserSid = Get-UserSid -User $PwdUser
|
||||||
Set-FileOwnerAndACL -Filepath $authorizedkeyPath -owner $objPwdUser -OwnerPerms "Read","Write"
|
Repair-FilePermission -Filepath $authorizedkeyPath -Owner $objPwdUserSid -FullAccessNeeded $adminsSid,$systemSid,$objPwdUser -confirm:$false
|
||||||
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $systemAccount -Perms "FullControl"
|
|
||||||
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $adminAccount -Perms "FullControl"
|
|
||||||
|
|
||||||
#Run
|
#Run
|
||||||
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow
|
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow
|
||||||
@ -180,12 +185,12 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
|
|||||||
$matches.Count | Should BeGreaterThan 2
|
$matches.Count | Should BeGreaterThan 2
|
||||||
|
|
||||||
#Cleanup
|
#Cleanup
|
||||||
Get-Process -Name sshd | % { if($_.SI -ne 0) { Start-sleep 1; Stop-Process $_; Start-sleep 1 } }
|
Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
It "$tC.$tI-authorized_keys-negative(the running process does not have read access to the authorized_keys)" {
|
It "$tC.$tI-authorized_keys-negative(the running process does not have read access to the authorized_keys)" -skip:$skip {
|
||||||
#setup to have ssouser as owner and grant it full control
|
#setup to have ssouser as owner and grant it full control
|
||||||
Set-FileOwnerAndACL -Filepath $authorizedkeyPath -Owner $objUser -OwnerPerms "Read","Write"
|
Repair-FilePermission -Filepath $authorizedkeyPath -Owner $objUserSid -FullAccessNeeded $systemSid,$objUserSid -confirm:$false
|
||||||
Add-PermissionToFileACL -FilePath $authorizedkeyPath -User $systemAccount -Perms "FullControl"
|
Set-FilePermission -Filepath $authorizedkeyPath -UserSid $adminsSid -Action Delete
|
||||||
|
|
||||||
#Run
|
#Run
|
||||||
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow
|
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-o `"AuthorizedKeysFile .testssh/authorized_keys`"", "-E $logPath") -NoNewWindow
|
||||||
@ -196,7 +201,7 @@ Describe "Tests for authorized_keys file permission" -Tags "CI" {
|
|||||||
$matches.Count | Should BeGreaterThan 2
|
$matches.Count | Should BeGreaterThan 2
|
||||||
|
|
||||||
#Cleanup
|
#Cleanup
|
||||||
Get-Process -Name sshd | % { if($_.SI -ne 0) { Start-sleep 1; Stop-Process $_; Start-sleep 1 } }
|
Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force -DisableNameChecking
|
If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
|
||||||
|
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force
|
||||||
$tC = 1
|
$tC = 1
|
||||||
$tI = 0
|
$tI = 0
|
||||||
$suite = "authorized_keys_fileperm"
|
$suite = "authorized_keys_fileperm"
|
||||||
@ -6,7 +7,7 @@ Describe "Tests for ssh config" -Tags "CI" {
|
|||||||
BeforeAll {
|
BeforeAll {
|
||||||
if($OpenSSHTestInfo -eq $null)
|
if($OpenSSHTestInfo -eq $null)
|
||||||
{
|
{
|
||||||
Throw "`$OpenSSHTestInfo is null. Please run Setup-OpenSSHTestEnvironment to setup test environment."
|
Throw "`$OpenSSHTestInfo is null. Please run Set-OpenSSHTestEnvironment to set test environments."
|
||||||
}
|
}
|
||||||
|
|
||||||
if(-not (Test-Path $OpenSSHTestInfo["TestDataPath"]))
|
if(-not (Test-Path $OpenSSHTestInfo["TestDataPath"]))
|
||||||
@ -27,38 +28,39 @@ Describe "Tests for ssh config" -Tags "CI" {
|
|||||||
# for the first time, delete the existing log files.
|
# for the first time, delete the existing log files.
|
||||||
if ($OpenSSHTestInfo['DebugMode'])
|
if ($OpenSSHTestInfo['DebugMode'])
|
||||||
{
|
{
|
||||||
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction ignore
|
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue
|
||||||
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction ignore
|
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction SilentlyContinue
|
||||||
Remove-Item -Path (Join-Path $testDir "*log*.log") -Force -ErrorAction ignore
|
Remove-Item -Path (Join-Path $testDir "*log*.log") -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
Remove-Item -Path (Join-Path $testDir "*logName") -Force -ErrorAction ignore
|
Remove-Item -Path (Join-Path $testDir "*logName") -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
AfterEach {
|
AfterEach {
|
||||||
if( $OpenSSHTestInfo["DebugMode"])
|
if( $OpenSSHTestInfo["DebugMode"])
|
||||||
{
|
{
|
||||||
Copy-Item "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" "$testDir\agentlog$tC.$tI.log" -Force -ErrorAction ignore
|
Copy-Item "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" "$testDir\agentlog$tC.$tI.log" -Force -ErrorAction SilentlyContinue
|
||||||
Copy-Item "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" "$testDir\sshdlog$tC.$tI.log" -Force -ErrorAction ignore
|
Copy-Item "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" "$testDir\sshdlog$tC.$tI.log" -Force -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
#Clear the ssh-agent, sshd logs so that next testcase will get fresh logs.
|
#Clear the ssh-agent, sshd logs so that next testcase will get fresh logs.
|
||||||
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction ignore
|
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue
|
||||||
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction ignore
|
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
$tI++
|
$tI++
|
||||||
}
|
}
|
||||||
|
|
||||||
Context "$tC-User SSHConfig--ReadConfig" {
|
Context "$tC-User SSHConfig--ReadConfig" {
|
||||||
BeforeAll {
|
BeforeAll {
|
||||||
$systemAccount = New-Object System.Security.Principal.NTAccount("NT AUTHORITY", "SYSTEM")
|
$systemSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::LocalSystemSid)
|
||||||
$adminAccount = New-Object System.Security.Principal.NTAccount("BUILTIN","Administrators")
|
$adminsSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid)
|
||||||
$objUser = New-Object System.Security.Principal.NTAccount($ssouser)
|
$currentUserSid = Get-UserSID -User "$($env:USERDOMAIN)\$($env:USERNAME)"
|
||||||
$currentUser = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME))
|
$objUserSid = Get-UserSID -User $ssouser
|
||||||
|
|
||||||
$userConfigFile = Join-Path $home ".ssh\config"
|
$userConfigFile = Join-Path $home ".ssh\config"
|
||||||
if( -not (Test-path $userConfigFile) ) {
|
if( -not (Test-path $userConfigFile) ) {
|
||||||
Copy-item "$PSScriptRoot\testdata\ssh_config" $userConfigFile -force
|
Copy-item "$PSScriptRoot\testdata\ssh_config" $userConfigFile -force
|
||||||
}
|
}
|
||||||
|
Enable-Privilege SeRestorePrivilege | out-null
|
||||||
$oldACL = Get-ACL $userConfigFile
|
$oldACL = Get-ACL $userConfigFile
|
||||||
$tI=1
|
$tI=1
|
||||||
}
|
}
|
||||||
@ -68,7 +70,7 @@ Describe "Tests for ssh config" -Tags "CI" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AfterEach {
|
AfterEach {
|
||||||
Set-Acl -Path $userConfigFile -AclObject $oldACL
|
Set-Acl -Path $userConfigFile -AclObject $oldACL -confirm:$false
|
||||||
}
|
}
|
||||||
|
|
||||||
AfterAll {
|
AfterAll {
|
||||||
@ -77,9 +79,7 @@ Describe "Tests for ssh config" -Tags "CI" {
|
|||||||
|
|
||||||
It "$tC.$tI-User SSHConfig-ReadConfig positive (current logon user is the owner)" {
|
It "$tC.$tI-User SSHConfig-ReadConfig positive (current logon user is the owner)" {
|
||||||
#setup
|
#setup
|
||||||
Set-FileOwnerAndACL -Filepath $userConfigFile -Owner $currentUser -OwnerPerms "Read","Write"
|
Repair-FilePermission -Filepath $userConfigFile -Owners $currentUserSid -FullAccessNeeded $adminsSid,$systemSid,$currentUserSid -confirm:$false
|
||||||
Add-PermissionToFileACL -FilePath $userConfigFile -User $systemAccount -Perms "FullControl"
|
|
||||||
Add-PermissionToFileACL -FilePath $userConfigFile -User $adminAccount -Perms "FullControl"
|
|
||||||
|
|
||||||
#Run
|
#Run
|
||||||
$o = ssh test_target echo 1234
|
$o = ssh test_target echo 1234
|
||||||
@ -88,8 +88,7 @@ Describe "Tests for ssh config" -Tags "CI" {
|
|||||||
|
|
||||||
It "$tC.$tI-User SSHConfig-ReadConfig positive (local system is the owner)" {
|
It "$tC.$tI-User SSHConfig-ReadConfig positive (local system is the owner)" {
|
||||||
#setup
|
#setup
|
||||||
Set-FileOwnerAndACL -Filepath $userConfigFile -Owner $systemAccount -OwnerPerms "FullControl"
|
Repair-FilePermission -Filepath $userConfigFile -Owners $systemSid -FullAccessNeeded $adminsSid,$systemSid -confirm:$false
|
||||||
Add-PermissionToFileACL -FilePath $userConfigFile -User $adminAccount -Perms "FullControl"
|
|
||||||
|
|
||||||
#Run
|
#Run
|
||||||
$o = ssh test_target echo 1234
|
$o = ssh test_target echo 1234
|
||||||
@ -98,8 +97,8 @@ Describe "Tests for ssh config" -Tags "CI" {
|
|||||||
|
|
||||||
It "$tC.$tI-User SSHConfig-ReadConfig positive (admin is the owner and current user has no explict ACE)" {
|
It "$tC.$tI-User SSHConfig-ReadConfig positive (admin is the owner and current user has no explict ACE)" {
|
||||||
#setup
|
#setup
|
||||||
Set-FileOwnerAndACL -Filepath $userConfigFile -Owner $adminAccount -OwnerPerms "FullControl"
|
Repair-FilePermission -Filepath $userConfigFile -Owners $adminsSid -FullAccessNeeded $adminsSid,$systemSid -confirm:$false
|
||||||
Add-PermissionToFileACL -FilePath $userConfigFile -User $systemAccount -Perms "FullControl"
|
Set-FilePermission -Filepath $userConfigFile -UserSid $currentUserSid -Action Delete
|
||||||
|
|
||||||
#Run
|
#Run
|
||||||
$o = ssh test_target echo 1234
|
$o = ssh test_target echo 1234
|
||||||
@ -108,9 +107,7 @@ Describe "Tests for ssh config" -Tags "CI" {
|
|||||||
|
|
||||||
It "$tC.$tI-User SSHConfig-ReadConfig positive (admin is the owner and current user has explict ACE)" {
|
It "$tC.$tI-User SSHConfig-ReadConfig positive (admin is the owner and current user has explict ACE)" {
|
||||||
#setup
|
#setup
|
||||||
Set-FileOwnerAndACL -Filepath $userConfigFile -Owner $adminAccount -OwnerPerms "FullControl"
|
Repair-FilePermission -Filepath $userConfigFile -Owners $adminsSid -FullAccessNeeded $adminsSid,$systemSid,$currentUserSid -confirm:$false
|
||||||
Add-PermissionToFileACL -FilePath $userConfigFile -User $systemAccount -Perms "FullControl"
|
|
||||||
Add-PermissionToFileACL -FilePath $userConfigFile -User $currentUser -Perms "Read, Write"
|
|
||||||
|
|
||||||
#Run
|
#Run
|
||||||
$o = ssh test_target echo 1234
|
$o = ssh test_target echo 1234
|
||||||
@ -119,9 +116,7 @@ Describe "Tests for ssh config" -Tags "CI" {
|
|||||||
|
|
||||||
It "$tC.$tI-User SSHConfig-ReadConfig negative (wrong owner)" {
|
It "$tC.$tI-User SSHConfig-ReadConfig negative (wrong owner)" {
|
||||||
#setup
|
#setup
|
||||||
Set-FileOwnerAndACL -Filepath $userConfigFile -Owner $ssouser -OwnerPerms "Read","Write"
|
Repair-FilePermission -Filepath $userConfigFile -Owners $objUserSid -FullAccessNeeded $adminsSid,$systemSid,$objUserSid -confirm:$false
|
||||||
Add-PermissionToFileACL -FilePath $userConfigFile -User $systemAccount -Perms "FullControl"
|
|
||||||
Add-PermissionToFileACL -FilePath $userConfigFile -User $adminAccount -Perms "FullControl"
|
|
||||||
|
|
||||||
#Run
|
#Run
|
||||||
cmd /c "ssh test_target echo 1234 2> $logPath"
|
cmd /c "ssh test_target echo 1234 2> $logPath"
|
||||||
@ -131,10 +126,7 @@ Describe "Tests for ssh config" -Tags "CI" {
|
|||||||
|
|
||||||
It "$tC.$tI-User SSHConfig-ReadConfig negative (others has permission)" {
|
It "$tC.$tI-User SSHConfig-ReadConfig negative (others has permission)" {
|
||||||
#setup
|
#setup
|
||||||
Set-FileOwnerAndACL -Filepath $userConfigFile -Owner $currentUser -OwnerPerms "Read","Write"
|
Repair-FilePermission -Filepath $userConfigFile -Owners $currentUserSid -FullAccessNeeded $adminsSid,$systemSid,$currentUserSid -ReadAccessNeeded $objUserSid -confirm:$false
|
||||||
Add-PermissionToFileACL -FilePath $userConfigFile -User $systemAccount -Perms "FullControl"
|
|
||||||
Add-PermissionToFileACL -FilePath $userConfigFile -User $adminAccount -Perms "FullControl"
|
|
||||||
Add-PermissionToFileACL -FilePath $userConfigFile -User $objUser -Perms "Read"
|
|
||||||
|
|
||||||
#Run
|
#Run
|
||||||
cmd /c "ssh test_target echo 1234 2> $logPath"
|
cmd /c "ssh test_target echo 1234 2> $logPath"
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
Enum PlatformType {
|
Import-Module OpenSSHUtils -Force
|
||||||
Windows
|
|
||||||
Linux
|
Add-Type -TypeDefinition @"
|
||||||
OSX
|
public enum PlatformType
|
||||||
}
|
{
|
||||||
|
Windows,
|
||||||
|
Linux,
|
||||||
|
OSX
|
||||||
|
}
|
||||||
|
"@
|
||||||
|
|
||||||
function Get-Platform {
|
function Get-Platform {
|
||||||
# Use the .NET Core APIs to determine the current platform; if a runtime
|
# Use the .NET Core APIs to determine the current platform; if a runtime
|
||||||
@ -31,157 +36,59 @@ function Get-Platform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
<#
|
function Set-FilePermission
|
||||||
.Synopsis
|
|
||||||
user key should be owned by current user account
|
|
||||||
private key can be accessed only by the file owner, localsystem and Administrators
|
|
||||||
public user key can be accessed by only file owner, localsystem and Administrators and read by everyone
|
|
||||||
|
|
||||||
.Outputs
|
|
||||||
N/A
|
|
||||||
|
|
||||||
.Inputs
|
|
||||||
FilePath - The path to the file
|
|
||||||
Owner - The file owner
|
|
||||||
OwnerPerms - The permissions grant to owner
|
|
||||||
#>
|
|
||||||
function Adjust-UserKeyFileACL
|
|
||||||
{
|
|
||||||
param (
|
|
||||||
[parameter(Mandatory=$true)]
|
|
||||||
[string]$FilePath,
|
|
||||||
[System.Security.Principal.NTAccount] $Owner = $null,
|
|
||||||
[System.Security.AccessControl.FileSystemRights[]] $OwnerPerms = $null
|
|
||||||
)
|
|
||||||
|
|
||||||
$myACL = Get-ACL $FilePath
|
|
||||||
$myACL.SetAccessRuleProtection($True, $FALSE)
|
|
||||||
Set-Acl -Path $FilePath -AclObject $myACL
|
|
||||||
|
|
||||||
$systemAccount = New-Object System.Security.Principal.NTAccount("NT AUTHORITY", "SYSTEM")
|
|
||||||
$adminAccount = New-Object System.Security.Principal.NTAccount("BUILTIN","Administrators")
|
|
||||||
$everyoneAccount = New-Object System.Security.Principal.NTAccount("EveryOne")
|
|
||||||
$myACL = Get-ACL $FilePath
|
|
||||||
|
|
||||||
$actualOwner = $null
|
|
||||||
if($Owner -eq $null)
|
|
||||||
{
|
|
||||||
$actualOwner = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME))
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$actualOwner = $Owner
|
|
||||||
}
|
|
||||||
|
|
||||||
$myACL.SetOwner($actualOwner)
|
|
||||||
|
|
||||||
if($myACL.Access)
|
|
||||||
{
|
|
||||||
$myACL.Access | % {
|
|
||||||
if(-not ($myACL.RemoveAccessRule($_)))
|
|
||||||
{
|
|
||||||
throw "failed to remove access of $($_.IdentityReference.Value) rule in setup "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$adminACE = New-Object System.Security.AccessControl.FileSystemAccessRule `
|
|
||||||
($adminAccount, "FullControl", "None", "None", "Allow")
|
|
||||||
$myACL.AddAccessRule($adminACE)
|
|
||||||
|
|
||||||
$systemACE = New-Object System.Security.AccessControl.FileSystemAccessRule `
|
|
||||||
($systemAccount, "FullControl", "None", "None", "Allow")
|
|
||||||
$myACL.AddAccessRule($systemACE)
|
|
||||||
|
|
||||||
if(-not ($actualOwner.Equals($adminAccount)) -and (-not $actualOwner.Equals($systemAccount)) -and $OwnerPerms)
|
|
||||||
{
|
|
||||||
$OwnerPerms | % {
|
|
||||||
$ownerACE = New-Object System.Security.AccessControl.FileSystemAccessRule `
|
|
||||||
($actualOwner, $_, "None", "None", "Allow")
|
|
||||||
$myACL.AddAccessRule($ownerACE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if($FilePath.EndsWith(".pub"))
|
|
||||||
{
|
|
||||||
$everyoneAce = New-Object System.Security.AccessControl.FileSystemAccessRule `
|
|
||||||
("Everyone", "Read", "None", "None", "Allow")
|
|
||||||
$myACL.AddAccessRule($everyoneAce)
|
|
||||||
}
|
|
||||||
|
|
||||||
Set-Acl -Path $FilePath -AclObject $myACL
|
|
||||||
}
|
|
||||||
|
|
||||||
function Set-FileOwnerAndACL
|
|
||||||
{
|
{
|
||||||
param(
|
param(
|
||||||
[parameter(Mandatory=$true)]
|
[parameter(Mandatory=$true)]
|
||||||
[string]$FilePath,
|
[string]$FilePath,
|
||||||
[System.Security.Principal.NTAccount]$Owner = $null,
|
|
||||||
[System.Security.AccessControl.FileSystemRights[]] $OwnerPerms = @("Read", "Write")
|
|
||||||
)
|
|
||||||
|
|
||||||
$myACL = Get-ACL -Path $FilePath
|
|
||||||
$myACL.SetAccessRuleProtection($True, $FALSE)
|
|
||||||
Set-Acl -Path $FilePath -AclObject $myACL
|
|
||||||
|
|
||||||
$myACL = Get-ACL $FilePath
|
|
||||||
$actualOwner = $null
|
|
||||||
if($owner -eq $null)
|
|
||||||
{
|
|
||||||
$actualOwner = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME))
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$actualOwner = $Owner
|
|
||||||
}
|
|
||||||
|
|
||||||
$myACL.SetOwner($actualOwner)
|
|
||||||
|
|
||||||
if($myACL.Access)
|
|
||||||
{
|
|
||||||
$myACL.Access | % {
|
|
||||||
if(-not ($myACL.RemoveAccessRule($_)))
|
|
||||||
{
|
|
||||||
throw "failed to remove access of $($_.IdentityReference.Value) rule in setup "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if($OwnerPerms)
|
|
||||||
{
|
|
||||||
$OwnerPerms | % {
|
|
||||||
$ownerACE = New-Object System.Security.AccessControl.FileSystemAccessRule `
|
|
||||||
($actualOwner, $_, "None", "None", "Allow")
|
|
||||||
$myACL.AddAccessRule($ownerACE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Set-Acl -Path $FilePath -AclObject $myACL
|
|
||||||
}
|
|
||||||
|
|
||||||
function Add-PermissionToFileACL
|
|
||||||
{
|
|
||||||
param(
|
|
||||||
[parameter(Mandatory=$true)]
|
[parameter(Mandatory=$true)]
|
||||||
[string]$FilePath,
|
[System.Security.Principal.SecurityIdentifier] $UserSid,
|
||||||
[System.Security.Principal.NTAccount] $User,
|
|
||||||
[System.Security.AccessControl.FileSystemRights[]]$Perms,
|
[System.Security.AccessControl.FileSystemRights[]]$Perms,
|
||||||
[System.Security.AccessControl.AccessControlType] $AccessType = "Allow"
|
[System.Security.AccessControl.AccessControlType] $AccessType = "Allow",
|
||||||
|
[ValidateSet("Add", "Delete")]
|
||||||
|
[string]$Action = "Add"
|
||||||
)
|
)
|
||||||
|
|
||||||
$myACL = Get-ACL $FilePath
|
$myACL = Get-ACL $FilePath
|
||||||
|
$account = Get-UserAccount -UserSid $UserSid
|
||||||
|
if($Action -ieq "Delete")
|
||||||
|
{
|
||||||
|
$myACL.SetAccessRuleProtection($True, $True)
|
||||||
|
Enable-Privilege SeRestorePrivilege | out-null
|
||||||
|
Set-Acl -Path $FilePath -AclObject $myACL
|
||||||
|
$myACL = Get-ACL $FilePath
|
||||||
|
|
||||||
if($Perms)
|
if($myACL.Access)
|
||||||
|
{
|
||||||
|
$myACL.Access | % {
|
||||||
|
if($_.IdentityReference.Equals($account))
|
||||||
|
{
|
||||||
|
if($_.IsInherited)
|
||||||
|
{
|
||||||
|
$myACL.SetAccessRuleProtection($True, $True)
|
||||||
|
Enable-Privilege SeRestorePrivilege | out-null
|
||||||
|
Set-Acl -Path $FilePath -AclObject $myACL
|
||||||
|
$myACL = Get-ACL $FilePath
|
||||||
|
}
|
||||||
|
|
||||||
|
if(-not ($myACL.RemoveAccessRule($_)))
|
||||||
|
{
|
||||||
|
throw "failed to remove access of $($_.IdentityReference) rule in setup "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif($Perms)
|
||||||
{
|
{
|
||||||
$Perms | % {
|
$Perms | % {
|
||||||
$userACE = New-Object System.Security.AccessControl.FileSystemAccessRule `
|
$userACE = New-Object System.Security.AccessControl.FileSystemAccessRule `
|
||||||
($User, $_, "None", "None", $AccessType)
|
($UserSid, $_, "None", "None", $AccessType)
|
||||||
$myACL.AddAccessRule($userACE)
|
$myACL.AddAccessRule($userACE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Enable-Privilege SeRestorePrivilege | out-null
|
||||||
Set-Acl -Path $FilePath -AclObject $myACL
|
Set-Acl -Path $FilePath -AclObject $myACL -confirm:$false
|
||||||
}
|
}
|
||||||
|
|
||||||
function Add-PasswordSetting
|
function Add-PasswordSetting
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force -DisableNameChecking
|
If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
|
||||||
|
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force
|
||||||
$tC = 1
|
$tC = 1
|
||||||
$tI = 0
|
$tI = 0
|
||||||
$suite = "hostkey_fileperm"
|
$suite = "hostkey_fileperm"
|
||||||
@ -6,7 +7,7 @@ Describe "Tests for host keys file permission" -Tags "CI" {
|
|||||||
BeforeAll {
|
BeforeAll {
|
||||||
if($OpenSSHTestInfo -eq $null)
|
if($OpenSSHTestInfo -eq $null)
|
||||||
{
|
{
|
||||||
Throw "`$OpenSSHTestInfo is null. Please run Setup-OpenSSHTestEnvironment to setup test environment."
|
Throw "`$OpenSSHTestInfo is null. Please run Set-OpenSSHTestEnvironment to set test environments."
|
||||||
}
|
}
|
||||||
|
|
||||||
$testDir = "$($OpenSSHTestInfo["TestDataPath"])\$suite"
|
$testDir = "$($OpenSSHTestInfo["TestDataPath"])\$suite"
|
||||||
@ -19,30 +20,57 @@ Describe "Tests for host keys file permission" -Tags "CI" {
|
|||||||
$port = 47003
|
$port = 47003
|
||||||
$ssouser = $OpenSSHTestInfo["SSOUser"]
|
$ssouser = $OpenSSHTestInfo["SSOUser"]
|
||||||
$script:logNum = 0
|
$script:logNum = 0
|
||||||
Remove-Item -Path (Join-Path $testDir "*$logName") -Force -ErrorAction ignore
|
Remove-Item -Path (Join-Path $testDir "*$logName") -Force -ErrorAction SilentlyContinue
|
||||||
|
$platform = Get-Platform
|
||||||
|
$skip = ($platform -eq [PlatformType]::Windows) -and ($PSVersionTable.PSVersion.Major -le 2)
|
||||||
|
if(($platform -eq [PlatformType]::Windows) -and ($psversiontable.BuildVersion.Major -le 6))
|
||||||
|
{
|
||||||
|
#suppress the firewall blocking dialogue on win7
|
||||||
|
netsh advfirewall firewall add rule name="sshd" program="$($OpenSSHTestInfo['OpenSSHBinPath'])\sshd.exe" protocol=any action=allow dir=in
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AfterEach { $tI++ }
|
AfterEach { $tI++ }
|
||||||
|
AfterAll {
|
||||||
|
if(($platform -eq [PlatformType]::Windows) -and ($psversiontable.BuildVersion.Major -le 6))
|
||||||
|
{
|
||||||
|
netsh advfirewall firewall delete rule name="sshd" program="$($OpenSSHTestInfo['OpenSSHBinPath'])\sshd.exe" protocol=any dir=in
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Context "$tC - Host key files permission" {
|
Context "$tC - Host key files permission" {
|
||||||
BeforeAll {
|
BeforeAll {
|
||||||
$systemAccount = New-Object System.Security.Principal.NTAccount("NT AUTHORITY", "SYSTEM")
|
$systemSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::LocalSystemSid)
|
||||||
$adminAccount = New-Object System.Security.Principal.NTAccount("BUILTIN","Administrators")
|
$adminsSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid)
|
||||||
$objUser = New-Object System.Security.Principal.NTAccount($ssouser)
|
$currentUserSid = Get-UserSID -User "$($env:USERDOMAIN)\$($env:USERNAME)"
|
||||||
$currentUser = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME))
|
$objUserSid = Get-UserSID -User $ssouser
|
||||||
$everyone = New-Object System.Security.Principal.NTAccount("EveryOne")
|
$everyoneSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::WorldSid)
|
||||||
|
|
||||||
$hostKeyFilePath = join-path $testDir hostkeyFilePermTest_ed25519_key
|
$hostKeyFilePath = join-path $testDir hostkeyFilePermTest_ed25519_key
|
||||||
if(Test-path $hostKeyFilePath -PathType Leaf) {
|
if(Test-path $hostKeyFilePath -PathType Leaf) {
|
||||||
Set-FileOwnerAndACL -filepath $hostKeyFilePath
|
Repair-SshdHostKeyPermission -filepath $hostKeyFilePath -confirm:$false
|
||||||
}
|
}
|
||||||
if(Test-path "$hostKeyFilePath.pub" -PathType Leaf){
|
Remove-Item -path "$hostKeyFilePath*" -Force -ErrorAction SilentlyContinue
|
||||||
Set-FileOwnerAndACL -filepath "$hostKeyFilePath.pub"
|
|
||||||
}
|
|
||||||
Remove-Item -path "$hostKeyFilePath*" -Force -ErrorAction Ignore
|
|
||||||
ssh-keygen.exe -t ed25519 -f $hostKeyFilePath -P `"`"
|
ssh-keygen.exe -t ed25519 -f $hostKeyFilePath -P `"`"
|
||||||
Get-Process -Name sshd | Where-Object {$_.SI -ne 0} | Stop-process
|
Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
|
||||||
$tI=1
|
$tI=1
|
||||||
|
|
||||||
|
function WaitForValidation
|
||||||
|
{
|
||||||
|
param([string]$logPath, [int]$length)
|
||||||
|
$num = 0
|
||||||
|
while((-not (Test-Path $logPath -PathType leaf)) -or ((Get-item $logPath).Length -lt $length) -and ($num++ -lt 4))
|
||||||
|
{
|
||||||
|
Start-Sleep -Milliseconds 1000
|
||||||
|
}
|
||||||
|
Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
$num = 0
|
||||||
|
while ([string]::IsNullorEmpty($(Get-Content $logPath -ErrorAction SilentlyContinue | Out-String)) -and ($num++ -lt 4))
|
||||||
|
{
|
||||||
|
Start-Sleep -Milliseconds 1000
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BeforeEach {
|
BeforeEach {
|
||||||
@ -50,76 +78,59 @@ Describe "Tests for host keys file permission" -Tags "CI" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AfterAll {
|
AfterAll {
|
||||||
if(Test-path $hostKeyFilePath -PathType Leaf){
|
if(Test-path $hostKeyFilePath -PathType Leaf) {
|
||||||
Adjust-UserKeyFileACL -Filepath $hostKeyFilePath -Owner $systemAccount
|
Repair-SshdHostKeyPermission -filepath $hostKeyFilePath -confirm:$false
|
||||||
}
|
|
||||||
if(Test-path "$hostKeyFilePath.pub" -PathType Leaf){
|
|
||||||
Adjust-UserKeyFileACL -Filepath "$hostKeyFilePath.pub" -Owner $systemAccount
|
|
||||||
}
|
}
|
||||||
$tC++
|
$tC++
|
||||||
}
|
}
|
||||||
|
|
||||||
It "$tC.$tI-Host keys-positive (both public and private keys are owned by admin groups and running process can access to public key file)" {
|
It "$tC.$tI-Host keys-positive (both public and private keys are owned by admin groups and running process can access to public key file)" {
|
||||||
Set-FileOwnerAndACL -Filepath $hostKeyFilePath -Owner $adminAccount -OwnerPerms "FullControl"
|
Repair-FilePermission -Filepath $hostKeyFilePath -Owners $adminsSid -FullAccessNeeded $adminsSid,$systemSid -confirm:$false
|
||||||
Add-PermissionToFileACL -FilePath $hostKeyFilePath -User $systemAccount -Perms "FullControl"
|
Repair-FilePermission -Filepath "$hostKeyFilePath.pub" -Owners $adminsSid -FullAccessNeeded $adminsSid,$systemSid -confirm:$false
|
||||||
|
|
||||||
Set-FileOwnerAndACL -Filepath "$hostKeyFilePath.pub" -Owner $adminAccount -OwnerPerms "FullControl"
|
|
||||||
Add-PermissionToFileACL -FilePath "$hostKeyFilePath.pub" -User $systemAccount -Perms "FullControl"
|
|
||||||
Add-PermissionToFileACL -FilePath "$hostKeyFilePath.pub" -User $everyOne -Perms "Read"
|
|
||||||
|
|
||||||
#Run
|
#Run
|
||||||
|
|
||||||
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-h $hostKeyFilePath", "-E $logPath") -NoNewWindow
|
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-h $hostKeyFilePath", "-E $logPath") -NoNewWindow
|
||||||
Get-Process -Name sshd | % { if($_.SI -ne 0) { Start-sleep 2; Stop-Process $_; Start-sleep 1 } }
|
WaitForValidation -LogPath $logPath -Length 600
|
||||||
|
|
||||||
#validate file content does not contain unprotected info.
|
#validate file content does not contain unprotected info.
|
||||||
$logPath | Should Not Contain "UNPROTECTED PRIVATE KEY FILE!"
|
$logPath | Should Not Contain "UNPROTECTED PRIVATE KEY FILE!"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
It "$tC.$tI-Host keys-positive (both public and private keys are owned by admin groups and pwd user has explicit ACE)" {
|
It "$tC.$tI-Host keys-positive (both public and private keys are owned by admin groups and pwd user has explicit ACE)" {
|
||||||
Set-FileOwnerAndACL -Filepath $hostKeyFilePath -Owner $adminAccount -OwnerPerms "FullControl"
|
Repair-FilePermission -Filepath $hostKeyFilePath -Owners $adminsSid -FullAccessNeeded $adminsSid,$systemSid -ReadAccessNeeded $currentUserSid -confirm:$false
|
||||||
Add-PermissionToFileACL -FilePath $hostKeyFilePath -User $systemAccount -Perms "FullControl"
|
Repair-FilePermission -Filepath "$hostKeyFilePath.pub" -Owners $adminsSid -FullAccessNeeded $adminsSid,$systemSid -ReadAccessNeeded $everyOneSid -confirm:$false
|
||||||
Add-PermissionToFileACL -FilePath "$hostKeyFilePath.pub" -User $currentUser -Perms "Read"
|
|
||||||
|
|
||||||
Set-FileOwnerAndACL -Filepath "$hostKeyFilePath.pub" -Owner $adminAccount -OwnerPerms "FullControl"
|
|
||||||
Add-PermissionToFileACL -FilePath "$hostKeyFilePath.pub" -User $systemAccount -Perms "FullControl"
|
|
||||||
Add-PermissionToFileACL -FilePath "$hostKeyFilePath.pub" -User $everyOne -Perms "Read"
|
|
||||||
|
|
||||||
#Run
|
#Run
|
||||||
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-h $hostKeyFilePath", "-E $logPath") -NoNewWindow
|
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-h $hostKeyFilePath", "-E $logPath") -NoNewWindow
|
||||||
Get-Process -Name sshd | % { if($_.SI -ne 0) { Start-sleep 2; Stop-Process $_; Start-sleep 1 } }
|
WaitForValidation -LogPath $logPath -Length 600
|
||||||
|
|
||||||
#validate file content does not contain unprotected info.
|
#validate file content does not contain unprotected info.
|
||||||
$logPath | Should Not Contain "UNPROTECTED PRIVATE KEY FILE!"
|
$logPath | Should Not Contain "UNPROTECTED PRIVATE KEY FILE!"
|
||||||
}
|
}
|
||||||
|
|
||||||
It "$tC.$tI-Host keys-positive (both public and private keys are owned by system and running process can access to public key file)" {
|
It "$tC.$tI-Host keys-positive (both public and private keys are owned by system and running process can access to public key file)" -skip:$skip {
|
||||||
Set-FileOwnerAndACL -Filepath $hostKeyFilePath -Owner $systemAccount -OwnerPerms "FullControl"
|
Repair-FilePermission -Filepath $hostKeyFilePath -Owners $systemSid -FullAccessNeeded $systemSid,$adminsSid -ReadAccessNeeded $currentUserSid -confirm:$false
|
||||||
Add-PermissionToFileACL -FilePath $hostKeyFilePath -User $adminAccount -Perms "Read"
|
Set-FilePermission -Filepath $hostKeyFilePath -UserSid $adminsSid -Action Delete
|
||||||
|
Repair-FilePermission -Filepath "$hostKeyFilePath.pub" -Owners $systemSid -FullAccessNeeded $systemSid,$adminsSid -ReadAccessNeeded $currentUserSid -confirm:$false
|
||||||
Set-FileOwnerAndACL -Filepath "$hostKeyFilePath.pub" -Owner $systemAccount -OwnerPerms "FullControl"
|
Set-FilePermission -Filepath "$hostKeyFilePath.pub" -UserSid $adminsSid -Action Delete
|
||||||
Add-PermissionToFileACL -FilePath "$hostKeyFilePath.pub" -User $adminAccount -Perms "Read"
|
|
||||||
|
|
||||||
#Run
|
#Run
|
||||||
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-h $hostKeyFilePath", "-E $logPath") -NoNewWindow
|
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-h $hostKeyFilePath", "-E $logPath") -NoNewWindow
|
||||||
Get-Process -Name sshd | % { if($_.SI -ne 0) { Start-sleep 2; Stop-Process $_; Start-sleep 1 } }
|
WaitForValidation -LogPath $logPath -Length 600
|
||||||
|
|
||||||
|
|
||||||
#validate file content does not contain unprotected info.
|
#validate file content does not contain unprotected info.
|
||||||
$logPath | Should Not Contain "UNPROTECTED PRIVATE KEY FILE!"
|
$logPath | Should Not Contain "UNPROTECTED PRIVATE KEY FILE!"
|
||||||
}
|
}
|
||||||
|
|
||||||
It "$tC.$tI-Host keys-negative (other account can access private key file)" {
|
It "$tC.$tI-Host keys-negative (other account can access private key file)" {
|
||||||
Set-FileOwnerAndACL -Filepath $hostKeyFilePath -Owner $systemAccount -OwnerPerms "FullControl"
|
Repair-FilePermission -Filepath $hostKeyFilePath -Owners $adminsSid -FullAccessNeeded $systemSid,$adminsSid -ReadAccessNeeded $objUserSid -confirm:$false
|
||||||
Add-PermissionToFileACL -FilePath $hostKeyFilePath -User $adminAccount -Perms "FullControl"
|
Repair-FilePermission -Filepath "$hostKeyFilePath.pub" -Owners $adminsSid -FullAccessNeeded $systemSid,$adminsSid -ReadAccessNeeded $everyOneSid -confirm:$false
|
||||||
Add-PermissionToFileACL -FilePath $hostKeyFilePath -User $objUser -Perms "Read"
|
|
||||||
|
|
||||||
Set-FileOwnerAndACL -Filepath "$hostKeyFilePath.pub" -Owner $adminAccount -OwnerPerms "FullControl"
|
|
||||||
Add-PermissionToFileACL -FilePath "$hostKeyFilePath.pub" -User $systemAccount -Perms "FullControl"
|
|
||||||
Add-PermissionToFileACL -FilePath "$hostKeyFilePath.pub" -User $everyOne -Perms "Read"
|
|
||||||
|
|
||||||
#Run
|
#Run
|
||||||
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-h $hostKeyFilePath", "-E $logPath") -NoNewWindow
|
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-h $hostKeyFilePath", "-E $logPath") -NoNewWindow
|
||||||
Get-Process -Name sshd | % { if($_.SI -ne 0) { Start-sleep 2; Stop-Process $_; Start-sleep 1 } }
|
WaitForValidation -LogPath $logPath -Length 1100
|
||||||
|
|
||||||
#validate file content contains unprotected info.
|
#validate file content contains unprotected info.
|
||||||
$logPath | Should Contain "key_load_private: bad permissions"
|
$logPath | Should Contain "key_load_private: bad permissions"
|
||||||
@ -127,32 +138,26 @@ Describe "Tests for host keys file permission" -Tags "CI" {
|
|||||||
|
|
||||||
It "$tC.$tI-Host keys-negative (the private key has wrong owner)" {
|
It "$tC.$tI-Host keys-negative (the private key has wrong owner)" {
|
||||||
#setup to have ssouser as owner and grant it full control
|
#setup to have ssouser as owner and grant it full control
|
||||||
Set-FileOwnerAndACL -FilePath $hostKeyFilePath -Owner $objUser -OwnerPerms "Read","Write"
|
Repair-FilePermission -Filepath $hostKeyFilePath -Owners $objUserSid -FullAccessNeeded $systemSid,$adminsSid,$objUserSid -confirm:$false
|
||||||
Add-PermissionToFileACL -FilePath $hostKeyFilePath -User $adminAccount -Perms "FullControl"
|
Repair-FilePermission -Filepath "$hostKeyFilePath.pub" -Owners $adminsSid -FullAccessNeeded $systemSid,$adminsSid -ReadAccessNeeded $everyOneSid -confirm:$false
|
||||||
Add-PermissionToFileACL -FilePath $hostKeyFilePath -User $systemAccount -Perms "FullControl"
|
|
||||||
|
|
||||||
Set-FileOwnerAndACL -Filepath "$hostKeyFilePath.pub" -Owner $adminAccount -OwnerPerms "FullControl"
|
|
||||||
Add-PermissionToFileACL -FilePath "$hostKeyFilePath.pub" -User $systemAccount -Perms "FullControl"
|
|
||||||
Add-PermissionToFileACL -FilePath "$hostKeyFilePath.pub" -User $everyOne -Perms "Read"
|
|
||||||
|
|
||||||
#Run
|
#Run
|
||||||
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-h $hostKeyFilePath", "-E $logPath") -NoNewWindow
|
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-h $hostKeyFilePath", "-E $logPath") -NoNewWindow
|
||||||
Get-Process -Name sshd | % { if($_.SI -ne 0) { Start-sleep 2; Stop-Process $_; Start-sleep 1 } }
|
WaitForValidation -LogPath $logPath -Length 1100
|
||||||
|
|
||||||
#validate file content contains unprotected info.
|
#validate file content contains unprotected info.
|
||||||
$logPath | Should Contain "key_load_private: bad permissions"
|
$logPath | Should Contain "key_load_private: bad permissions"
|
||||||
}
|
}
|
||||||
|
|
||||||
It "$tC.$tI-Host keys-negative (the running process does not have read access to public key)" {
|
It "$tC.$tI-Host keys-negative (the running process does not have read access to public key)" -skip:$skip {
|
||||||
#setup to have ssouser as owner and grant it full control
|
#setup to have ssouser as owner and grant it full control
|
||||||
Set-FileOwnerAndACL -FilePath $hostKeyFilePath -Owner $systemAccount -OwnerPerms "FullControl"
|
Repair-FilePermission -Filepath $hostKeyFilePath -Owners $systemSid -FullAccessNeeded $systemSid,$adminsSid -confirm:$false
|
||||||
Add-PermissionToFileACL -FilePath $hostKeyFilePath -User $adminAccount -Perms "Read"
|
Repair-FilePermission -Filepath "$hostKeyFilePath.pub" -Owners $systemSid -FullAccessNeeded $systemSid -confirm:$false
|
||||||
|
Set-FilePermission -Filepath "$hostKeyFilePath.pub" -UserSid $adminsSid -Action Delete
|
||||||
Set-FileOwnerAndACL -Filepath "$hostKeyFilePath.pub" -Owner $systemAccount -OwnerPerms "FullControl"
|
|
||||||
|
|
||||||
#Run
|
#Run
|
||||||
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-h $hostKeyFilePath", "-E $logPath") -NoNewWindow
|
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-h $hostKeyFilePath", "-E $logPath") -NoNewWindow
|
||||||
Get-Process -Name sshd | % { if($_.SI -ne 0) { Start-sleep 2; Stop-Process $_; Start-sleep 1 } }
|
WaitForValidation -LogPath $logPath -Length 1100
|
||||||
|
|
||||||
#validate file content contains unprotected info.
|
#validate file content contains unprotected info.
|
||||||
$logPath | Should Contain "key_load_public: Permission denied"
|
$logPath | Should Contain "key_load_public: Permission denied"
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force -DisableNameChecking
|
If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
|
||||||
|
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force
|
||||||
$tC = 1
|
$tC = 1
|
||||||
$tI = 0
|
$tI = 0
|
||||||
$suite = "keyutils"
|
$suite = "keyutils"
|
||||||
@ -7,7 +8,7 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
|
|||||||
BeforeAll {
|
BeforeAll {
|
||||||
if($OpenSSHTestInfo -eq $null)
|
if($OpenSSHTestInfo -eq $null)
|
||||||
{
|
{
|
||||||
Throw "`$OpenSSHTestInfo is null. Please run Setup-OpenSSHTestEnvironment to setup test environment."
|
Throw "`$OpenSSHTestInfo is null. Please run Set-OpenSSHTestEnvironment to set test environments."
|
||||||
}
|
}
|
||||||
|
|
||||||
$testDir = "$($OpenSSHTestInfo["TestDataPath"])\$suite"
|
$testDir = "$($OpenSSHTestInfo["TestDataPath"])\$suite"
|
||||||
@ -21,47 +22,57 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
|
|||||||
|
|
||||||
$ssouser = $OpenSSHTestInfo["SSOUser"]
|
$ssouser = $OpenSSHTestInfo["SSOUser"]
|
||||||
|
|
||||||
$systemAccount = New-Object System.Security.Principal.NTAccount("NT AUTHORITY", "SYSTEM")
|
$systemSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::LocalSystemSid)
|
||||||
$adminsAccount = New-Object System.Security.Principal.NTAccount("BUILTIN","Administrators")
|
$adminsSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid)
|
||||||
$currentUser = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME))
|
$currentUserSid = Get-UserSID -User "$($env:USERDOMAIN)\$($env:USERNAME)"
|
||||||
$everyone = New-Object System.Security.Principal.NTAccount("EveryOne")
|
$objUserSid = Get-UserSID -User $ssouser
|
||||||
$objUser = New-Object System.Security.Principal.NTAccount($ssouser)
|
$everyoneSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::WorldSid)
|
||||||
|
|
||||||
#only validate owner and ACEs of the file
|
#only validate owner and ACEs of the file
|
||||||
function ValidateKeyFile {
|
function ValidateKeyFile {
|
||||||
param([string]$FilePath)
|
param([string]$FilePath)
|
||||||
|
|
||||||
$myACL = Get-ACL $FilePath
|
$myACL = Get-ACL $FilePath
|
||||||
$myACL.Owner.Equals($currentUser.Value) | Should Be $true
|
$currentOwnerSid = Get-UserSid -User $myACL.Owner
|
||||||
|
$currentOwnerSid.Equals($currentUserSid) | Should Be $true
|
||||||
$myACL.Access | Should Not Be $null
|
$myACL.Access | Should Not Be $null
|
||||||
|
|
||||||
|
$ReadAccessPerm = ([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Read.value__) -bor `
|
||||||
|
([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Synchronize.value__)
|
||||||
|
$ReadWriteAccessPerm = ([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Read.value__) -bor `
|
||||||
|
([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Write.value__) -bor `
|
||||||
|
([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Synchronize.value__)
|
||||||
|
$FullControlPerm = [System.UInt32] [System.Security.AccessControl.FileSystemRights]::FullControl.value__
|
||||||
|
|
||||||
if($FilePath.EndsWith(".pub")) {
|
if($FilePath.EndsWith(".pub")) {
|
||||||
$myACL.Access.Count | Should Be 4
|
$myACL.Access.Count | Should Be 4
|
||||||
$identities = @($systemAccount.Value, $adminsAccount.Value, $currentUser.Value, $everyone.Value)
|
$identities = @($systemSid, $adminsSid, $currentUserSid, $everyoneSid)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$myACL.Access.Count | Should Be 3
|
$myACL.Access.Count | Should Be 3
|
||||||
$identities = @($systemAccount.Value, $adminsAccount.Value, $currentUser.Value)
|
$identities = @($systemSid, $adminsSid, $currentUserSid)
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($a in $myACL.Access) {
|
foreach ($a in $myACL.Access) {
|
||||||
$a.IdentityReference.Value -in $identities | Should Be $true
|
$id = Get-UserSid -User $a.IdentityReference
|
||||||
|
$identities -contains $id | Should Be $true
|
||||||
|
|
||||||
switch ($a.IdentityReference.Value)
|
switch ($id)
|
||||||
{
|
{
|
||||||
{$_ -in @($systemAccount.Value, $adminsAccount.Value)}
|
{@($systemSid, $adminsSid) -contains $_}
|
||||||
{
|
{
|
||||||
$a.FileSystemRights | Should Be "FullControl"
|
([System.UInt32]$a.FileSystemRights.value__) | Should Be $FullControlPerm
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
$currentUser.Value
|
$currentUserSid
|
||||||
{
|
{
|
||||||
$a.FileSystemRights | Should Be "Write, Read, Synchronize"
|
([System.UInt32]$a.FileSystemRights.value__) | Should Be $ReadWriteAccessPerm
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
$everyone.Value
|
$everyoneSid
|
||||||
{
|
{
|
||||||
$a.FileSystemRights | Should Be "Read, Synchronize"
|
([System.UInt32]$a.FileSystemRights.value__) | Should Be $ReadAccessPerm
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -106,7 +117,7 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
|
|||||||
foreach($type in $keytypes)
|
foreach($type in $keytypes)
|
||||||
{
|
{
|
||||||
$keyPath = Join-Path $testDir "id_$type"
|
$keyPath = Join-Path $testDir "id_$type"
|
||||||
remove-item $keyPath -ErrorAction ignore
|
remove-item $keyPath -ErrorAction SilentlyContinue
|
||||||
ssh-keygen -t $type -P $keypassphrase -f $keyPath
|
ssh-keygen -t $type -P $keypassphrase -f $keyPath
|
||||||
ValidateKeyFile -FilePath $keyPath
|
ValidateKeyFile -FilePath $keyPath
|
||||||
ValidateKeyFile -FilePath "$keyPath.pub"
|
ValidateKeyFile -FilePath "$keyPath.pub"
|
||||||
@ -116,7 +127,17 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
|
|||||||
|
|
||||||
# This uses keys generated in above context
|
# This uses keys generated in above context
|
||||||
Context "$tC -ssh-add test cases" {
|
Context "$tC -ssh-add test cases" {
|
||||||
BeforeAll {$tI=1}
|
BeforeAll {
|
||||||
|
$tI=1
|
||||||
|
function WaitForStatus
|
||||||
|
{
|
||||||
|
param([string]$ServiceName, [string]$Status)
|
||||||
|
while((((Get-Service $ServiceName).Status) -ine $Status) -and ($num++ -lt 4))
|
||||||
|
{
|
||||||
|
Start-Sleep -Milliseconds 1000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
AfterAll{$tC++}
|
AfterAll{$tC++}
|
||||||
|
|
||||||
# Executing ssh-agent will start agent service
|
# Executing ssh-agent will start agent service
|
||||||
@ -131,16 +152,21 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
|
|||||||
(Get-Service sshd).Status | Should Be "Stopped"
|
(Get-Service sshd).Status | Should Be "Stopped"
|
||||||
|
|
||||||
ssh-agent
|
ssh-agent
|
||||||
|
WaitForStatus -ServiceName ssh-agent -Status "Running"
|
||||||
|
|
||||||
(Get-Service ssh-agent).Status | Should Be "Running"
|
(Get-Service ssh-agent).Status | Should Be "Running"
|
||||||
|
|
||||||
Stop-Service ssh-agent -Force
|
Stop-Service ssh-agent -Force
|
||||||
|
|
||||||
|
WaitForStatus -ServiceName ssh-agent -Status "Stopped"
|
||||||
|
|
||||||
(Get-Service ssh-agent).Status | Should Be "Stopped"
|
(Get-Service ssh-agent).Status | Should Be "Stopped"
|
||||||
(Get-Service sshd).Status | Should Be "Stopped"
|
(Get-Service sshd).Status | Should Be "Stopped"
|
||||||
|
|
||||||
# this should automatically start both the services
|
# this should automatically start both the services
|
||||||
Start-Service sshd
|
Start-Service sshd
|
||||||
|
|
||||||
|
WaitForStatus -ServiceName sshd -Status "Running"
|
||||||
(Get-Service ssh-agent).Status | Should Be "Running"
|
(Get-Service ssh-agent).Status | Should Be "Running"
|
||||||
(Get-Service sshd).Status | Should Be "Running"
|
(Get-Service sshd).Status | Should Be "Running"
|
||||||
}
|
}
|
||||||
@ -170,7 +196,7 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
|
|||||||
{
|
{
|
||||||
$keyPath = Join-Path $testDir "id_$type"
|
$keyPath = Join-Path $testDir "id_$type"
|
||||||
$pubkeyraw = ((Get-Content "$keyPath.pub").Split(' '))[1]
|
$pubkeyraw = ((Get-Content "$keyPath.pub").Split(' '))[1]
|
||||||
($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 1
|
@($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 1
|
||||||
}
|
}
|
||||||
|
|
||||||
#delete added keys
|
#delete added keys
|
||||||
@ -188,7 +214,7 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
|
|||||||
{
|
{
|
||||||
$keyPath = Join-Path $testDir "id_$type"
|
$keyPath = Join-Path $testDir "id_$type"
|
||||||
$pubkeyraw = ((Get-Content "$keyPath.pub").Split(' '))[1]
|
$pubkeyraw = ((Get-Content "$keyPath.pub").Split(' '))[1]
|
||||||
($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 0
|
@($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -197,7 +223,7 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
|
|||||||
BeforeAll {
|
BeforeAll {
|
||||||
$keyFileName = "sshadd_userPermTestkey_ed25519"
|
$keyFileName = "sshadd_userPermTestkey_ed25519"
|
||||||
$keyFilePath = Join-Path $testDir $keyFileName
|
$keyFilePath = Join-Path $testDir $keyFileName
|
||||||
Remove-Item -path "$keyFilePath*" -Force -ErrorAction Ignore
|
Remove-Item -path "$keyFilePath*" -Force -ErrorAction SilentlyContinue
|
||||||
ssh-keygen.exe -t ed25519 -f $keyFilePath -P $keypassphrase
|
ssh-keygen.exe -t ed25519 -f $keyFilePath -P $keypassphrase
|
||||||
#set up SSH_ASKPASS
|
#set up SSH_ASKPASS
|
||||||
Add-PasswordSetting -Pass $keypassphrase
|
Add-PasswordSetting -Pass $keypassphrase
|
||||||
@ -209,7 +235,7 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
|
|||||||
}
|
}
|
||||||
AfterEach {
|
AfterEach {
|
||||||
if(Test-Path $keyFilePath) {
|
if(Test-Path $keyFilePath) {
|
||||||
Adjust-UserKeyFileACL -FilePath $keyFilePath -Owner $currentUser -OwnerPerms "Read, Write"
|
Repair-FilePermission -FilePath $keyFilePath -Owner $currentUserSid -FullAccessNeeded $currentUserSid,$systemSid,$adminsSid -confirm:$false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,14 +247,14 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
|
|||||||
|
|
||||||
It "$tC.$tI- ssh-add - positive (Secured private key owned by current user)" {
|
It "$tC.$tI- ssh-add - positive (Secured private key owned by current user)" {
|
||||||
#setup to have current user as owner and grant it full control
|
#setup to have current user as owner and grant it full control
|
||||||
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $currentUser -OwnerPerms "FullControl"
|
Repair-FilePermission -FilePath $keyFilePath -Owner $currentUserSid -FullAccessNeeded $currentUserSid,$systemSid,$adminsSid -confirm:$false
|
||||||
|
|
||||||
# for ssh-add to consume SSh_ASKPASS, stdin should not be TTY
|
# for ssh-add to consume SSh_ASKPASS, stdin should not be TTY
|
||||||
cmd /c "ssh-add $keyFilePath < $nullFile 2> nul"
|
cmd /c "ssh-add $keyFilePath < $nullFile 2> nul"
|
||||||
$LASTEXITCODE | Should Be 0
|
$LASTEXITCODE | Should Be 0
|
||||||
$allkeys = ssh-add -L
|
$allkeys = ssh-add -L
|
||||||
$pubkeyraw = ((Get-Content "$keyFilePath.pub").Split(' '))[1]
|
$pubkeyraw = ((Get-Content "$keyFilePath.pub").Split(' '))[1]
|
||||||
($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 1
|
@($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 1
|
||||||
|
|
||||||
#clean up
|
#clean up
|
||||||
cmd /c "ssh-add -d $keyFilePath 2> nul "
|
cmd /c "ssh-add -d $keyFilePath 2> nul "
|
||||||
@ -236,14 +262,14 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
|
|||||||
|
|
||||||
It "$tC.$tI - ssh-add - positive (Secured private key owned by Administrators group and the current user has no explicit ACE)" {
|
It "$tC.$tI - ssh-add - positive (Secured private key owned by Administrators group and the current user has no explicit ACE)" {
|
||||||
#setup to have local admin group as owner and grant it full control
|
#setup to have local admin group as owner and grant it full control
|
||||||
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $adminsAccount -OwnerPerms "FullControl"
|
Repair-FilePermission -FilePath $keyFilePath -Owner $adminsSid -FullAccessNeeded $adminsSid,$systemSid -confirm:$false
|
||||||
|
|
||||||
# for ssh-add to consume SSh_ASKPASS, stdin should not be TTY
|
# for ssh-add to consume SSh_ASKPASS, stdin should not be TTY
|
||||||
cmd /c "ssh-add $keyFilePath < $nullFile 2> nul "
|
cmd /c "ssh-add $keyFilePath < $nullFile 2> nul "
|
||||||
$LASTEXITCODE | Should Be 0
|
$LASTEXITCODE | Should Be 0
|
||||||
$allkeys = ssh-add -L
|
$allkeys = ssh-add -L
|
||||||
$pubkeyraw = ((Get-Content "$keyFilePath.pub").Split(' '))[1]
|
$pubkeyraw = ((Get-Content "$keyFilePath.pub").Split(' '))[1]
|
||||||
($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 1
|
@($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 1
|
||||||
|
|
||||||
#clean up
|
#clean up
|
||||||
cmd /c "ssh-add -d $keyFilePath 2> nul "
|
cmd /c "ssh-add -d $keyFilePath 2> nul "
|
||||||
@ -251,15 +277,14 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
|
|||||||
|
|
||||||
It "$tC.$tI - ssh-add - positive (Secured private key owned by Administrators group and the current user has explicit ACE)" {
|
It "$tC.$tI - ssh-add - positive (Secured private key owned by Administrators group and the current user has explicit ACE)" {
|
||||||
#setup to have local admin group as owner and grant it full control
|
#setup to have local admin group as owner and grant it full control
|
||||||
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $adminsAccount -OwnerPerms "FullControl"
|
Repair-FilePermission -FilePath $keyFilePath -Owners $adminsSid -FullAccessNeeded $currentUserSid,$adminsSid,$systemSid -confirm:$false
|
||||||
Add-PermissionToFileACL -FilePath $keyFilePath -User $currentUser -Perm "Read, Write"
|
|
||||||
|
|
||||||
# for ssh-add to consume SSh_ASKPASS, stdin should not be TTY
|
# for ssh-add to consume SSh_ASKPASS, stdin should not be TTY
|
||||||
cmd /c "ssh-add $keyFilePath < $nullFile 2> nul "
|
cmd /c "ssh-add $keyFilePath < $nullFile 2> nul "
|
||||||
$LASTEXITCODE | Should Be 0
|
$LASTEXITCODE | Should Be 0
|
||||||
$allkeys = ssh-add -L
|
$allkeys = ssh-add -L
|
||||||
$pubkeyraw = ((Get-Content "$keyFilePath.pub").Split(' '))[1]
|
$pubkeyraw = ((Get-Content "$keyFilePath.pub").Split(' '))[1]
|
||||||
($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 1
|
@($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 1
|
||||||
|
|
||||||
#clean up
|
#clean up
|
||||||
cmd /c "ssh-add -d $keyFilePath 2> nul "
|
cmd /c "ssh-add -d $keyFilePath 2> nul "
|
||||||
@ -267,15 +292,14 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
|
|||||||
|
|
||||||
It "$tC.$tI - ssh-add - positive (Secured private key owned by local system group)" {
|
It "$tC.$tI - ssh-add - positive (Secured private key owned by local system group)" {
|
||||||
#setup to have local admin group as owner and grant it full control
|
#setup to have local admin group as owner and grant it full control
|
||||||
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $systemAccount -OwnerPerms "FullControl"
|
Repair-FilePermission -FilePath $keyFilePath -Owners $systemSid -FullAccessNeeded $systemSid,$adminsSid -confirm:$false
|
||||||
Add-PermissionToFileACL -FilePath $keyFilePath -User $adminsAccount -Perm "FullControl"
|
|
||||||
|
|
||||||
# for ssh-add to consume SSh_ASKPASS, stdin should not be TTY
|
# for ssh-add to consume SSh_ASKPASS, stdin should not be TTY
|
||||||
cmd /c "ssh-add $keyFilePath < $nullFile 2> nul "
|
cmd /c "ssh-add $keyFilePath < $nullFile 2> nul "
|
||||||
$LASTEXITCODE | Should Be 0
|
$LASTEXITCODE | Should Be 0
|
||||||
$allkeys = ssh-add -L
|
$allkeys = ssh-add -L
|
||||||
$pubkeyraw = ((Get-Content "$keyFilePath.pub").Split(' '))[1]
|
$pubkeyraw = ((Get-Content "$keyFilePath.pub").Split(' '))[1]
|
||||||
($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 1
|
@($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 1
|
||||||
|
|
||||||
#clean up
|
#clean up
|
||||||
cmd /c "ssh-add -d $keyFilePath 2> nul "
|
cmd /c "ssh-add -d $keyFilePath 2> nul "
|
||||||
@ -283,30 +307,26 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
|
|||||||
|
|
||||||
It "$tC.$tI- ssh-add - negative (other account can access private key file)" {
|
It "$tC.$tI- ssh-add - negative (other account can access private key file)" {
|
||||||
#setup to have current user as owner and grant it full control
|
#setup to have current user as owner and grant it full control
|
||||||
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $currentUser -OwnerPerms "FullControl"
|
Repair-FilePermission -FilePath $keyFilePath -Owners $currentUserSid -FullAccessNeeded $currentUserSid,$adminsSid, $systemSid -ReadAccessNeeded $objUserSid -confirm:$false
|
||||||
|
|
||||||
#add ssouser to access the private key
|
|
||||||
Add-PermissionToFileACL -FilePath $keyFilePath -User $objUser -Perm "Read"
|
|
||||||
|
|
||||||
cmd /c "ssh-add $keyFilePath < $nullFile 2> nul "
|
cmd /c "ssh-add $keyFilePath < $nullFile 2> nul "
|
||||||
$LASTEXITCODE | Should Not Be 0
|
$LASTEXITCODE | Should Not Be 0
|
||||||
|
|
||||||
$allkeys = ssh-add -L
|
$allkeys = ssh-add -L
|
||||||
$pubkeyraw = ((Get-Content "$keyFilePath.pub").Split(' '))[1]
|
$pubkeyraw = ((Get-Content "$keyFilePath.pub").Split(' '))[1]
|
||||||
($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 0
|
@($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 0
|
||||||
}
|
}
|
||||||
|
|
||||||
It "$tC.$tI - ssh-add - negative (the private key has wrong owner)" {
|
It "$tC.$tI - ssh-add - negative (the private key has wrong owner)" {
|
||||||
#setup to have ssouser as owner and grant it full control
|
#setup to have ssouser as owner and grant it full control
|
||||||
Set-FileOwnerAndACL -FilePath $keyFilePath -owner $objUser -OwnerPerms "Read, Write"
|
Repair-FilePermission -FilePath $keyFilePath -Owners $objUserSid -FullAccessNeeded $objUserSid,$adminsSid, $systemSid -confirm:$false
|
||||||
Add-PermissionToFileACL -FilePath $keyFilePath -User $adminsAccount -Perm "FullControl"
|
|
||||||
|
|
||||||
cmd /c "ssh-add $keyFilePath < $nullFile 2> nul "
|
cmd /c "ssh-add $keyFilePath < $nullFile 2> nul "
|
||||||
$LASTEXITCODE | Should Not Be 0
|
$LASTEXITCODE | Should Not Be 0
|
||||||
|
|
||||||
$allkeys = ssh-add -L
|
$allkeys = ssh-add -L
|
||||||
$pubkeyraw = ((Get-Content "$keyFilePath.pub").Split(' '))[1]
|
$pubkeyraw = ((Get-Content "$keyFilePath.pub").Split(' '))[1]
|
||||||
($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 0
|
@($allkeys | where { $_.contains($pubkeyraw) }).count | Should Be 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -314,7 +334,7 @@ Describe "E2E scenarios for ssh key management" -Tags "CI" {
|
|||||||
BeforeAll {
|
BeforeAll {
|
||||||
$tI=1
|
$tI=1
|
||||||
$port = $OpenSSHTestInfo["Port"]
|
$port = $OpenSSHTestInfo["Port"]
|
||||||
Remove-item (join-path $testDir "$tC.$tI.out.txt") -force -ErrorAction Ignore
|
Remove-item (join-path $testDir "$tC.$tI.out.txt") -force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
BeforeEach {
|
BeforeEach {
|
||||||
$outputFile = join-path $testDir "$tC.$tI.out.txt"
|
$outputFile = join-path $testDir "$tC.$tI.out.txt"
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
$tC = 1
|
If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
|
||||||
|
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force
|
||||||
|
$tC = 1
|
||||||
$tI = 0
|
$tI = 0
|
||||||
$suite = "log_fileperm"
|
$suite = "log_fileperm"
|
||||||
|
|
||||||
@ -17,36 +19,50 @@ Describe "Tests for log file permission" -Tags "CI" {
|
|||||||
$port = 47003
|
$port = 47003
|
||||||
$logName = "log.txt"
|
$logName = "log.txt"
|
||||||
|
|
||||||
$systemAccount = New-Object System.Security.Principal.NTAccount("NT AUTHORITY", "SYSTEM")
|
$systemSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::LocalSystemSid)
|
||||||
$adminsAccount = New-Object System.Security.Principal.NTAccount("BUILTIN","Administrators")
|
$adminsSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid)
|
||||||
$currentUser = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME))
|
$currentUserSid = Get-UserSID -User "$($env:USERDOMAIN)\$($env:USERNAME)"
|
||||||
|
|
||||||
Remove-Item (Join-Path $testDir "*$logName") -Force -ErrorAction Ignore
|
Remove-Item (Join-Path $testDir "*$logName") -Force -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
$platform = Get-Platform
|
||||||
|
if(($platform -eq [PlatformType]::Windows) -and ($psversiontable.BuildVersion.Major -le 6))
|
||||||
|
{
|
||||||
|
#suppress the firewall blocking dialogue on win7
|
||||||
|
netsh advfirewall firewall add rule name="sshd" program="$($OpenSSHTestInfo['OpenSSHBinPath'])\sshd.exe" protocol=any action=allow dir=in
|
||||||
|
}
|
||||||
|
|
||||||
#only validate owner and ACEs of the file
|
#only validate owner and ACEs of the file
|
||||||
function ValiLogFilePerm {
|
function ValidateLogFilePerm {
|
||||||
param([string]$FilePath)
|
param([string]$FilePath)
|
||||||
|
|
||||||
$myACL = Get-ACL $FilePath
|
$myACL = Get-ACL $FilePath
|
||||||
$myACL.Owner.Equals($currentUser.Value) | Should Be $true
|
$currentOwnerSid = Get-UserSid -User $myACL.Owner
|
||||||
|
$currentOwnerSid.Equals($currentUserSid) | Should Be $true
|
||||||
$myACL.Access | Should Not Be $null
|
$myACL.Access | Should Not Be $null
|
||||||
|
|
||||||
|
$ReadWriteAccessPerm = ([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Read.value__) -bor `
|
||||||
|
([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Write.value__) -bor `
|
||||||
|
([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Synchronize.value__)
|
||||||
|
$FullControlPerm = [System.UInt32] [System.Security.AccessControl.FileSystemRights]::FullControl.value__
|
||||||
|
|
||||||
$myACL.Access.Count | Should Be 3
|
$myACL.Access.Count | Should Be 3
|
||||||
$identities = @($systemAccount.Value, $adminsAccount.Value, $currentUser.Value)
|
$identities = @($systemSid, $adminsSid, $currentUserSid)
|
||||||
|
|
||||||
foreach ($a in $myACL.Access) {
|
foreach ($a in $myACL.Access) {
|
||||||
$a.IdentityReference.Value -in $identities | Should Be $true
|
$id = Get-UserSid -User $a.IdentityReference
|
||||||
|
$identities -contains $id | Should Be $true
|
||||||
|
|
||||||
switch ($a.IdentityReference.Value)
|
switch ($id)
|
||||||
{
|
{
|
||||||
{$_ -in @($systemAccount.Value, $adminsAccount.Value)}
|
{@($systemSid, $adminsSid) -contains $_}
|
||||||
{
|
{
|
||||||
$a.FileSystemRights | Should Be "FullControl"
|
([System.UInt32]$a.FileSystemRights.value__) | Should Be $FullControlPerm
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
$currentUserSid
|
||||||
$currentUser.Value
|
|
||||||
{
|
{
|
||||||
$a.FileSystemRights | Should Be "Write, Read, Synchronize"
|
([System.UInt32]$a.FileSystemRights.value__) | Should Be $ReadWriteAccessPerm
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,10 +80,16 @@ Describe "Tests for log file permission" -Tags "CI" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AfterEach {$tI++;}
|
AfterEach {$tI++;}
|
||||||
|
AfterAll {
|
||||||
|
if(($platform -eq [PlatformType]::Windows) -and ($psversiontable.BuildVersion.Major -le 6))
|
||||||
|
{
|
||||||
|
netsh advfirewall firewall delete rule name="sshd" program="$($OpenSSHTestInfo['OpenSSHBinPath'])\sshd.exe" protocol=any dir=in
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Context "$tC-SSHD -E Log file permission" {
|
Context "$tC-SSHD -E Log file permission" {
|
||||||
BeforeAll {
|
BeforeAll {
|
||||||
Get-Process -Name sshd | Where-Object {$_.SI -ne 0} | Stop-process
|
Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
|
||||||
$tI=1
|
$tI=1
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,8 +101,8 @@ Describe "Tests for log file permission" -Tags "CI" {
|
|||||||
#Run
|
#Run
|
||||||
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-E $logPath") -NoNewWindow
|
Start-Process -FilePath sshd.exe -WorkingDirectory $($OpenSSHTestInfo['OpenSSHBinPath']) -ArgumentList @("-d", "-p $port", "-E $logPath") -NoNewWindow
|
||||||
Start-sleep 1;
|
Start-sleep 1;
|
||||||
ValiLogFilePerm -FilePath $logPath
|
ValidateLogFilePerm -FilePath $logPath
|
||||||
Get-Process -Name sshd | % { if($_.SI -ne 0) { Stop-Process $_; Start-sleep 1 } }
|
Get-Process -Name sshd -ErrorAction SilentlyContinue | Where-Object {$_.SessionID -ne 0} | Stop-process -force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,14 +1,22 @@
|
|||||||
$tC = 1
|
If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
|
||||||
|
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force
|
||||||
|
$tC = 1
|
||||||
$tI = 0
|
$tI = 0
|
||||||
$suite = "portfwd"
|
$suite = "portfwd"
|
||||||
|
|
||||||
Describe "E2E scenarios for port forwarding" -Tags "CI" {
|
Describe "E2E scenarios for port forwarding" -Tags "CI" {
|
||||||
BeforeAll {
|
BeforeAll {
|
||||||
|
if($OpenSSHTestInfo -eq $null)
|
||||||
|
{
|
||||||
|
Throw "`$OpenSSHTestInfo is null. Please run Set-OpenSSHTestEnvironment to set test environments."
|
||||||
|
}
|
||||||
$testDir = Join-Path $OpenSSHTestInfo["TestDataPath"] $suite
|
$testDir = Join-Path $OpenSSHTestInfo["TestDataPath"] $suite
|
||||||
if(-not (Test-Path $testDir))
|
if(-not (Test-Path $testDir))
|
||||||
{
|
{
|
||||||
$null = New-Item $testDir -ItemType directory -Force -ErrorAction SilentlyContinue
|
$null = New-Item $testDir -ItemType directory -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
$platform = Get-Platform
|
||||||
|
$skip = ($platform -eq [PlatformType]::Windows) -and ($PSVersionTable.PSVersion.Major -le 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
BeforeEach {
|
BeforeEach {
|
||||||
@ -23,12 +31,12 @@ Describe "E2E scenarios for port forwarding" -Tags "CI" {
|
|||||||
AfterAll{$tC++}
|
AfterAll{$tC++}
|
||||||
|
|
||||||
#TODO - this relies on winrm (that is windows specific)
|
#TODO - this relies on winrm (that is windows specific)
|
||||||
It "$tC.$tI - local port forwarding" {
|
It "$tC.$tI - local port forwarding" -skip:$skip {
|
||||||
ssh -L 5432:127.0.0.1:47001 test_target powershell.exe Test-WSMan -computer 127.0.0.1 -port 5432 | Set-Content $stdoutFile
|
ssh -L 5432:127.0.0.1:47001 test_target powershell.exe Test-WSMan -computer 127.0.0.1 -port 5432 | Set-Content $stdoutFile
|
||||||
$stdoutFile | Should Contain "wsmid"
|
$stdoutFile | Should Contain "wsmid"
|
||||||
}
|
}
|
||||||
|
|
||||||
It "$tC.$tI - remote port forwarding" {
|
It "$tC.$tI - remote port forwarding" -skip:$skip {
|
||||||
ssh -R 5432:127.0.0.1:47001 test_target powershell.exe Test-WSMan -computer 127.0.0.1 -port 5432 | Set-Content $stdoutFile
|
ssh -R 5432:127.0.0.1:47001 test_target powershell.exe Test-WSMan -computer 127.0.0.1 -port 5432 | Set-Content $stdoutFile
|
||||||
$stdoutFile | Should Contain "wsmid"
|
$stdoutFile | Should Contain "wsmid"
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
|
If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
|
||||||
|
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force
|
||||||
#covered -i -p -q -r -v -c -S -C
|
#covered -i -p -q -r -v -c -S -C
|
||||||
#todo: -F, -l and -P should be tested over the network
|
#todo: -F, -l and -P should be tested over the network
|
||||||
Describe "Tests for scp command" -Tags "CI" {
|
Describe "Tests for scp command" -Tags "CI" {
|
||||||
BeforeAll {
|
BeforeAll {
|
||||||
if($OpenSSHTestInfo -eq $null)
|
if($OpenSSHTestInfo -eq $null)
|
||||||
{
|
{
|
||||||
Throw "`$OpenSSHTestInfo is null. Please run Setup-OpenSSHTestEnvironment to setup test environment."
|
Throw "`$OpenSSHTestInfo is null. Please run Set-OpenSSHTestEnvironment to set test environments."
|
||||||
}
|
}
|
||||||
|
|
||||||
$fileName1 = "test.txt"
|
$fileName1 = "test.txt"
|
||||||
@ -19,8 +20,8 @@ Describe "Tests for scp command" -Tags "CI" {
|
|||||||
$NestedSourceFilePath = Join-Path $NestedSourceDir $fileName2
|
$NestedSourceFilePath = Join-Path $NestedSourceDir $fileName2
|
||||||
$null = New-Item $SourceDir -ItemType directory -Force -ErrorAction SilentlyContinue
|
$null = New-Item $SourceDir -ItemType directory -Force -ErrorAction SilentlyContinue
|
||||||
$null = New-Item $NestedSourceDir -ItemType directory -Force -ErrorAction SilentlyContinue
|
$null = New-Item $NestedSourceDir -ItemType directory -Force -ErrorAction SilentlyContinue
|
||||||
$null = New-item -path $SourceFilePath -force -ErrorAction SilentlyContinue
|
$null = New-item -path $SourceFilePath -ItemType file -force -ErrorAction SilentlyContinue
|
||||||
$null = New-item -path $NestedSourceFilePath -force -ErrorAction SilentlyContinue
|
$null = New-item -path $NestedSourceFilePath -ItemType file -force -ErrorAction SilentlyContinue
|
||||||
"Test content111" | Set-content -Path $SourceFilePath
|
"Test content111" | Set-content -Path $SourceFilePath
|
||||||
"Test content in nested dir" | Set-content -Path $NestedSourceFilePath
|
"Test content in nested dir" | Set-content -Path $NestedSourceFilePath
|
||||||
$null = New-Item $DestinationDir -ItemType directory -Force -ErrorAction SilentlyContinue
|
$null = New-Item $DestinationDir -ItemType directory -Force -ErrorAction SilentlyContinue
|
||||||
@ -94,8 +95,8 @@ Describe "Tests for scp command" -Tags "CI" {
|
|||||||
# for the first time, delete the existing log files.
|
# for the first time, delete the existing log files.
|
||||||
if ($OpenSSHTestInfo['DebugMode'])
|
if ($OpenSSHTestInfo['DebugMode'])
|
||||||
{
|
{
|
||||||
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction ignore
|
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue
|
||||||
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction ignore
|
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
function CheckTarget {
|
function CheckTarget {
|
||||||
@ -110,8 +111,8 @@ Describe "Tests for scp command" -Tags "CI" {
|
|||||||
$script:logNum++
|
$script:logNum++
|
||||||
|
|
||||||
# clear the ssh-agent, sshd logs so that next testcase will get fresh logs.
|
# clear the ssh-agent, sshd logs so that next testcase will get fresh logs.
|
||||||
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction ignore
|
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue
|
||||||
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction ignore
|
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
return $false
|
return $false
|
||||||
@ -144,6 +145,7 @@ Describe "Tests for scp command" -Tags "CI" {
|
|||||||
|
|
||||||
AfterEach {
|
AfterEach {
|
||||||
Get-ChildItem $DestinationDir -Recurse | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
|
Get-ChildItem $DestinationDir -Recurse | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
|
Start-Sleep 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -184,7 +186,7 @@ Describe "Tests for scp command" -Tags "CI" {
|
|||||||
$equal = @(Compare-Object (Get-ChildItem -Recurse -path $SourceDir) (Get-ChildItem -Recurse -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length).Length -eq 0
|
$equal = @(Compare-Object (Get-ChildItem -Recurse -path $SourceDir) (Get-ChildItem -Recurse -path (join-path $DestinationDir $SourceDirName) ) -Property Name, Length).Length -eq 0
|
||||||
$equal | Should Be $true
|
$equal | Should Be $true
|
||||||
|
|
||||||
if($Options.contains("-p"))
|
if($Options.contains("-p") -and ($platform -eq [PlatformType]::Windows) -and ($PSVersionTable.PSVersion.Major -gt 2))
|
||||||
{
|
{
|
||||||
$equal = @(Compare-Object (Get-ChildItem -Recurse -path $SourceDir).LastWriteTime.DateTime (Get-ChildItem -Recurse -path (join-path $DestinationDir $SourceDirName) ).LastWriteTime.DateTime).Length -eq 0
|
$equal = @(Compare-Object (Get-ChildItem -Recurse -path $SourceDir).LastWriteTime.DateTime (Get-ChildItem -Recurse -path (join-path $DestinationDir $SourceDirName) ).LastWriteTime.DateTime).Length -eq 0
|
||||||
$equal | Should Be $true
|
$equal | Should Be $true
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force -DisableNameChecking
|
If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
|
||||||
|
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force
|
||||||
Describe "SFTP Test Cases" -Tags "CI" {
|
Describe "SFTP Test Cases" -Tags "CI" {
|
||||||
BeforeAll {
|
BeforeAll {
|
||||||
|
$serverDirectory = $null
|
||||||
|
$clientDirectory = $null
|
||||||
if($OpenSSHTestInfo -eq $null)
|
if($OpenSSHTestInfo -eq $null)
|
||||||
{
|
{
|
||||||
Throw "`$OpenSSHTestInfo is null. Please run Setup-OpenSSHTestEnvironment to setup test environment."
|
Throw "`$OpenSSHTestInfo is null. Please run Set-OpenSSHTestEnvironment to set test environments."
|
||||||
}
|
}
|
||||||
|
|
||||||
$rootDirectory = "$($OpenSSHTestInfo["TestDataPath"])\SFTP"
|
$rootDirectory = "$($OpenSSHTestInfo["TestDataPath"])\SFTP"
|
||||||
@ -29,8 +32,11 @@ Describe "SFTP Test Cases" -Tags "CI" {
|
|||||||
$ssouser = $OpenSSHTestInfo["SSOUser"]
|
$ssouser = $OpenSSHTestInfo["SSOUser"]
|
||||||
$script:testId = 1
|
$script:testId = 1
|
||||||
|
|
||||||
Remove-item (Join-Path $rootDirectory "*.$outputFileName") -Force -ErrorAction Ignore
|
Remove-item (Join-Path $rootDirectory "*.$outputFileName") -Force -ErrorAction SilentlyContinue
|
||||||
Remove-item (Join-Path $rootDirectory "*.$batchFileName") -Force -ErrorAction Ignore
|
Remove-item (Join-Path $rootDirectory "*.$batchFileName") -Force -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
$platform = Get-Platform
|
||||||
|
$skip = ($platform -eq [PlatformType]::Windows) -and ($PSVersionTable.PSVersion.Major -le 2)
|
||||||
|
|
||||||
$testData1 = @(
|
$testData1 = @(
|
||||||
@{
|
@{
|
||||||
@ -162,9 +168,9 @@ Describe "SFTP Test Cases" -Tags "CI" {
|
|||||||
# for the first time, delete the existing log files.
|
# for the first time, delete the existing log files.
|
||||||
if ($OpenSSHTestInfo['DebugMode'])
|
if ($OpenSSHTestInfo['DebugMode'])
|
||||||
{
|
{
|
||||||
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction ignore
|
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue
|
||||||
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction ignore
|
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction SilentlyContinue
|
||||||
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sftp-server.log" -Force -ErrorAction ignore
|
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sftp-server.log" -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
function CopyDebugLogs {
|
function CopyDebugLogs {
|
||||||
@ -175,21 +181,21 @@ Describe "SFTP Test Cases" -Tags "CI" {
|
|||||||
Copy-Item "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sftp-server.log" "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sftp-server_$script:testId.log" -Force
|
Copy-Item "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sftp-server.log" "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sftp-server_$script:testId.log" -Force
|
||||||
|
|
||||||
# clear the ssh-agent, sshd logs so that next testcase will get fresh logs.
|
# clear the ssh-agent, sshd logs so that next testcase will get fresh logs.
|
||||||
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction ignore
|
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\ssh-agent.log" -Force -ErrorAction SilentlyContinue
|
||||||
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction ignore
|
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sshd.log" -Force -ErrorAction SilentlyContinue
|
||||||
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sftp-server.log" -Force -ErrorAction ignore
|
Clear-Content "$($OpenSSHTestInfo['OpenSSHBinPath'])\logs\sftp-server.log" -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AfterAll {
|
AfterAll {
|
||||||
Get-ChildItem $serverDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
|
if($serverDirectory) { Get-ChildItem $serverDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue }
|
||||||
Get-ChildItem $clientDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
|
if($clientDirectory) { Get-ChildItem $clientDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue }
|
||||||
}
|
}
|
||||||
|
|
||||||
BeforeEach {
|
BeforeEach {
|
||||||
Get-ChildItem $serverDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
|
if($serverDirectory) { Get-ChildItem $serverDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue }
|
||||||
Get-ChildItem $clientDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
|
if($clientDirectory) { Get-ChildItem $clientDirectory | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue }
|
||||||
$outputFilePath = Join-Path $rootDirectory "$($script:testId).$outputFileName"
|
$outputFilePath = Join-Path $rootDirectory "$($script:testId).$outputFileName"
|
||||||
$batchFilePath = Join-Path $rootDirectory "$($script:testId).$batchFileName"
|
$batchFilePath = Join-Path $rootDirectory "$($script:testId).$batchFileName"
|
||||||
}
|
}
|
||||||
@ -212,6 +218,7 @@ Describe "SFTP Test Cases" -Tags "CI" {
|
|||||||
|
|
||||||
It '<Title>' -TestCases:$testData2 {
|
It '<Title>' -TestCases:$testData2 {
|
||||||
param([string]$Title, $Options, $tmpFileName1, $tmpFilePath1, $tmpFileName2, $tmpFilePath2, $tmpDirectoryName1, $tmpDirectoryPath1, $tmpDirectoryName2, $tmpDirectoryPath2)
|
param([string]$Title, $Options, $tmpFileName1, $tmpFilePath1, $tmpFileName2, $tmpFilePath2, $tmpDirectoryName1, $tmpDirectoryPath1, $tmpDirectoryName2, $tmpDirectoryPath2)
|
||||||
|
if($skip) { return }
|
||||||
|
|
||||||
#rm (remove file)
|
#rm (remove file)
|
||||||
$commands = "mkdir $tmpDirectoryPath1
|
$commands = "mkdir $tmpDirectoryPath1
|
||||||
@ -263,16 +270,19 @@ Describe "SFTP Test Cases" -Tags "CI" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
It "$script:testId-ls lists items the user has no read permission" {
|
It "$script:testId-ls lists items the user has no read permission" {
|
||||||
|
$adminsSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid)
|
||||||
|
$currentUserSid = Get-UserSID -User "$($env:USERDOMAIN)\$($env:USERNAME)"
|
||||||
|
|
||||||
$permTestHasAccessFile = "permTestHasAccessFile.txt"
|
$permTestHasAccessFile = "permTestHasAccessFile.txt"
|
||||||
$permTestHasAccessFilePath = Join-Path $serverDirectory $permTestHasAccessFile
|
$permTestHasAccessFilePath = Join-Path $serverDirectory $permTestHasAccessFile
|
||||||
Remove-Item $permTestHasAccessFilePath -Force -ErrorAction Ignore
|
Remove-Item $permTestHasAccessFilePath -Force -ErrorAction SilentlyContinue
|
||||||
New-Item $permTestHasAccessFilePath -ItemType file -Force -value "perm test has access file data" | Out-Null
|
New-Item $permTestHasAccessFilePath -ItemType file -Force -value "perm test has access file data" | Out-Null
|
||||||
|
|
||||||
$permTestNoAccessFile = "permTestNoAccessFile.txt"
|
$permTestNoAccessFile = "permTestNoAccessFile.txt"
|
||||||
$permTestNoAccessFilePath = Join-Path $serverDirectory $permTestNoAccessFile
|
$permTestNoAccessFilePath = Join-Path $serverDirectory $permTestNoAccessFile
|
||||||
Remove-Item $permTestNoAccessFilePath -Force -ErrorAction Ignore
|
Remove-Item $permTestNoAccessFilePath -Force -ErrorAction SilentlyContinue
|
||||||
New-Item $permTestNoAccessFilePath -ItemType file -Force -value "perm test no access file data" | Out-Null
|
New-Item $permTestNoAccessFilePath -ItemType file -Force -value "perm test no access file data" | Out-Null
|
||||||
Set-FileOwnerAndACL -Filepath $permTestNoAccessFilePath -OwnerPerms "Read","Write"
|
Repair-FilePermission -Filepath $permTestNoAccessFilePath -Owners $currentUserSid -FullAccessNeeded $adminsSid,$currentUserSid -confirm:$false
|
||||||
|
|
||||||
$Commands = "ls $serverDirectory"
|
$Commands = "ls $serverDirectory"
|
||||||
Set-Content $batchFilePath -Encoding UTF8 -value $Commands
|
Set-Content $batchFilePath -Encoding UTF8 -value $Commands
|
||||||
@ -282,11 +292,11 @@ Describe "SFTP Test Cases" -Tags "CI" {
|
|||||||
|
|
||||||
#cleanup
|
#cleanup
|
||||||
$HasAccessPattern = $permTestHasAccessFilePath.Replace("\", "[/\\]")
|
$HasAccessPattern = $permTestHasAccessFilePath.Replace("\", "[/\\]")
|
||||||
$matches = $content | select-string -Pattern "^/$HasAccessPattern\s{0,}$"
|
$matches = @($content | select-string -Pattern "^/$HasAccessPattern\s{0,}$")
|
||||||
$matches.count | Should be 1
|
$matches.count | Should be 1
|
||||||
|
|
||||||
$NoAccessPattern = $permTestNoAccessFilePath.Replace("\", "[/\\]")
|
$NoAccessPattern = $permTestNoAccessFilePath.Replace("\", "[/\\]")
|
||||||
$matches = $content | select-string -Pattern "^/$NoAccessPattern\s{0,}$"
|
$matches = @($content | select-string -Pattern "^/$NoAccessPattern\s{0,}$")
|
||||||
$matches.count | Should be 1
|
$matches.count | Should be 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
#todo: -i -q -v -l -c -C
|
If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
|
||||||
|
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force
|
||||||
|
#todo: -i -q -v -l -c -C
|
||||||
#todo: -S -F -V -e
|
#todo: -S -F -V -e
|
||||||
$tC = 1
|
$tC = 1
|
||||||
$tI = 0
|
$tI = 0
|
||||||
@ -8,7 +10,7 @@ Describe "E2E scenarios for ssh client" -Tags "CI" {
|
|||||||
BeforeAll {
|
BeforeAll {
|
||||||
if($OpenSSHTestInfo -eq $null)
|
if($OpenSSHTestInfo -eq $null)
|
||||||
{
|
{
|
||||||
Throw "`$OpenSSHTestInfo is null. Please run Setup-OpenSSHTestEnvironment to setup test environment."
|
Throw "`$OpenSSHTestInfo is null. Please run Set-OpenSSHTestEnvironment to set test environments."
|
||||||
}
|
}
|
||||||
|
|
||||||
$server = $OpenSSHTestInfo["Target"]
|
$server = $OpenSSHTestInfo["Target"]
|
||||||
@ -20,6 +22,8 @@ Describe "E2E scenarios for ssh client" -Tags "CI" {
|
|||||||
{
|
{
|
||||||
$null = New-Item $testDir -ItemType directory -Force -ErrorAction SilentlyContinue
|
$null = New-Item $testDir -ItemType directory -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
$platform = Get-Platform
|
||||||
|
$skip = ($platform -eq [PlatformType]::Windows) -and ($PSVersionTable.PSVersion.Major -le 2)
|
||||||
|
|
||||||
<#$testData = @(
|
<#$testData = @(
|
||||||
@{
|
@{
|
||||||
@ -112,7 +116,7 @@ Describe "E2E scenarios for ssh client" -Tags "CI" {
|
|||||||
BeforeAll {$tI=1}
|
BeforeAll {$tI=1}
|
||||||
AfterAll{$tC++}
|
AfterAll{$tC++}
|
||||||
|
|
||||||
It "$tC.$tI - stdout to file" {
|
It "$tC.$tI - stdout to file" -skip:$skip {
|
||||||
ssh test_target powershell get-process > $stdoutFile
|
ssh test_target powershell get-process > $stdoutFile
|
||||||
$stdoutFile | Should Contain "ProcessName"
|
$stdoutFile | Should Contain "ProcessName"
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
$client.AddPasswordSetting($password)
|
$client.AddPasswordSetting($password)
|
||||||
}
|
}
|
||||||
AfterEach {
|
AfterEach {
|
||||||
Remove-Item -Path $filePath -Force -ea ignore
|
Remove-Item -Path $filePath -Force -ea SilentlyContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
AfterAll {
|
AfterAll {
|
||||||
|
@ -126,3 +126,4 @@ PubkeyAcceptedKeyTypes ssh-ed25519*
|
|||||||
#AllowUsers allowuser1 allowu*r2 allow?se?3 allowuser4 localuser1 localu*r2 loc?lu?er3 localadmin
|
#AllowUsers allowuser1 allowu*r2 allow?se?3 allowuser4 localuser1 localu*r2 loc?lu?er3 localadmin
|
||||||
#DenyGroups denygroup1 denygr*p2 deny?rou?3
|
#DenyGroups denygroup1 denygr*p2 deny?rou?3
|
||||||
#AllowGroups allowgroup1 allowg*2 allowg?ou?3 Adm*
|
#AllowGroups allowgroup1 allowg*2 allowg?ou?3 Adm*
|
||||||
|
hostkeyagent \\.\pipe\openssh-ssh-agent
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force -DisableNameChecking
|
If ($PSVersiontable.PSVersion.Major -le 2) {$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path}
|
||||||
|
Import-Module $PSScriptRoot\CommonUtils.psm1 -Force
|
||||||
|
|
||||||
$tC = 1
|
$tC = 1
|
||||||
$tI = 0
|
$tI = 0
|
||||||
@ -8,7 +9,7 @@ Describe "Tests for user Key file permission" -Tags "CI" {
|
|||||||
BeforeAll {
|
BeforeAll {
|
||||||
if($OpenSSHTestInfo -eq $null)
|
if($OpenSSHTestInfo -eq $null)
|
||||||
{
|
{
|
||||||
Throw "`$OpenSSHTestInfo is null. Please run Setup-OpenSSHTestEnvironment to setup test environment."
|
Throw "`$OpenSSHTestInfo is null. Please run Set-OpenSSHTestEnvironment to setup test environment."
|
||||||
}
|
}
|
||||||
$testDir = "$($OpenSSHTestInfo["TestDataPath"])\$suite"
|
$testDir = "$($OpenSSHTestInfo["TestDataPath"])\$suite"
|
||||||
if( -not (Test-path $testDir -PathType Container))
|
if( -not (Test-path $testDir -PathType Container))
|
||||||
@ -25,12 +26,12 @@ Describe "Tests for user Key file permission" -Tags "CI" {
|
|||||||
$userName = "$env:USERNAME@$env:USERDOMAIN"
|
$userName = "$env:USERNAME@$env:USERDOMAIN"
|
||||||
$keypassphrase = "testpassword"
|
$keypassphrase = "testpassword"
|
||||||
|
|
||||||
$systemAccount = New-Object System.Security.Principal.NTAccount("NT AUTHORITY", "SYSTEM")
|
$systemSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::LocalSystemSid)
|
||||||
$adminsAccount = New-Object System.Security.Principal.NTAccount("BUILTIN","Administrators")
|
$adminsSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid)
|
||||||
$objUser = New-Object System.Security.Principal.NTAccount($ssouser)
|
$currentUserSid = Get-UserSID -User "$($env:USERDOMAIN)\$($env:USERNAME)"
|
||||||
$pubKeyUserAccount = New-Object System.Security.Principal.NTAccount($pubKeyUser)
|
$objUserSid = Get-UserSID -User $ssouser
|
||||||
$currentUser = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME))
|
$everyoneSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::WorldSid)
|
||||||
$everyone = New-Object System.Security.Principal.NTAccount("EveryOne")
|
$pubKeyUserAccountSid = Get-UserSID -User $pubKeyUser
|
||||||
|
|
||||||
Add-PasswordSetting -Pass $keypassphrase
|
Add-PasswordSetting -Pass $keypassphrase
|
||||||
}
|
}
|
||||||
@ -48,7 +49,7 @@ Describe "Tests for user Key file permission" -Tags "CI" {
|
|||||||
BeforeAll {
|
BeforeAll {
|
||||||
$keyFileName = "sshtest_userPermTestkey_ed25519"
|
$keyFileName = "sshtest_userPermTestkey_ed25519"
|
||||||
$keyFilePath = Join-Path $testDir $keyFileName
|
$keyFilePath = Join-Path $testDir $keyFileName
|
||||||
Remove-Item -path "$keyFilePath*" -Force -ErrorAction Ignore
|
Remove-Item -path "$keyFilePath*" -Force -ErrorAction SilentlyContinue
|
||||||
ssh-keygen.exe -t ed25519 -f $keyFilePath -P $keypassphrase
|
ssh-keygen.exe -t ed25519 -f $keyFilePath -P $keypassphrase
|
||||||
|
|
||||||
$pubKeyUserProfilePath = Join-Path $pubKeyUserProfile .ssh
|
$pubKeyUserProfilePath = Join-Path $pubKeyUserProfile .ssh
|
||||||
@ -58,22 +59,22 @@ Describe "Tests for user Key file permission" -Tags "CI" {
|
|||||||
|
|
||||||
$testAuthorizedKeyPath = Join-Path $pubKeyUserProfilePath authorized_keys
|
$testAuthorizedKeyPath = Join-Path $pubKeyUserProfilePath authorized_keys
|
||||||
Copy-Item "$keyFilePath.pub" $testAuthorizedKeyPath -Force -ErrorAction SilentlyContinue
|
Copy-Item "$keyFilePath.pub" $testAuthorizedKeyPath -Force -ErrorAction SilentlyContinue
|
||||||
Adjust-UserKeyFileACL -FilePath $testAuthorizedKeyPath -Owner $pubKeyUserAccount -OwnerPerms "Read, Write"
|
Repair-AuthorizedKeyPermission -FilePath $testAuthorizedKeyPath -confirm:$false
|
||||||
Add-PermissionToFileACL -FilePath $testAuthorizedKeyPath -User "NT Service\sshd" -Perm "Read"
|
|
||||||
$tI=1
|
$tI=1
|
||||||
}
|
}
|
||||||
AfterAll {
|
AfterAll {
|
||||||
if(Test-Path $testAuthorizedKeyPath) {
|
if(Test-Path $testAuthorizedKeyPath) {
|
||||||
Remove-Item $testAuthorizedKeyPath -Force -ErrorAction Ignore
|
Remove-Item $testAuthorizedKeyPath -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
if(Test-Path $pubKeyUserProfilePath) {
|
if(Test-Path $pubKeyUserProfilePath) {
|
||||||
Remove-Item $pubKeyUserProfilePath -Recurse -Force -ErrorAction Ignore
|
Remove-Item $pubKeyUserProfilePath -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
$tC++
|
$tC++
|
||||||
}
|
}
|
||||||
|
|
||||||
It "$tC.$tI-ssh with private key file -- positive (Secured private key owned by current user)" {
|
It "$tC.$tI-ssh with private key file -- positive (Secured private key owned by current user)" {
|
||||||
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $currentUser -OwnerPerms "Read, Write"
|
Repair-FilePermission -FilePath $keyFilePath -Owners $currentUserSid -FullAccessNeeded $adminsSid,$systemSid,$currentUserSid -confirm:$false
|
||||||
|
|
||||||
#Run
|
#Run
|
||||||
$o = ssh -p $port -i $keyFilePath $pubKeyUser@$server echo 1234
|
$o = ssh -p $port -i $keyFilePath $pubKeyUser@$server echo 1234
|
||||||
$o | Should Be "1234"
|
$o | Should Be "1234"
|
||||||
@ -81,7 +82,7 @@ Describe "Tests for user Key file permission" -Tags "CI" {
|
|||||||
|
|
||||||
It "$tC.$tI-ssh with private key file -- positive(Secured private key owned by Administrators group and current user has no explicit ACE)" {
|
It "$tC.$tI-ssh with private key file -- positive(Secured private key owned by Administrators group and current user has no explicit ACE)" {
|
||||||
#setup to have local admin group as owner and grant it full control
|
#setup to have local admin group as owner and grant it full control
|
||||||
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $adminsAccount -OwnerPerms "FullControl"
|
Repair-FilePermission -FilePath $keyFilePath -Owners $adminsSid -FullAccessNeeded $adminsSid,$systemSid -confirm:$false
|
||||||
|
|
||||||
#Run
|
#Run
|
||||||
$o = ssh -p $port -i $keyFilePath $pubKeyUser@$server echo 1234
|
$o = ssh -p $port -i $keyFilePath $pubKeyUser@$server echo 1234
|
||||||
@ -90,8 +91,7 @@ Describe "Tests for user Key file permission" -Tags "CI" {
|
|||||||
|
|
||||||
It "$tC.$tI-ssh with private key file -- positive(Secured private key owned by Administrators group and current user has explicit ACE)" {
|
It "$tC.$tI-ssh with private key file -- positive(Secured private key owned by Administrators group and current user has explicit ACE)" {
|
||||||
#setup to have local admin group as owner and grant it full control
|
#setup to have local admin group as owner and grant it full control
|
||||||
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $adminsAccount -OwnerPerms "FullControl"
|
Repair-FilePermission -FilePath $keyFilePath -Owners $adminsSid -FullAccessNeeded $adminsSid,$systemSid -ReadAccessNeeded $currentUserSid -confirm:$false
|
||||||
Add-PermissionToFileACL -FilePath $keyFilePath -User $currentUser -Perm "Read"
|
|
||||||
|
|
||||||
#Run
|
#Run
|
||||||
$o = ssh -p $port -i $keyFilePath $pubKeyUser@$server echo 1234
|
$o = ssh -p $port -i $keyFilePath $pubKeyUser@$server echo 1234
|
||||||
@ -100,8 +100,7 @@ Describe "Tests for user Key file permission" -Tags "CI" {
|
|||||||
|
|
||||||
It "$tC.$tI-ssh with private key file -- positive (Secured private key owned by local system)" {
|
It "$tC.$tI-ssh with private key file -- positive (Secured private key owned by local system)" {
|
||||||
#setup to have local system as owner and grant it full control
|
#setup to have local system as owner and grant it full control
|
||||||
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $systemAccount -OwnerPerms "FullControl"
|
Repair-FilePermission -FilePath $keyFilePath -Owners $systemSid -FullAccessNeeded $adminsSid,$systemSid -confirm:$false
|
||||||
Add-PermissionToFileACL -FilePath $keyFilePath -User $adminsAccount -Perm "Read"
|
|
||||||
|
|
||||||
#Run
|
#Run
|
||||||
$o = ssh -p $port -i $keyFilePath $pubKeyUser@$server echo 1234
|
$o = ssh -p $port -i $keyFilePath $pubKeyUser@$server echo 1234
|
||||||
@ -110,10 +109,7 @@ Describe "Tests for user Key file permission" -Tags "CI" {
|
|||||||
|
|
||||||
It "$tC.$tI-ssh with private key file -- negative(other account can access private key file)" {
|
It "$tC.$tI-ssh with private key file -- negative(other account can access private key file)" {
|
||||||
#setup to have current user as owner and grant it full control
|
#setup to have current user as owner and grant it full control
|
||||||
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $currentUser -OwnerPerms "Read, Write"
|
Repair-FilePermission -FilePath $keyFilePath -Owners $currentUserSid -FullAccessNeeded $currentUser,$adminsSid,$systemSid -ReadAccessNeeded $objUserSid -confirm:$false
|
||||||
|
|
||||||
#add ssouser to access the private key
|
|
||||||
Add-PermissionToFileACL -FilePath $keyFilePath -User $objUser -Perm "Read"
|
|
||||||
|
|
||||||
#Run
|
#Run
|
||||||
$o = ssh -p $port -i $keyFilePath -E $logPath $pubKeyUser@$server echo 1234
|
$o = ssh -p $port -i $keyFilePath -E $logPath $pubKeyUser@$server echo 1234
|
||||||
@ -124,8 +120,7 @@ Describe "Tests for user Key file permission" -Tags "CI" {
|
|||||||
|
|
||||||
It "$tC.$tI-ssh with private key file -- negative(the private key has wrong owner)" {
|
It "$tC.$tI-ssh with private key file -- negative(the private key has wrong owner)" {
|
||||||
#setup to have ssouser as owner and grant it full control
|
#setup to have ssouser as owner and grant it full control
|
||||||
Set-FileOwnerAndACL -FilePath $keyFilePath -Owner $objUser -OwnerPerms "Read, Write"
|
Repair-FilePermission -FilePath $keyFilePath -Owners $objUserSid -FullAccessNeeded $objUserSid,$adminsSid,$systemSid -ReadAccessNeeded $objUserSid -confirm:$false
|
||||||
Add-PermissionToFileACL -FilePath $keyFilePath -User $adminsAccount -Perm "FullControl"
|
|
||||||
|
|
||||||
$o = ssh -p $port -i $keyFilePath -E $logPath $pubKeyUser@$server echo 1234
|
$o = ssh -p $port -i $keyFilePath -E $logPath $pubKeyUser@$server echo 1234
|
||||||
$LASTEXITCODE | Should Not Be 0
|
$LASTEXITCODE | Should Not Be 0
|
||||||
|
@ -605,8 +605,9 @@ derelativise_path(const char *path)
|
|||||||
return xstrdup("none");
|
return xstrdup("none");
|
||||||
expanded = tilde_expand_filename(path, getuid());
|
expanded = tilde_expand_filename(path, getuid());
|
||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
/* Windows absolute paths have a drive letter followed by :*/
|
/* Windows absolute paths - \abc, /abc, c:\abc, c:/abc*/
|
||||||
if (*expanded != '\0' && expanded[1] == ':')
|
if (*expanded == '/' || *expanded == '\\' ||
|
||||||
|
(*expanded != '\0' && expanded[1] == ':'))
|
||||||
#else /* !WINDOWS */
|
#else /* !WINDOWS */
|
||||||
if (*expanded == '/')
|
if (*expanded == '/')
|
||||||
#endif /* !WINDOWS */
|
#endif /* !WINDOWS */
|
||||||
|
@ -477,6 +477,9 @@ int do_exec_windows(Session *s, const char *command, int pty) {
|
|||||||
*cmd = '\0';
|
*cmd = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* load user profile */
|
||||||
|
mm_load_profile(s->pw->pw_name, ((INT_PTR)s->authctxt->auth_token) & 0xffffffff);
|
||||||
|
|
||||||
/* start the process */
|
/* start the process */
|
||||||
{
|
{
|
||||||
memset(&si, 0, sizeof(STARTUPINFO));
|
memset(&si, 0, sizeof(STARTUPINFO));
|
||||||
@ -492,7 +495,7 @@ int do_exec_windows(Session *s, const char *command, int pty) {
|
|||||||
si.hStdError = (HANDLE)w32_fd_to_handle(pipeerr[1]);
|
si.hStdError = (HANDLE)w32_fd_to_handle(pipeerr[1]);
|
||||||
si.lpDesktop = NULL;
|
si.lpDesktop = NULL;
|
||||||
|
|
||||||
hToken = s->authctxt->methoddata;
|
hToken = s->authctxt->auth_token;
|
||||||
|
|
||||||
debug("Executing command: %s", exec_command);
|
debug("Executing command: %s", exec_command);
|
||||||
UTF8_TO_UTF16_FATAL(exec_command_w, exec_command);
|
UTF8_TO_UTF16_FATAL(exec_command_w, exec_command);
|
||||||
|
11
sftp.c
11
sftp.c
@ -296,9 +296,14 @@ static void
|
|||||||
local_do_shell(const char *args)
|
local_do_shell(const char *args)
|
||||||
{
|
{
|
||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
/* execute via system call in Windows*/
|
/* execute via system call in Windows*/
|
||||||
if (!*args) {
|
char cmd_path[PATH_MAX] = { 0, };
|
||||||
args = (char *) getenv("ComSpec"); // get name of Windows cmd shell
|
if (!*args){
|
||||||
|
if (!GetSystemDirectory(cmd_path, sizeof(cmd_path)))
|
||||||
|
fatal("GetSystemDirectory failed");
|
||||||
|
|
||||||
|
strcat_s(cmd_path, PATH_MAX, "\\cmd.exe");
|
||||||
|
args = cmd_path;
|
||||||
} else {
|
} else {
|
||||||
convertToBackslash((char *) args);
|
convertToBackslash((char *) args);
|
||||||
}
|
}
|
||||||
|
4
sshd.c
4
sshd.c
@ -1765,9 +1765,7 @@ main(int ac, char **av)
|
|||||||
error("Could not connect to agent \"%s\": %s",
|
error("Could not connect to agent \"%s\": %s",
|
||||||
options.host_key_agent, ssh_err(r));
|
options.host_key_agent, ssh_err(r));
|
||||||
}
|
}
|
||||||
#ifdef WINDOWS /* Windows version always needs and has agent running */
|
|
||||||
have_agent = 1;
|
|
||||||
#endif
|
|
||||||
for (i = 0; i < options.num_host_key_files; i++) {
|
for (i = 0; i < options.num_host_key_files; i++) {
|
||||||
if (options.host_key_files[i] == NULL)
|
if (options.host_key_files[i] == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user