mirror of
https://github.com/PowerShell/openssh-portable.git
synced 2025-07-31 01:35:11 +02:00
854 lines
32 KiB
PowerShell
854 lines
32 KiB
PowerShell
Set-StrictMode -Version 2.0
|
||
|
||
<#
|
||
.Synopsis
|
||
Get-UserSID
|
||
#>
|
||
function Get-UserSID
|
||
{
|
||
[CmdletBinding(DefaultParameterSetName='User')]
|
||
param
|
||
( [parameter(Mandatory=$true, ParameterSetName="User")]
|
||
[ValidateNotNull()]
|
||
[System.Security.Principal.NTAccount]$User,
|
||
[parameter(Mandatory=$true, ParameterSetName="WellKnownSidType")]
|
||
[ValidateNotNull()]
|
||
[System.Security.Principal.WellKnownSidType]$WellKnownSidType
|
||
)
|
||
try
|
||
{
|
||
if($PSBoundParameters.ContainsKey("User"))
|
||
{
|
||
$sid = $User.Translate([System.Security.Principal.SecurityIdentifier])
|
||
}
|
||
elseif($PSBoundParameters.ContainsKey("WellKnownSidType"))
|
||
{
|
||
$sid = New-Object System.Security.Principal.SecurityIdentifier($WellKnownSidType, $null)
|
||
}
|
||
$sid
|
||
}
|
||
catch {
|
||
return $null
|
||
}
|
||
}
|
||
|
||
# get the local System user
|
||
$systemSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::LocalSystemSid)
|
||
|
||
# get the Administrators group
|
||
$adminsSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid)
|
||
|
||
# get the everyone
|
||
$everyoneSid = Get-UserSID -WellKnownSidType ([System.Security.Principal.WellKnownSidType]::WorldSid)
|
||
|
||
$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;
|
||
using System.Runtime.InteropServices;
|
||
|
||
public class AdjPriv
|
||
{
|
||
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
|
||
internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
|
||
ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);
|
||
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
|
||
internal static extern IntPtr GetCurrentProcess();
|
||
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
|
||
internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);
|
||
[DllImport("advapi32.dll", SetLastError = true)]
|
||
internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);
|
||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||
internal struct TokPriv1Luid
|
||
{
|
||
public int Count;
|
||
public long Luid;
|
||
public int Attr;
|
||
}
|
||
|
||
internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
|
||
internal const int SE_PRIVILEGE_DISABLED = 0x00000000;
|
||
internal const int TOKEN_QUERY = 0x00000008;
|
||
internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
|
||
public static bool EnablePrivilege(string privilege, bool disable)
|
||
{
|
||
bool retVal;
|
||
TokPriv1Luid tp;
|
||
IntPtr hproc = GetCurrentProcess();
|
||
IntPtr htok = IntPtr.Zero;
|
||
retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
|
||
tp.Count = 1;
|
||
tp.Luid = 0;
|
||
if(disable)
|
||
{
|
||
tp.Attr = SE_PRIVILEGE_DISABLED;
|
||
}
|
||
else
|
||
{
|
||
tp.Attr = SE_PRIVILEGE_ENABLED;
|
||
}
|
||
retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
|
||
retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
|
||
return retVal;
|
||
}
|
||
}
|
||
'@
|
||
|
||
try
|
||
{
|
||
$type = Add-Type $definition -PassThru -ErrorAction SilentlyContinue
|
||
}
|
||
catch
|
||
{
|
||
# Powershell 7 does not add a type if it already exists
|
||
$type = [AdjPriv]
|
||
}
|
||
|
||
<#
|
||
.Synopsis
|
||
Repair-SshdConfigPermission
|
||
Repair the file owner and Permission of sshd_config
|
||
#>
|
||
function Repair-SshdConfigPermission
|
||
{
|
||
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
|
||
param (
|
||
[parameter(Mandatory=$true)]
|
||
[ValidateNotNullOrEmpty()]
|
||
[string]$FilePath)
|
||
|
||
Repair-FilePermission -Owners $systemSid,$adminsSid -FullAccessNeeded $systemSid @psBoundParameters
|
||
}
|
||
|
||
<#
|
||
.Synopsis
|
||
Repair-SshdHostKeyPermission
|
||
Repair the file owner and Permission of host private and public key
|
||
-FilePath: The path of the private host key
|
||
#>
|
||
function Repair-SshdHostKeyPermission
|
||
{
|
||
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
|
||
param (
|
||
[parameter(Mandatory=$true)]
|
||
[ValidateNotNullOrEmpty()]
|
||
[string]$FilePath)
|
||
|
||
if($PSBoundParameters["FilePath"].EndsWith(".pub"))
|
||
{
|
||
$PSBoundParameters["FilePath"] = $PSBoundParameters["FilePath"].Replace(".pub", "")
|
||
}
|
||
|
||
Repair-FilePermission -Owners $systemSid,$adminsSid @psBoundParameters
|
||
|
||
$PSBoundParameters["FilePath"] += ".pub"
|
||
Repair-FilePermission -Owners $systemSid,$adminsSid -ReadAccessOK $everyoneSid @psBoundParameters
|
||
}
|
||
|
||
<#
|
||
.Synopsis
|
||
Repair-AuthorizedKeyPermission
|
||
Repair the file owner and Permission of authorized_keys
|
||
#>
|
||
function Repair-AuthorizedKeyPermission
|
||
{
|
||
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
|
||
param (
|
||
[parameter(Mandatory=$true)]
|
||
[ValidateNotNullOrEmpty()]
|
||
[string]$FilePath)
|
||
|
||
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 SilentlyContinue | ? {
|
||
$properties = Get-ItemProperty $_.pspath -ErrorAction SilentlyContinue
|
||
$userProfilePath = $null
|
||
if($properties)
|
||
{
|
||
$userProfilePath = $properties.ProfileImagePath
|
||
}
|
||
$userProfilePath = $userProfilePath.Replace("\", "\\")
|
||
if ( $properties.PSChildName -notmatch '\.bak$') {
|
||
$fullPath -match "^$userProfilePath\\[\\|\W|\w]+authorized_keys$"
|
||
}
|
||
}
|
||
if($profileItem)
|
||
{
|
||
$userSid = $profileItem.PSChildName
|
||
Repair-FilePermission -Owners $userSid,$adminsSid,$systemSid -AnyAccessOK $userSid -FullAccessNeeded $systemSid @psBoundParameters
|
||
|
||
}
|
||
else
|
||
{
|
||
Write-host "$fullPath is not in the profile folder of any user. Skip checking..." -ForegroundColor Yellow
|
||
}
|
||
}
|
||
|
||
<#
|
||
.Synopsis
|
||
Repair-AdministratorsAuthorizedKeysPermission
|
||
Repair the file owner and Permission of administrators_authorized_keys
|
||
#>
|
||
|
||
function Repair-AdministratorsAuthorizedKeysPermission
|
||
{
|
||
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
|
||
param (
|
||
[parameter(Mandatory=$true)]
|
||
[ValidateNotNullOrEmpty()]
|
||
[string]$FilePath)
|
||
|
||
Repair-FilePermission -Owners $adminsSid -FullAccessNeeded $adminsSid,$systemSid -ReadAccessOK $everyoneSid @psBoundParameters
|
||
|
||
}
|
||
|
||
<#
|
||
.Synopsis
|
||
Repair-ModuliFilePermission
|
||
Repair the file owner and Permission of moduli file
|
||
#>
|
||
|
||
function Repair-ModuliFilePermission
|
||
{
|
||
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
|
||
param (
|
||
[parameter(Mandatory=$true)]
|
||
[ValidateNotNullOrEmpty()]
|
||
[string]$FilePath)
|
||
|
||
Repair-FilePermission -Owners $adminsSid -FullAccessNeeded $adminsSid,$systemSid -ReadAccessOK $everyoneSid @psBoundParameters
|
||
|
||
}
|
||
|
||
<#
|
||
.Synopsis
|
||
Repair-UserKeyPermission
|
||
Repair the file owner and Permission of user config
|
||
-FilePath: The path of the private user key
|
||
-User: The user associated with this ssh config
|
||
#>
|
||
function Repair-UserKeyPermission
|
||
{
|
||
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
|
||
param (
|
||
[parameter(Mandatory=$true, Position = 0)]
|
||
[ValidateNotNullOrEmpty()]
|
||
[string]$FilePath,
|
||
[System.Security.Principal.SecurityIdentifier] $UserSid = $currentUserSid)
|
||
|
||
if($PSBoundParameters["FilePath"].EndsWith(".pub"))
|
||
{
|
||
$PSBoundParameters["FilePath"] = $PSBoundParameters["FilePath"].Replace(".pub", "")
|
||
}
|
||
Repair-FilePermission -Owners $UserSid, $adminsSid,$systemSid -AnyAccessOK $UserSid @psBoundParameters
|
||
|
||
$PSBoundParameters["FilePath"] += ".pub"
|
||
Repair-FilePermission -Owners $UserSid, $adminsSid,$systemSid -AnyAccessOK $UserSid -ReadAccessOK $everyoneSid @psBoundParameters
|
||
}
|
||
|
||
<#
|
||
.Synopsis
|
||
Repair-UserSSHConfigPermission
|
||
Repair the file owner and Permission of user config
|
||
#>
|
||
function Repair-UserSshConfigPermission
|
||
{
|
||
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
|
||
param (
|
||
[parameter(Mandatory=$true)]
|
||
[ValidateNotNullOrEmpty()]
|
||
[string]$FilePath,
|
||
[System.Security.Principal.SecurityIdentifier] $UserSid = $currentUserSid)
|
||
Repair-FilePermission -Owners $UserSid,$adminsSid,$systemSid -AnyAccessOK $UserSid @psBoundParameters
|
||
}
|
||
|
||
<#
|
||
.Synopsis
|
||
Repair-SSHFolderPermission
|
||
Repair the folder owner and permission of ProgramData\ssh folder
|
||
#>
|
||
function Repair-SSHFolderPermission
|
||
{
|
||
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
|
||
param (
|
||
[parameter(Mandatory=$true)]
|
||
[ValidateNotNullOrEmpty()]
|
||
[string]$FilePath)
|
||
|
||
Repair-FilePermission -Owners $adminsSid, $systemSid -FullAccessNeeded $adminsSid,$systemSid -ReadAndExecuteAccessOK $authenticatedUserSid @psBoundParameters
|
||
}
|
||
|
||
<#
|
||
.Synopsis
|
||
Repair-SSHFolderFilePermission
|
||
Repair the file owner and permission of general files inside ProgramData\ssh folder
|
||
#>
|
||
function Repair-SSHFolderFilePermission
|
||
{
|
||
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
|
||
param (
|
||
[parameter(Mandatory=$true)]
|
||
[ValidateNotNullOrEmpty()]
|
||
[string]$FilePath)
|
||
|
||
Repair-FilePermission -Owners $adminsSid, $systemSid -FullAccessNeeded $adminsSid, $systemSid -ReadAndExecuteAccessOK $authenticatedUserSid @psBoundParameters
|
||
}
|
||
|
||
<#
|
||
.Synopsis
|
||
Repair-SSHFolderPrivateKeyPermission
|
||
Repair the file owner and permission of private key files inside ProgramData\ssh folder
|
||
#>
|
||
function Repair-SSHFolderPrivateKeyPermission
|
||
{
|
||
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
|
||
param (
|
||
[parameter(Mandatory=$true)]
|
||
[ValidateNotNullOrEmpty()]
|
||
[string]$FilePath)
|
||
|
||
Repair-FilePermission -Owners $adminsSid, $systemSid -FullAccessNeeded $systemSid, $adminsSid @psBoundParameters
|
||
}
|
||
|
||
<#
|
||
.Synopsis
|
||
Repair-FilePermissionInternal
|
||
Only validate owner and ACEs of the file
|
||
#>
|
||
function Repair-FilePermission
|
||
{
|
||
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
|
||
param (
|
||
[parameter(Mandatory=$true, Position = 0)]
|
||
[ValidateNotNullOrEmpty()]
|
||
[string]$FilePath,
|
||
[ValidateNotNull()]
|
||
[System.Security.Principal.SecurityIdentifier[]] $Owners = $currentUserSid,
|
||
[System.Security.Principal.SecurityIdentifier[]] $AnyAccessOK = $null,
|
||
[System.Security.Principal.SecurityIdentifier[]] $FullAccessNeeded = $null,
|
||
[System.Security.Principal.SecurityIdentifier[]] $ReadAccessOK = $null,
|
||
[System.Security.Principal.SecurityIdentifier[]] $ReadAccessNeeded = $null,
|
||
[System.Security.Principal.SecurityIdentifier[]] $ReadAndExecuteAccessOK = $null
|
||
)
|
||
|
||
if(-not (Test-Path $FilePath))
|
||
{
|
||
Write-host "$FilePath not found" -ForegroundColor Yellow
|
||
return
|
||
}
|
||
|
||
Write-host " [*] $FilePath"
|
||
$return = Repair-FilePermissionInternal @PSBoundParameters
|
||
|
||
if($return -contains $true)
|
||
{
|
||
#Write-host "Re-check the health of file $FilePath"
|
||
Repair-FilePermissionInternal @PSBoundParameters
|
||
}
|
||
}
|
||
|
||
<#
|
||
.Synopsis
|
||
Repair-FilePermissionInternal
|
||
#>
|
||
function Repair-FilePermissionInternal {
|
||
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
|
||
param (
|
||
[parameter(Mandatory=$true, Position = 0)]
|
||
[ValidateNotNullOrEmpty()]
|
||
[string]$FilePath,
|
||
[ValidateNotNull()]
|
||
[System.Security.Principal.SecurityIdentifier[]] $Owners = $currentUserSid,
|
||
[System.Security.Principal.SecurityIdentifier[]] $AnyAccessOK = $null,
|
||
[System.Security.Principal.SecurityIdentifier[]] $FullAccessNeeded = $null,
|
||
[System.Security.Principal.SecurityIdentifier[]] $ReadAccessOK = $null,
|
||
[System.Security.Principal.SecurityIdentifier[]] $ReadAccessNeeded = $null,
|
||
[System.Security.Principal.SecurityIdentifier[]] $ReadAndExecuteAccessOK = $null
|
||
)
|
||
|
||
$acl = Get-Acl $FilePath
|
||
$needChange = $false
|
||
$health = $true
|
||
$paras = @{}
|
||
$PSBoundParameters.GetEnumerator() | % { if((-not $_.key.Contains("Owners")) -and (-not $_.key.Contains("Access"))) { $paras.Add($_.key,$_.Value) } }
|
||
|
||
$currentOwnerSid = Get-UserSid -User $acl.owner
|
||
if($owners -notcontains $currentOwnerSid)
|
||
{
|
||
$newOwner = Get-UserAccount -User $Owners[0]
|
||
$caption = "Current owner: '$($acl.Owner)'. '$newOwner' should own '$FilePath'."
|
||
$prompt = "Shall I set the file owner?"
|
||
$description = "Set '$newOwner' as owner of '$FilePath'."
|
||
if($pscmdlet.ShouldProcess($description, $prompt, $caption))
|
||
{
|
||
Enable-Privilege SeRestorePrivilege | out-null
|
||
$acl.SetOwner($newOwner)
|
||
Set-Acl -Path $FilePath -AclObject $acl -Confirm:$false
|
||
}
|
||
else
|
||
{
|
||
$health = $false
|
||
if(-not $PSBoundParameters.ContainsKey("WhatIf"))
|
||
{
|
||
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__)
|
||
$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
|
||
$realAnyAccessOKList = @($systemSid, $adminsSid)
|
||
if($AnyAccessOK)
|
||
{
|
||
$realAnyAccessOKList += $AnyAccessOK
|
||
}
|
||
|
||
$realFullAccessNeeded = $FullAccessNeeded
|
||
$realReadAccessNeeded = $ReadAccessNeeded
|
||
if($realFullAccessNeeded -contains $everyoneSid)
|
||
{
|
||
$realFullAccessNeeded = @($everyoneSid)
|
||
$realReadAccessNeeded = $null
|
||
}
|
||
|
||
if($realReadAccessNeeded -contains $everyoneSid)
|
||
{
|
||
$realReadAccessNeeded = @($everyoneSid)
|
||
}
|
||
#this is original list requested by the user, the account will be removed from the list if they already part of the dacl
|
||
if($realReadAccessNeeded)
|
||
{
|
||
$realReadAccessNeeded = $realReadAccessNeeded | ? { ($_ -ne $null) -and ($realFullAccessNeeded -notcontains $_) }
|
||
}
|
||
|
||
#if accounts in the ReadAccessNeeded or $realFullAccessNeeded already part of dacl, they are okay;
|
||
#need to make sure they have read access only
|
||
$realReadAcessOKList = $ReadAccessOK + $realReadAccessNeeded
|
||
|
||
foreach($a in $acl.Access)
|
||
{
|
||
if ($a.IdentityReference -is [System.Security.Principal.SecurityIdentifier])
|
||
{
|
||
$IdentityReferenceSid = $a.IdentityReference
|
||
}
|
||
Else
|
||
{
|
||
$IdentityReferenceSid = Get-UserSid -User $a.IdentityReference
|
||
}
|
||
if($IdentityReferenceSid -eq $null)
|
||
{
|
||
$idRefShortValue = ($a.IdentityReference.Value).split('\')[-1]
|
||
$IdentityReferenceSid = Get-UserSID -User $idRefShortValue
|
||
if($IdentityReferenceSid -eq $null)
|
||
{
|
||
Write-Warning "Can't translate '$idRefShortValue'. "
|
||
continue
|
||
}
|
||
}
|
||
|
||
if($realFullAccessNeeded -contains ($IdentityReferenceSid))
|
||
{
|
||
$realFullAccessNeeded = $realFullAccessNeeded | ? { ($_ -ne $null) -and (-not $_.Equals($IdentityReferenceSid)) }
|
||
if($realReadAccessNeeded)
|
||
{
|
||
$realReadAccessNeeded = $realReadAccessNeeded | ? { ($_ -ne $null) -and (-not $_.Equals($IdentityReferenceSid)) }
|
||
}
|
||
if (($a.AccessControlType.Equals([System.Security.AccessControl.AccessControlType]::Allow)) -and `
|
||
((([System.UInt32]$a.FileSystemRights.value__) -band $FullControlPerm) -eq $FullControlPerm))
|
||
{
|
||
continue;
|
||
}
|
||
#update the account to full control
|
||
if($a.IsInherited)
|
||
{
|
||
if($needChange)
|
||
{
|
||
Enable-Privilege SeRestorePrivilege | out-null
|
||
Set-Acl -Path $FilePath -AclObject $acl -Confirm:$false
|
||
}
|
||
|
||
return Remove-RuleProtection @paras
|
||
}
|
||
$caption = "'$($a.IdentityReference)' has the following access to '$FilePath': '$($a.AccessControlType)'-'$($a.FileSystemRights)'."
|
||
$prompt = "Shall I make it Allow FullControl?"
|
||
$description = "Grant '$($a.IdentityReference)' FullControl access to '$FilePath'. "
|
||
|
||
if($pscmdlet.ShouldProcess($description, $prompt, $caption))
|
||
{
|
||
$needChange = $true
|
||
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
|
||
($IdentityReferenceSid, "FullControl", "None", "None", "Allow")
|
||
|
||
$acl.SetAccessRule($ace)
|
||
Write-Host "'$($a.IdentityReference)' now has FullControl access to '$FilePath'. " -ForegroundColor Green
|
||
}
|
||
else
|
||
{
|
||
$health = $false
|
||
if(-not $PSBoundParameters.ContainsKey("WhatIf"))
|
||
{
|
||
Write-Host "'$($a.IdentityReference)' still has these access to '$FilePath': '$($a.AccessControlType)'-'$($a.FileSystemRights)'." -ForegroundColor Yellow
|
||
}
|
||
}
|
||
}
|
||
elseif(($realAnyAccessOKList -contains $everyoneSid) -or ($realAnyAccessOKList -contains $IdentityReferenceSid))
|
||
{
|
||
#ignore those accounts listed in the AnyAccessOK list.
|
||
continue;
|
||
}
|
||
# 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))
|
||
{
|
||
if($realReadAccessNeeded -and ($IdentityReferenceSid.Equals($everyoneSid)))
|
||
{
|
||
$realReadAccessNeeded= $null
|
||
}
|
||
elseif($realReadAccessNeeded)
|
||
{
|
||
$realReadAccessNeeded = $realReadAccessNeeded | ? { ($_ -ne $null ) -and (-not $_.Equals($IdentityReferenceSid)) }
|
||
}
|
||
|
||
if (-not ($a.AccessControlType.Equals([System.Security.AccessControl.AccessControlType]::Allow)) -or `
|
||
(-not (([System.UInt32]$a.FileSystemRights.value__) -band (-bnot $ReadAccessPerm))))
|
||
{
|
||
continue;
|
||
}
|
||
|
||
if($a.IsInherited)
|
||
{
|
||
if($needChange)
|
||
{
|
||
Enable-Privilege SeRestorePrivilege | out-null
|
||
Set-Acl -Path $FilePath -AclObject $acl -Confirm:$false
|
||
}
|
||
|
||
return Remove-RuleProtection @paras
|
||
}
|
||
$caption = "'$($a.IdentityReference)' has the following access to '$FilePath': '$($a.FileSystemRights)'."
|
||
$prompt = "Shall I make it Read 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, "Read", "None", "None", "Allow")
|
||
|
||
$acl.SetAccessRule($ace)
|
||
Write-Host "'$($a.IdentityReference)' now has Read 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
|
||
}
|
||
}
|
||
}
|
||
#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))
|
||
{
|
||
$caption = "'$($a.IdentityReference)' should not have access to '$FilePath'."
|
||
if($a.IsInherited)
|
||
{
|
||
if($needChange)
|
||
{
|
||
Enable-Privilege SeRestorePrivilege | out-null
|
||
Set-Acl -Path $FilePath -AclObject $acl -Confirm:$false
|
||
}
|
||
return Remove-RuleProtection @paras
|
||
}
|
||
|
||
$prompt = "Shall I remove this access?"
|
||
$description = "Remove access rule of '$($a.IdentityReference)' from '$FilePath'."
|
||
|
||
if($pscmdlet.ShouldProcess($description, $prompt, "$caption."))
|
||
{
|
||
$needChange = $true
|
||
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
|
||
($IdentityReferenceSid, $a.FileSystemRights, $a.InheritanceFlags, $a.PropagationFlags, $a.AccessControlType)
|
||
|
||
if(-not ($acl.RemoveAccessRule($ace)))
|
||
{
|
||
Write-Warning "Failed to remove access of '$($a.IdentityReference)' from '$FilePath'."
|
||
}
|
||
else
|
||
{
|
||
Write-Host "'$($a.IdentityReference)' has no more access to '$FilePath'." -ForegroundColor Green
|
||
}
|
||
}
|
||
else
|
||
{
|
||
$health = $false
|
||
if(-not $PSBoundParameters.ContainsKey("WhatIf"))
|
||
{
|
||
Write-Host "'$($a.IdentityReference)' still has access to '$FilePath'." -ForegroundColor Yellow
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if($realFullAccessNeeded)
|
||
{
|
||
$realFullAccessNeeded | % {
|
||
$account = Get-UserAccount -UserSid $_
|
||
if($account -eq $null)
|
||
{
|
||
Write-Warning "'$_' needs FullControl access to '$FilePath', but it can't be translated on the machine."
|
||
}
|
||
else
|
||
{
|
||
$caption = "'$account' needs FullControl access to '$FilePath'."
|
||
$prompt = "Shall I make the above change?"
|
||
$description = "Set '$account' FullControl access to '$FilePath'. "
|
||
|
||
if($pscmdlet.ShouldProcess($description, $prompt, $caption))
|
||
{
|
||
$needChange = $true
|
||
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
|
||
($_, "FullControl", "None", "None", "Allow")
|
||
$acl.AddAccessRule($ace)
|
||
Write-Host "'$account' now has FullControl to '$FilePath'." -ForegroundColor Green
|
||
}
|
||
else
|
||
{
|
||
$health = $false
|
||
if(-not $PSBoundParameters.ContainsKey("WhatIf"))
|
||
{
|
||
Write-Host "'$account' does not have FullControl to '$FilePath'." -ForegroundColor Yellow
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
#This is the real account list we need to add read access to the file
|
||
if($realReadAccessNeeded)
|
||
{
|
||
$realReadAccessNeeded | % {
|
||
$account = Get-UserAccount -UserSid $_
|
||
if($account -eq $null)
|
||
{
|
||
Write-Warning "'$_' needs Read access to '$FilePath', but it can't be translated on the machine."
|
||
}
|
||
else
|
||
{
|
||
$caption = "'$account' needs Read access to '$FilePath'."
|
||
$prompt = "Shall I make the above change?"
|
||
$description = "Set '$account' Read only access to '$FilePath'. "
|
||
|
||
if($pscmdlet.ShouldProcess($description, $prompt, $caption))
|
||
{
|
||
$needChange = $true
|
||
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
|
||
($_, "Read", "None", "None", "Allow")
|
||
$acl.AddAccessRule($ace)
|
||
Write-Host "'$account' now has Read access to '$FilePath'." -ForegroundColor Green
|
||
}
|
||
else
|
||
{
|
||
$health = $false
|
||
if(-not $PSBoundParameters.ContainsKey("WhatIf"))
|
||
{
|
||
Write-Host "'$account' does not have Read access to '$FilePath'." -ForegroundColor Yellow
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if($needChange)
|
||
{
|
||
Enable-Privilege SeRestorePrivilege | out-null
|
||
Set-Acl -Path $FilePath -AclObject $acl -Confirm:$false
|
||
}
|
||
if($health)
|
||
{
|
||
if ($needChange)
|
||
{
|
||
Write-Host " Repaired permissions" -ForegroundColor Yellow
|
||
}
|
||
else
|
||
{
|
||
Write-Host " looks good" -ForegroundColor Green
|
||
}
|
||
}
|
||
Write-host " "
|
||
}
|
||
|
||
<#
|
||
.Synopsis
|
||
Remove-RuleProtection
|
||
#>
|
||
function Remove-RuleProtection
|
||
{
|
||
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
|
||
param (
|
||
[parameter(Mandatory=$true)]
|
||
[string]$FilePath
|
||
)
|
||
$message = "Need to remove the inheritance before repair the rules."
|
||
$prompt = "Shall I remove the inheritance?"
|
||
$description = "Remove inheritance of '$FilePath'."
|
||
|
||
if($pscmdlet.ShouldProcess($description, $prompt, $message))
|
||
{
|
||
$acl = Get-acl -Path $FilePath
|
||
$acl.SetAccessRuleProtection($True, $True)
|
||
Enable-Privilege SeRestorePrivilege | out-null
|
||
Set-Acl -Path $FilePath -AclObject $acl -ErrorVariable e -Confirm:$false
|
||
if($e)
|
||
{
|
||
Write-Warning "Remove-RuleProtection failed with error: $($e[0].ToString())."
|
||
}
|
||
|
||
Write-Host "Inheritance is removed from '$FilePath'." -ForegroundColor Green
|
||
return $true
|
||
}
|
||
elseif(-not $PSBoundParameters.ContainsKey("WhatIf"))
|
||
{
|
||
Write-Host "inheritance is not removed from '$FilePath'. Skip Checking FilePath." -ForegroundColor Yellow
|
||
return $false
|
||
}
|
||
}
|
||
|
||
<#
|
||
.Synopsis
|
||
Get-UserAccount
|
||
#>
|
||
function Get-UserAccount
|
||
{
|
||
[CmdletBinding(DefaultParameterSetName='Sid')]
|
||
param
|
||
( [parameter(Mandatory=$true, ParameterSetName="Sid")]
|
||
[ValidateNotNull()]
|
||
[System.Security.Principal.SecurityIdentifier]$UserSid,
|
||
[parameter(Mandatory=$true, ParameterSetName="WellKnownSidType")]
|
||
[ValidateNotNull()]
|
||
[System.Security.Principal.WellKnownSidType]$WellKnownSidType
|
||
)
|
||
try
|
||
{
|
||
if($PSBoundParameters.ContainsKey("UserSid"))
|
||
{
|
||
$objUser = $UserSid.Translate([System.Security.Principal.NTAccount])
|
||
}
|
||
elseif($PSBoundParameters.ContainsKey("WellKnownSidType"))
|
||
{
|
||
$objSID = New-Object System.Security.Principal.SecurityIdentifier($WellKnownSidType, $null)
|
||
$objUser = $objSID.Translate( [System.Security.Principal.NTAccount])
|
||
}
|
||
$objUser
|
||
}
|
||
catch {
|
||
return $null
|
||
}
|
||
}
|
||
|
||
<#
|
||
.Synopsis
|
||
Enable-Privilege
|
||
#>
|
||
function Enable-Privilege {
|
||
param(
|
||
#The privilege to adjust. This set is taken from
|
||
#http://msdn.microsoft.com/en-us/library/bb530716(VS.85).aspx
|
||
[ValidateSet(
|
||
"SeAssignPrimaryTokenPrivilege", "SeAuditPrivilege", "SeBackupPrivilege",
|
||
"SeChangeNotifyPrivilege", "SeCreateGlobalPrivilege", "SeCreatePagefilePrivilege",
|
||
"SeCreatePermanentPrivilege", "SeCreateSymbolicLinkPrivilege", "SeCreateTokenPrivilege",
|
||
"SeDebugPrivilege", "SeEnableDelegationPrivilege", "SeImpersonatePrivilege", "SeIncreaseBasePriorityPrivilege",
|
||
"SeIncreaseQuotaPrivilege", "SeIncreaseWorkingSetPrivilege", "SeLoadDriverPrivilege",
|
||
"SeLockMemoryPrivilege", "SeMachineAccountPrivilege", "SeManageVolumePrivilege",
|
||
"SeProfileSingleProcessPrivilege", "SeRelabelPrivilege", "SeRemoteShutdownPrivilege",
|
||
"SeRestorePrivilege", "SeSecurityPrivilege", "SeShutdownPrivilege", "SeSyncAgentPrivilege",
|
||
"SeSystemEnvironmentPrivilege", "SeSystemProfilePrivilege", "SeSystemtimePrivilege",
|
||
"SeTakeOwnershipPrivilege", "SeTcbPrivilege", "SeTimeZonePrivilege", "SeTrustedCredManAccessPrivilege",
|
||
"SeUndockPrivilege", "SeUnsolicitedInputPrivilege")]
|
||
$Privilege,
|
||
# Switch to disable the privilege, rather than enable it.
|
||
[Switch] $Disable
|
||
)
|
||
|
||
$type[0]::EnablePrivilege($Privilege, $Disable)
|
||
}
|
||
|
||
Function Add-MachinePath {
|
||
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
|
||
param
|
||
(
|
||
[parameter(Mandatory=$true)]
|
||
[string]$FilePath
|
||
)
|
||
|
||
if (Test-Path $FilePath) {
|
||
$machinePath = (Get-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).Path
|
||
if (-not ($machinePath.ToLower().Contains("$FilePath;".ToLower()) -or $machinePath.ToLower().Contains("$FilePath\;".ToLower())))
|
||
{
|
||
$newPath = $FilePath + ’;’ + $machinePath
|
||
Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH –Value $newPath
|
||
if ((Get-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).Path -eq $newPath) {
|
||
Write-Host "Updated Machine PATH to include OpenSSH directory, restart/re-login required to take effect globally" -ForegroundColor Yellow
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
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, Repair-SSHFolderFilePermission, Repair-SSHFolderPrivateKeyPermission, Add-MachinePath
|