Tess Gauthier 5124f3dcd4
Fix install path check (#633)
* update check for openssh directory in PATH

* add closing parentheses
2022-11-11 12:41:10 -05:00

854 lines
32 KiB
PowerShell
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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