Skip to content

Commit

Permalink
fix folder permissions for programdata\ssh during server install (#549)
Browse files Browse the repository at this point in the history
  • Loading branch information
tgauth authored Feb 5, 2022
1 parent 762704b commit 9d73320
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 5 deletions.
84 changes: 79 additions & 5 deletions contrib/win32/openssh/OpenSSHUtils.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ $everyoneSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKno

$currentUserSid = Get-UserSID -User "$($env:USERDOMAIN)\$($env:USERNAME)"

$authenticatedUserSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::AuthenticatedUserSid)

#Taken from P/Invoke.NET with minor adjustments.
$definition = @'
using System;
Expand Down Expand Up @@ -268,6 +270,33 @@ function Repair-UserSshConfigPermission
Repair-FilePermission -Owners $UserSid,$adminsSid,$systemSid -AnyAccessOK $UserSid @psBoundParameters
}

<#
.Synopsis
Repair-SSHFolderPermission
Repair the file owner and permission of ssh folder & any files inside it
#>
function Repair-SSHFolderPermission
{
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
param (
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]$sshProgDataPath)

# SSH Folder - owner: System or Admins; full access: System, Admins; read or readandexecute/synchronize permissible: Authenticated Users
Repair-FilePermission -FilePath $sshProgDataPath -Owners $adminsSid, $systemSid -FullAccessNeeded $adminsSid,$systemSid -ReadAndExecuteAccessOK $authenticatedUserSid
# Files in SSH Folder (excluding private key files)
# owner: System or Admins; full access: System, Admins; read/readandexecute/synchronize permissable: Authenticated Users
$privateKeyFiles = @("ssh_host_dsa_key", "ssh_host_ecdsa_key", "ssh_host_ed25519_key", "ssh_host_rsa_key")
Get-ChildItem -Path (Join-Path $sshProgDataPath '*') -Recurse -Exclude ($privateKeyFiles) -Force | ForEach-Object {
Repair-FilePermission -FilePath $_.FullName -Owners $adminsSid, $systemSid -FullAccessNeeded $adminsSid, $systemSid -ReadAndExecuteAccessOK $authenticatedUserSid
}
# Private key files - owner: System or Admins; full access: System, Admins
Get-ChildItem -Path (Join-Path $sshProgDataPath '*') -Recurse -Include $privateKeyFiles -Force | ForEach-Object {
Repair-FilePermission -FilePath $_.FullName -Owners $adminsSid, $systemSid -FullAccessNeeded $systemSid, $adminsSid
}
}

<#
.Synopsis
Repair-FilePermissionInternal
Expand All @@ -285,10 +314,11 @@ function Repair-FilePermission
[System.Security.Principal.SecurityIdentifier[]] $AnyAccessOK = $null,
[System.Security.Principal.SecurityIdentifier[]] $FullAccessNeeded = $null,
[System.Security.Principal.SecurityIdentifier[]] $ReadAccessOK = $null,
[System.Security.Principal.SecurityIdentifier[]] $ReadAccessNeeded = $null
[System.Security.Principal.SecurityIdentifier[]] $ReadAccessNeeded = $null,
[System.Security.Principal.SecurityIdentifier[]] $ReadAndExecuteAccessOK = $null
)

if(-not (Test-Path $FilePath -PathType Leaf))
if(-not (Test-Path $FilePath))
{
Write-host "$FilePath not found" -ForegroundColor Yellow
return
Expand Down Expand Up @@ -319,7 +349,8 @@ function Repair-FilePermissionInternal {
[System.Security.Principal.SecurityIdentifier[]] $AnyAccessOK = $null,
[System.Security.Principal.SecurityIdentifier[]] $FullAccessNeeded = $null,
[System.Security.Principal.SecurityIdentifier[]] $ReadAccessOK = $null,
[System.Security.Principal.SecurityIdentifier[]] $ReadAccessNeeded = $null
[System.Security.Principal.SecurityIdentifier[]] $ReadAccessNeeded = $null,
[System.Security.Principal.SecurityIdentifier[]] $ReadAndExecuteAccessOK = $null
)

$acl = Get-Acl $FilePath
Expand Down Expand Up @@ -353,6 +384,7 @@ function Repair-FilePermissionInternal {

$ReadAccessPerm = ([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Read.value__) -bor `
([System.UInt32] [System.Security.AccessControl.FileSystemRights]::Synchronize.value__)
$ReadAndExecuteAccessPerm = $ReadAccessPerm -bor ([System.UInt32] [System.Security.AccessControl.FileSystemRights]::ReadAndExecute.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
Expand Down Expand Up @@ -455,6 +487,48 @@ function Repair-FilePermissionInternal {
#ignore those accounts listed in the AnyAccessOK list.
continue;
}
# Handle ReadAndExecuteAccessOK list and make sure they are only granted Read or ReadAndExecute & Synchronize access
elseif($ReadAndExecuteAccessOK -contains $IdentityReferenceSid)
{
# checks if user access is already either: Read or ReadAndExecute & Synchronize
if (-not ($a.AccessControlType.Equals([System.Security.AccessControl.AccessControlType]::Allow)) -or `
(-not (([System.UInt32]$a.FileSystemRights.value__) -band (-bnot $ReadAndExecuteAccessPerm))))
{
continue;
}

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.FileSystemRights)'."
$prompt = "Shall I make it ReadAndExecute, and Synchronize only?"
$description = "Set'$($a.IdentityReference)' Read access only to '$FilePath'. "

if($pscmdlet.ShouldProcess($description, $prompt, $caption))
{
$needChange = $true
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
($IdentityReferenceSid, "ReadAndExecute, Synchronize", "None", "None", "Allow")

$acl.SetAccessRule($ace)
Write-Host "'$($a.IdentityReference)' now has ReadAndExecute, Synchronize access to '$FilePath'. " -ForegroundColor Green
}
else
{
$health = $false
if(-not $PSBoundParameters.ContainsKey("WhatIf"))
{
Write-Host "'$($a.IdentityReference)' still has these access to '$FilePath': '$($a.FileSystemRights)'." -ForegroundColor Yellow
}
}
}
#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 -contains $everyoneSid) -or ($realReadAcessOKList -contains $IdentityReferenceSid))
Expand Down Expand Up @@ -649,7 +723,7 @@ function Remove-RuleProtection
[string]$FilePath
)
$message = "Need to remove the inheritance before repair the rules."
$prompt = "Shall I remove the inheritace?"
$prompt = "Shall I remove the inheritance?"
$description = "Remove inheritance of '$FilePath'."

if($pscmdlet.ShouldProcess($description, $prompt, $message))
Expand Down Expand Up @@ -734,4 +808,4 @@ function Enable-Privilege {
$type[0]::EnablePrivilege($Privilege, $Disable)
}

Export-ModuleMember -Function Repair-FilePermission, Repair-SshdConfigPermission, Repair-SshdHostKeyPermission, Repair-AuthorizedKeyPermission, Repair-UserKeyPermission, Repair-UserSshConfigPermission, Enable-Privilege, Get-UserAccount, Get-UserSID, Repair-AdministratorsAuthorizedKeysPermission, Repair-ModuliFilePermission
Export-ModuleMember -Function Repair-FilePermission, Repair-SshdConfigPermission, Repair-SshdHostKeyPermission, Repair-AuthorizedKeyPermission, Repair-UserKeyPermission, Repair-UserSshConfigPermission, Enable-Privilege, Get-UserAccount, Get-UserSID, Repair-AdministratorsAuthorizedKeysPermission, Repair-ModuliFilePermission, Repair-SSHFolderPermission
8 changes: 8 additions & 0 deletions contrib/win32/openssh/install-sshd.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# @friism - Fixed issue with invalid SDDL on Set-Acl
# @manojampalam - removed ntrights.exe dependency
# @bingbing8 - removed secedit.exe dependency
# @tessgauthier - added permissions check for %programData%/ssh

$ErrorActionPreference = 'Stop'

Expand Down Expand Up @@ -84,6 +85,13 @@ if (Test-Path $moduliPath -PathType Leaf)
Repair-ModuliFilePermission -FilePath $moduliPath @psBoundParameters -confirm:$false
}

# If %programData%/ssh folder already exists, verify and, if necessary and approved by user, fix permissions
$sshProgDataPath = Join-Path $env:ProgramData "ssh"
if (Test-Path $sshProgDataPath)
{
Repair-SSHFolderPermission -sshProgDataPath $sshProgDataPath
}

#register etw provider
wevtutil im `"$etwman`"

Expand Down

0 comments on commit 9d73320

Please sign in to comment.