From bbd97bfb66b04da13fcae2792935c4ec63697fdb Mon Sep 17 00:00:00 2001 From: Yanbing Date: Fri, 2 Jun 2017 15:07:26 -0700 Subject: [PATCH] File perm utilites and temporary suspension of psexec usage (#154) --- appveyor.yml | 3 +- .../win32/openssh/FixHostFilePermissions.ps1 | 52 ++ .../win32/openssh/FixUserFilePermissions.ps1 | 14 + contrib/win32/openssh/OpenSSHBuildHelper.psm1 | 2 +- contrib/win32/openssh/OpenSSHTestHelper.psm1 | 11 +- contrib/win32/openssh/OpenSSHUtils.psm1 | 474 ++++++++++++++++++ contrib/win32/openssh/config.vcxproj | 32 +- 7 files changed, 573 insertions(+), 15 deletions(-) create mode 100644 contrib/win32/openssh/FixHostFilePermissions.ps1 create mode 100644 contrib/win32/openssh/FixUserFilePermissions.ps1 create mode 100644 contrib/win32/openssh/OpenSSHUtils.psm1 diff --git a/appveyor.yml b/appveyor.yml index 0c84dbf96..0d4d3fcc6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -37,5 +37,4 @@ after_test: on_finish: - ps: | Import-Module $env:APPVEYOR_BUILD_FOLDER\contrib\win32\openssh\AppveyorHelper.psm1 -DisableNameChecking - Publish-Artifact - \ No newline at end of file + Publish-Artifact \ No newline at end of file diff --git a/contrib/win32/openssh/FixHostFilePermissions.ps1 b/contrib/win32/openssh/FixHostFilePermissions.ps1 new file mode 100644 index 000000000..b24e0db93 --- /dev/null +++ b/contrib/win32/openssh/FixHostFilePermissions.ps1 @@ -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 " " diff --git a/contrib/win32/openssh/FixUserFilePermissions.ps1 b/contrib/win32/openssh/FixUserFilePermissions.ps1 new file mode 100644 index 000000000..123c6b382 --- /dev/null +++ b/contrib/win32/openssh/FixUserFilePermissions.ps1 @@ -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 " " diff --git a/contrib/win32/openssh/OpenSSHBuildHelper.psm1 b/contrib/win32/openssh/OpenSSHBuildHelper.psm1 index c48b59e6c..8f358c97f 100644 --- a/contrib/win32/openssh/OpenSSHBuildHelper.psm1 +++ b/contrib/win32/openssh/OpenSSHBuildHelper.psm1 @@ -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') { diff --git a/contrib/win32/openssh/OpenSSHTestHelper.psm1 b/contrib/win32/openssh/OpenSSHTestHelper.psm1 index 89bf25210..3c4f16467 100644 --- a/contrib/win32/openssh/OpenSSHTestHelper.psm1 +++ b/contrib/win32/openssh/OpenSSHTestHelper.psm1 @@ -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 diff --git a/contrib/win32/openssh/OpenSSHUtils.psm1 b/contrib/win32/openssh/OpenSSHUtils.psm1 new file mode 100644 index 000000000..5ffc1e135 --- /dev/null +++ b/contrib/win32/openssh/OpenSSHUtils.psm1 @@ -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 diff --git a/contrib/win32/openssh/config.vcxproj b/contrib/win32/openssh/config.vcxproj index 1b1ea347c..8b8245620 100644 --- a/contrib/win32/openssh/config.vcxproj +++ b/contrib/win32/openssh/config.vcxproj @@ -118,8 +118,12 @@ Generate crtheaders.h and config.h - copy /Y $(SolutionDir)install-ssh*ps1 $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\ & copy /Y $(SolutionDir)uninstall-ssh*ps1 $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\ & If NOT exist $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\sshd_config (copy $(SolutionDir)sshd_config $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\) - Copy install-sshd.ps1, uninstall-sshd.ps1 and sshd_config (if not already present) to build directory + 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)) + Copy install-sshd.ps1, uninstall-sshd.ps1, OpenSSHUtils.psm1, FixHostFilePermissions.ps1, FixUserFilePermissions.ps1, and sshd_config (if not already present) to build directory @@ -146,8 +150,12 @@ Generate crtheaders.h and config.h - copy /Y $(SolutionDir)install-ssh*ps1 $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\ & copy /Y $(SolutionDir)uninstall-ssh*ps1 $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\ & If NOT exist $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\sshd_config (copy $(SolutionDir)sshd_config $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\) - Copy install-sshd.ps1, uninstall-sshd.ps1 and sshd_config (if not already present) to build directory + 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)) + Copy install-sshd.ps1, uninstall-sshd.ps1, OpenSSHUtils.psm1, FixHostFilePermissions.ps1, FixUserFilePermissions.ps1, and sshd_config (if not already present) to build directory @@ -178,8 +186,12 @@ Generate crtheaders.h and config.h - copy /Y $(SolutionDir)install-ssh*ps1 $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\ & copy /Y $(SolutionDir)uninstall-ssh*ps1 $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\ & If NOT exist $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\sshd_config (copy $(SolutionDir)sshd_config $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\) - Copy install-sshd.ps1, uninstall-sshd.ps1 and sshd_config (if not already present) to build directory + 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)) + Copy install-sshd.ps1, uninstall-sshd.ps1, OpenSSHUtils.psm1, FixHostFilePermissions.ps1, FixUserFilePermissions.ps1, and sshd_config (if not already present) to build directory @@ -210,8 +222,12 @@ Generate crtheaders.h and config.h - copy /Y $(SolutionDir)install-ssh*ps1 $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\ & copy /Y $(SolutionDir)uninstall-ssh*ps1 $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\ & If NOT exist $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\sshd_config (copy $(SolutionDir)sshd_config $(OpenSSH-Bin-Path)$(Platform)\$(Configuration)\) - Copy install-sshd.ps1, uninstall-sshd.ps1 and sshd_config (if not already present) to build directory + 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)) + Copy install-sshd.ps1, uninstall-sshd.ps1, OpenSSHUtils.psm1, FixHostFilePermissions.ps1, FixUserFilePermissions.ps1, and sshd_config (if not already present) to build directory