openssh-portable/contrib/win32/openssh/OpenSSHUtils.psm1

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