File perm utilites and temporary suspension of psexec usage (#154)

This commit is contained in:
Yanbing 2017-06-02 15:07:26 -07:00 committed by Manoj Ampalam
parent 1d53705be5
commit bbd97bfb66
7 changed files with 573 additions and 15 deletions

View File

@ -37,5 +37,4 @@ after_test:
on_finish:
- ps: |
Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking
Publish-Artifact
Publish-Artifact

View File

@ -0,0 +1,52 @@
param ([switch]$Quiet)
Import-Module $PSScriptRoot\OpenSSHUtils.psm1 -Force -DisableNameChecking
#check sshd config file
$sshdConfigPath = join-path $PSScriptRoot "sshd_config"
if(Test-Path $sshdConfigPath -PathType Leaf)
{
Fix-HostSSHDConfigPermissions -FilePath $sshdConfigPath @psBoundParameters
}
else
{
Write-host "$FilePath does not exist" -ForegroundColor Yellow
}
#check host keys
<#$result = 'n'
if (-not $Quiet) {
Do
{
$input = Read-Host -Prompt "Did you register host private keys with ssh-agent? [Yes] Y; [No] N"
} until ($input -match "^(y(es)?|N(o)?)$")
$result = $Matches[0]
}
if($result.ToLower().Startswith('n'))
{
$warning = @"
To keep the host private keys secure, it is recommended to register them with ssh-agent following
steps in link https://github.com/PowerShell/Win32-OpenSSH/wiki/Install-Win32-OpenSSH.
If you choose not to register the keys with ssh-agent, please grant sshd read access to the private host keys after run this script.
"@
Write-Warning $warning
Write-Host " "
}#>
Get-ChildItem $PSScriptRoot\ssh_host_*_key -ErrorAction Ignore | % {
Fix-HostKeyPermissions -FilePath $_.FullName @psBoundParameters
}
#check authorized_keys
Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList" -ErrorAction Ignore | % {
$userProfilePath = Get-ItemPropertyValue $_.pspath -Name ProfileImagePath -ErrorAction Ignore
$filePath = Join-Path $userProfilePath .ssh\authorized_keys
if(Test-Path $filePath -PathType Leaf)
{
Fix-AuthorizedKeyPermissions -FilePath $filePath @psBoundParameters
}
}
Write-Host " Done."
Write-Host " "

View File

@ -0,0 +1,14 @@
param ([switch]$Quiet)
Import-Module $PSScriptRoot\OpenSSHUtils.psm1 -Force -DisableNameChecking
if(Test-Path ~\.ssh\config -PathType Leaf)
{
Fix-UserSSHConfigPermissions -FilePath ~\.ssh\config @psBoundParameters
}
Get-ChildItem ~\.ssh\* -Include "id_rsa","id_dsa" -ErrorAction Ignore | % {
Fix-UserKeyPermissions -FilePath $_.FullName @psBoundParameters
}
Write-Host " Done."
Write-Host " "

View File

@ -301,7 +301,7 @@ function Package-OpenSSH
$buildDir = Join-Path $repositoryRoot ("bin\" + $folderName + "\" + $Configuration)
$payload = "sshd.exe", "ssh.exe", "ssh-agent.exe", "ssh-add.exe", "sftp.exe"
$payload += "sftp-server.exe", "scp.exe", "ssh-shellhost.exe", "ssh-keygen.exe", "ssh-keyscan.exe"
$payload += "sshd_config", "install-sshd.ps1", "uninstall-sshd.ps1"
$payload += "sshd_config", "install-sshd.ps1", "uninstall-sshd.ps1", "FixHostFilePermissions.ps1", "FixUserFilePermissions.ps1", "OpenSSHUtils.psm1"
$packageName = "OpenSSH-Win64"
if ($NativeHostArch -eq 'x86') {

View File

@ -164,15 +164,18 @@ WARNING: Following changes will be made to OpenSSH configuration
#workaround for the cariggage new line added by git before copy them
(Get-Content $_.FullName -Raw).Replace("`r`n","`n") | Set-Content $_.FullName -Force
Adjust-HostKeyFileACL -FilePath $_.FullName
if (-not ($_.Name.EndsWith(".pub"))) {
Add-PermissionToFileACL -FilePath $_.FullName -User "NT Service\sshd" -Perm "Read"
}
}
#register host keys with agent
Get-ChildItem "$($script:OpenSSHBinPath)\sshtest*hostkey*"| % {
<#Get-ChildItem "$($script:OpenSSHBinPath)\sshtest*hostkey*"| % {
if (-not ($_.Name.EndsWith(".pub"))) {
$cmd = "cmd /c `"$env:ProgramData\chocolatey\lib\sysinternals\tools\psexec -accepteula -nobanner -s -w $($script:OpenSSHBinPath) ssh-add $_ 2> tmp.txt`""
iex $cmd
& "$env:ProgramData\chocolatey\lib\sysinternals\tools\psexec" -accepteula -nobanner -i -s -w $($script:OpenSSHBinPath) cmd.exe /c "ssh-add $_"
Add-PermissionToFileACL -FilePath $_.FullName -User "NT Service\sshd" -Perm "Read"
}
}
}#>
Restart-Service sshd -Force
#Backup existing known_hosts and replace with test version

View File

@ -0,0 +1,474 @@
$systemAccount = New-Object System.Security.Principal.NTAccount("NT AUTHORITY", "SYSTEM")
$adminsAccount = New-Object System.Security.Principal.NTAccount("BUILTIN","Administrators")
$currentUser = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME))
$everyone = New-Object System.Security.Principal.NTAccount("EveryOne")
$sshdAccount = New-Object System.Security.Principal.NTAccount("NT SERVICE","sshd")
<#
.Synopsis
Fix-HostSSHDConfigPermissions
fix the file owner and permissions of sshd_config
#>
function Fix-HostSSHDConfigPermissions
{
param (
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]$FilePath,
[switch] $Quiet)
Fix-FilePermissions -Owners $systemAccount,$adminsAccount -ReadAccessNeeded $sshdAccount @psBoundParameters
}
<#
.Synopsis
Fix-HostKeyPermissions
fix the file owner and permissions of host private and public key
-FilePath: The path of the private host key
#>
function Fix-HostKeyPermissions
{
param (
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]$FilePath,
[switch] $Quiet)
$parameters = $PSBoundParameters
if($parameters["FilePath"].EndsWith(".pub"))
{
$parameters["FilePath"] = $parameters["FilePath"].Replace(".pub", "")
}
Fix-FilePermissions -Owners $systemAccount,$adminsAccount -ReadAccessNeeded $sshdAccount @psBoundParameters
$parameters["FilePath"] += ".pub"
Fix-FilePermissions -Owners $systemAccount,$adminsAccount -ReadAccessOK $everyone -ReadAccessNeeded $sshdAccount @parameters
}
<#
.Synopsis
Fix-AuthorizedKeyPermissions
fix the file owner and permissions of authorized_keys
#>
function Fix-AuthorizedKeyPermissions
{
param (
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]$FilePath,
[switch] $Quiet)
if(-not (Test-Path $FilePath -PathType Leaf))
{
Write-host "$FilePath not found" -ForegroundColor Yellow
return
}
$fullPath = (Resolve-Path $FilePath).Path
$profileListPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"
$profileItem = Get-ChildItem $profileListPath -ErrorAction Ignore | ? {
$fullPath.ToLower().Contains((Get-ItemPropertyValue $_.PSPath -Name ProfileImagePath -ErrorAction Ignore).Tolower())
}
if($profileItem)
{
$userSid = $profileItem.PSChildName
$account = Get-UserAccount -UserSid $userSid
Fix-FilePermissions -Owners $account,$adminsAccount,$systemAccount -AnyAccessOK $account -ReadAccessNeeded $sshdAccount @psBoundParameters
}
else
{
Write-host "$fullPath is not in the profile folder of any user. Skip checking..." -ForegroundColor Yellow
}
}
<#
.Synopsis
Fix-UserKeyPermissions
fix the file owner and permissions of user config
-FilePath: The path of the private user key
#>
function Fix-UserKeyPermissions
{
param (
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]$FilePath,
[switch] $Quiet)
$parameters = $PSBoundParameters
if($parameters["FilePath"].EndsWith(".pub"))
{
$parameters["FilePath"] = $parameters["FilePath"].Replace(".pub", "")
}
Fix-FilePermissions -Owners $currentUser, $adminsAccount,$systemAccount -AnyAccessOK $currentUser @psBoundParameters
$parameters["FilePath"] += ".pub"
Fix-FilePermissions -Owners $currentUser, $adminsAccount,$systemAccount -AnyAccessOK $currentUser -ReadAccessOK $everyone @parameters
}
<#
.Synopsis
Fix-UserSSHConfigPermissions
fix the file owner and permissions of user config
#>
function Fix-UserSSHConfigPermissions
{
param (
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]$FilePath,
[switch] $Quiet)
Fix-FilePermissions -Owners $currentUser,$adminsAccount,$systemAccount -AnyAccessOK $currentUser @psBoundParameters
}
<#
.Synopsis
Fix-FilePermissionInternal
Only validate owner and ACEs of the file
#>
function Fix-FilePermissions
{
param (
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]$FilePath,
[ValidateNotNull()]
[System.Security.Principal.NTAccount[]] $Owners = $currentUser,
[System.Security.Principal.NTAccount[]] $AnyAccessOK,
[System.Security.Principal.NTAccount[]] $ReadAccessOK,
[System.Security.Principal.NTAccount[]] $ReadAccessNeeded,
[switch] $Quiet
)
if(-not (Test-Path $FilePath -PathType Leaf))
{
Write-host "$FilePath not found" -ForegroundColor Yellow
return
}
Write-host " [*] $FilePath"
$return = Fix-FilePermissionInternal @PSBoundParameters
if($return -contains $true)
{
#Write-host "Re-check the health of file $FilePath"
Fix-FilePermissionInternal @PSBoundParameters
}
}
<#
.Synopsis
Fix-FilePermissionInternal
#>
function Fix-FilePermissionInternal {
param (
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]$FilePath,
[ValidateNotNull()]
[System.Security.Principal.NTAccount[]] $Owners = $currentUser,
[System.Security.Principal.NTAccount[]] $AnyAccessOK,
[System.Security.Principal.NTAccount[]] $ReadAccessOK,
[System.Security.Principal.NTAccount[]] $ReadAccessNeeded,
[switch] $Quiet
)
$acl = Get-Acl $FilePath
$needChange = $false
$health = $true
if ($Quiet)
{
$result = 'Y'
}
if(-not $Owners.Contains([System.Security.Principal.NTAccount]$($acl.Owner)))
{
if (-not $Quiet) {
$warning = "Current owner: '$($acl.Owner)'. '$($Owners[0])' should own $FilePath."
Do {
Write-Warning $warning
$input = Read-Host -Prompt "Shall I set the file owner? [Yes] Y; [No] N (default is `"Y`")"
if([string]::IsNullOrEmpty($input))
{
$input = 'Y'
}
} until ($input -match "^(y(es)?|N(o)?)$")
$result = $Matches[0]
}
if($result.ToLower().Startswith('y'))
{
$needChange = $true
$acl.SetOwner($Owners[0])
Write-Host "'$($Owners[0])' now owns $FilePath. " -ForegroundColor Green
}
else
{
$health = $false
Write-Host "The owner is still set to '$($acl.Owner)'." -ForegroundColor Yellow
}
}
$ReadAccessPerm = ([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Read.value__) -bor `
([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Synchronize.value__)
#system and admin groups can have any access to the file; plus the account in the AnyAccessOK list
$realAnyAccessOKList = $AnyAccessOK + @($systemAccount, $adminsAccount)
#if accounts in the ReadAccessNeeded already part of dacl, they are okay; need to make sure they have read access only
$realReadAcessOKList = $ReadAccessOK + $ReadAccessNeeded
#this is orginal list requested by the user, the account will be removed from the list if they already part of the dacl
$realReadAccessNeeded = $ReadAccessNeeded
foreach($a in $acl.Access)
{
if(($realAnyAccessOKList -ne $null) -and $realAnyAccessOKList.Contains($a.IdentityReference))
{
#ignore those accounts listed in the AnyAccessOK list.
}
#If everyone is in the ReadAccessOK list, any user can have read access;
# below block make sure they are granted Read access only
elseif($realReadAcessOKList -and (($realReadAcessOKList.Contains($everyone)) -or `
($realReadAcessOKList.Contains($a.IdentityReference))))
{
if($realReadAccessNeeded -and ($a.IdentityReference.Equals($everyone)))
{
$realReadAccessNeeded.Clear()
}
elseif($realReadAccessNeeded -and $realReadAccessNeeded.Contains($a.IdentityReference))
{
$realReadAccessNeeded = $realReadAccessNeeded | ? { -not $_.Equals($a.IdentityReference) }
}
if (-not ($a.AccessControlType.Equals([System.Security.AccessControl.AccessControlType]::Allow)) -or `
(-not (([System.UInt32]$a.FileSystemRights.value__) -band (-bnot $ReadAccessPerm))))
{
continue;
}
$warning = "'$($a.IdentityReference)' has the following access to $($FilePath): '$($a.FileSystemRights)'."
if($a.IsInherited)
{
if($needChange)
{
Set-Acl -Path $FilePath -AclObject $acl
}
$message = @"
$warning
Need to remove inheritance to fix it.
"@
return Remove-RuleProtection -FilePath $FilePath -Message $message -Quiet:$Quiet
}
if (-not $Quiet) {
Do {
Write-Warning $warning
$input = Read-Host -Prompt "Shall I make it Read only? [Yes] Y; [No] N (default is `"Y`")"
if([string]::IsNullOrEmpty($input))
{
$input = 'Y'
}
} until ($input -match "^(y(es)?|N(o)?)$")
$result = $Matches[0]
}
if($result.ToLower().Startswith('y'))
{
$needChange = $true
$sshAce = New-Object System.Security.AccessControl.FileSystemAccessRule `
($a.IdentityReference, "Read", "None", "None", "Allow")
$acl.SetAccessRule($sshAce)
Write-Host "'$($a.IdentityReference)' now has Read access to $FilePath. " -ForegroundColor Green
}
else
{
$health = $false
Write-Host "'$($a.IdentityReference)' still has these access to $($FilePath): '$($a.FileSystemRights)'." -ForegroundColor Yellow
}
}
#other than AnyAccessOK and ReadAccessOK list, if any other account is allowed, they should be removed from the dacl
elseif($a.AccessControlType.Equals([System.Security.AccessControl.AccessControlType]::Allow))
{
$warning = "'$($a.IdentityReference)' should not have access to '$FilePath'. "
if($a.IsInherited)
{
if($needChange)
{
Set-Acl -Path $FilePath -AclObject $acl
}
$message = @"
$warning
Need to remove inheritance to fix it.
"@
return Remove-RuleProtection -FilePath $FilePath -Message $message -Quiet:$Quiet
}
if (-not $Quiet) {
Do {
Write-Warning $warning
$input = Read-Host -Prompt "Shall I remove this access? [Yes] Y; [No] N (default is `"Y`")"
if([string]::IsNullOrEmpty($input))
{
$input = 'Y'
}
} until ($input -match "^(y(es)?|N(o)?)$")
$result = $Matches[0]
}
if($result.ToLower().Startswith('y'))
{
$needChange = $true
if(-not ($acl.RemoveAccessRule($a)))
{
throw "failed to remove access of $($a.IdentityReference) rule to file $FilePath"
}
else
{
Write-Host "'$($a.IdentityReference)' has no more access to $FilePath." -ForegroundColor Green
}
}
else
{
$health = $false
Write-Host "'$($a.IdentityReference)' still has access to $FilePath." -ForegroundColor Yellow
}
}
}
#This is the real account list we need to add read access to the file
if($realReadAccessNeeded)
{
$realReadAccessNeeded | % {
if([string]::IsNullOrEmpty((Get-UserSID -User $_)))
{
Write-Warning "'$_' needs Read access to $FilePath', but it does not exit on the machine."
}
else
{
if (-not $Quiet) {
$warning = "'$_' needs Read access to $FilePath'."
Do {
Write-Warning $warning
$input = Read-Host -Prompt "Shall I make the above change? [Yes] Y; [No] N (default is `"Y`")"
if([string]::IsNullOrEmpty($input))
{
$input = 'Y'
}
} until ($input -match "^(y(es)?|N(o)?)$")
$result = $Matches[0]
}
if($result.ToLower().Startswith('y'))
{
$needChange = $true
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
($_, "Read", "None", "None", "Allow")
$acl.AddAccessRule($ace)
Write-Host "'$_' now has Read access to $FilePath. " -ForegroundColor Green
}
else
{
$health = $false
Write-Host "'$_' does not have Read access to $FilePath." -ForegroundColor Yellow
}
}
}
}
if($needChange)
{
Set-Acl -Path $FilePath -AclObject $acl
}
if($health)
{
if ($needChange)
{
Write-Host " fixed permissions" -ForegroundColor Yellow
}
else
{
Write-Host " looks good" -ForegroundColor Green
}
}
Write-host " "
}
<#
.Synopsis
Remove-RuleProtection
#>
function Remove-RuleProtection
{
param (
[parameter(Mandatory=$true)]
[string]$FilePath,
[string]$Message,
[switch] $Quiet
)
if (-not $Quiet) {
Do
{
Write-Warning $Message
$input = Read-Host -Prompt "Shall I remove the inheritace? [Yes] Y; [No] N (default is `"Y`")"
if([string]::IsNullOrEmpty($input))
{
$input = 'Y'
}
} until ($input -match "^(y(es)?|N(o)?)$")
$result = $Matches[0]
}
if($result.ToLower().Startswith('y'))
{
$acl = Get-ACL $FilePath
$acl.SetAccessRuleProtection($True, $True)
Set-Acl -Path $FilePath -AclObject $acl
Write-Host "inheritance is removed from $FilePath. " -ForegroundColor Green
return $true
}
else
{
Write-Host "inheritance is not removed from $FilePath. Skip Checking FilePath." -ForegroundColor Yellow
return $false
}
}
<#
.Synopsis
Get-UserAccount
#>
function Get-UserAccount
{
param
( [parameter(Mandatory=$true)]
[string]$UserSid
)
try
{
$objSID = New-Object System.Security.Principal.SecurityIdentifier($UserSid)
$objUser = $objSID.Translate( [System.Security.Principal.NTAccount])
$objUser
}
catch {
}
}
<#
.Synopsis
Get-UserSID
#>
function Get-UserSID
{
param ([System.Security.Principal.NTAccount]$User)
try
{
$strSID = $User.Translate([System.Security.Principal.SecurityIdentifier])
$strSID.Value
}
catch {
}
}
Export-ModuleMember -Function Fix-HostSSHDConfigPermissions, Fix-HostKeyPermissions, Fix-AuthorizedKeyPermissions, Fix-UserKeyPermissions, Fix-UserSSHConfigPermissions

View File

@ -118,8 +118,12 @@
<Message>Generate crtheaders.h and config.h</Message>
</PreBuildEvent>
<PostBuildEvent>
<Command>copy /Y $(SolutionDir)install-ssh*ps1 $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\ &amp; copy /Y $(SolutionDir)uninstall-ssh*ps1 $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\ &amp; If NOT exist $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\sshd_config (copy $(SolutionDir)sshd_config $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\)</Command>
<Message>Copy install-sshd.ps1, uninstall-sshd.ps1 and sshd_config (if not already present) to build directory</Message>
<Command>copy /Y $(SolutionDir)install-ssh*ps1 $(OutDir)
copy /Y $(SolutionDir)uninstall-ssh*ps1 $(OutDir)
copy /Y $(SolutionDir)OpenSSHUtils.psm1 $(OutDir)
copy /Y $(SolutionDir)Fix*FilePermissions.ps1 $(OutDir)
If NOT exist $(OutDir)\sshd_config (copy $(SolutionDir)sshd_config $(OutDir))</Command>
<Message>Copy install-sshd.ps1, uninstall-sshd.ps1, OpenSSHUtils.psm1, FixHostFilePermissions.ps1, FixUserFilePermissions.ps1, and sshd_config (if not already present) to build directory</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@ -146,8 +150,12 @@
<Message>Generate crtheaders.h and config.h</Message>
</PreBuildEvent>
<PostBuildEvent>
<Command>copy /Y $(SolutionDir)install-ssh*ps1 $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\ &amp; copy /Y $(SolutionDir)uninstall-ssh*ps1 $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\ &amp; If NOT exist $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\sshd_config (copy $(SolutionDir)sshd_config $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\)</Command>
<Message>Copy install-sshd.ps1, uninstall-sshd.ps1 and sshd_config (if not already present) to build directory</Message>
<Command>copy /Y $(SolutionDir)install-ssh*ps1 $(OutDir)
copy /Y $(SolutionDir)uninstall-ssh*ps1 $(OutDir)
copy /Y $(SolutionDir)OpenSSHUtils.psm1 $(OutDir)
copy /Y $(SolutionDir)Fix*FilePermissions.ps1 $(OutDir)
If NOT exist $(OutDir)\sshd_config (copy $(SolutionDir)sshd_config $(OutDir))</Command>
<Message>Copy install-sshd.ps1, uninstall-sshd.ps1, OpenSSHUtils.psm1, FixHostFilePermissions.ps1, FixUserFilePermissions.ps1, and sshd_config (if not already present) to build directory</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@ -178,8 +186,12 @@
<Message>Generate crtheaders.h and config.h</Message>
</PreBuildEvent>
<PostBuildEvent>
<Command>copy /Y $(SolutionDir)install-ssh*ps1 $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\ &amp; copy /Y $(SolutionDir)uninstall-ssh*ps1 $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\ &amp; If NOT exist $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\sshd_config (copy $(SolutionDir)sshd_config $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\)</Command>
<Message>Copy install-sshd.ps1, uninstall-sshd.ps1 and sshd_config (if not already present) to build directory</Message>
<Command>copy /Y $(SolutionDir)install-ssh*ps1 $(OutDir)
copy /Y $(SolutionDir)uninstall-ssh*ps1 $(OutDir)
copy /Y $(SolutionDir)OpenSSHUtils.psm1 $(OutDir)
copy /Y $(SolutionDir)Fix*FilePermissions.ps1 $(OutDir)
If NOT exist $(OutDir)\sshd_config (copy $(SolutionDir)sshd_config $(OutDir))</Command>
<Message>Copy install-sshd.ps1, uninstall-sshd.ps1, OpenSSHUtils.psm1, FixHostFilePermissions.ps1, FixUserFilePermissions.ps1, and sshd_config (if not already present) to build directory</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -210,8 +222,12 @@
<Message>Generate crtheaders.h and config.h</Message>
</PreBuildEvent>
<PostBuildEvent>
<Command>copy /Y $(SolutionDir)install-ssh*ps1 $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\ &amp; copy /Y $(SolutionDir)uninstall-ssh*ps1 $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\ &amp; If NOT exist $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\sshd_config (copy $(SolutionDir)sshd_config $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\)</Command>
<Message>Copy install-sshd.ps1, uninstall-sshd.ps1 and sshd_config (if not already present) to build directory</Message>
<Command>copy /Y $(SolutionDir)install-ssh*ps1 $(OutDir)
copy /Y $(SolutionDir)uninstall-ssh*ps1 $(OutDir)
copy /Y $(SolutionDir)OpenSSHUtils.psm1 $(OutDir)
copy /Y $(SolutionDir)Fix*FilePermissions.ps1 $(OutDir)
If NOT exist $(OutDir)\sshd_config (copy $(SolutionDir)sshd_config $(OutDir))</Command>
<Message>Copy install-sshd.ps1, uninstall-sshd.ps1, OpenSSHUtils.psm1, FixHostFilePermissions.ps1, FixUserFilePermissions.ps1, and sshd_config (if not already present) to build directory</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />