mirror of
https://github.com/PowerShell/openssh-portable.git
synced 2025-08-27 04:38:34 +02:00
OpenSSh privilege separation model - http://www.citi.umich.edu/u/provos/ssh/privsep.html Posix_spawn is implemented in POSIX adapter as an alternative to fork() that is heavily used in Privilege separation. Additional state info is added to sshd to accommodate distinguishing the various modes (privileged monitor, unprivileged child, authenticated child). Required service state (like config and host keys) is transmitted over pipes from monitor to child processes. Changes to installation scripts and tests to accomodate new architectural changes
694 lines
26 KiB
PowerShell
694 lines
26 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)"
|
|
|
|
#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;
|
|
}
|
|
}
|
|
'@
|
|
|
|
$type = Add-Type $definition -PassThru -ErrorAction SilentlyContinue
|
|
|
|
<#
|
|
.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-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-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
|
|
)
|
|
|
|
if(-not (Test-Path $FilePath -PathType Leaf))
|
|
{
|
|
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
|
|
)
|
|
|
|
$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__)
|
|
$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;
|
|
}
|
|
#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 inheritace?"
|
|
$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)
|
|
}
|
|
|
|
Export-ModuleMember -Function Repair-FilePermission, Repair-SshdConfigPermission, Repair-SshdHostKeyPermission, Repair-AuthorizedKeyPermission, Repair-UserKeyPermission, Repair-UserSshConfigPermission, Enable-Privilege, Get-UserAccount, Get-UserSID
|