-Added the dynamic -UACFilter parameter that completes based on the $UACEnum enumeration

Example: Get-DomainUser -UACFilter DONT_REQ_PREAUTH,NOT_PASSWORD_EXPIRED
        Returns users with kerberos preauth not set AND where the password isn't expired
-Integrated New-DynamicParameter from beatcracker in order to accomplish the dynamic params
-Corrected from help typos
This commit is contained in:
HarmJ0y 2017-06-18 20:00:12 -04:00
parent 7dc41b6fe4
commit 872f711e3d
1 changed files with 466 additions and 13 deletions

View File

@ -731,6 +731,363 @@ New-Struct. :P
# #
######################################################## ########################################################
Function New-DynamicParameter {
<#
.SYNOPSIS
Helper function to simplify creating dynamic parameters.
Adapated from https://beatcracker.wordpress.com/2015/08/10/dynamic-parameters-validateset-and-enums/.
Originally released under the Microsoft Public License (Ms-PL).
.DESCRIPTION
Helper function to simplify creating dynamic parameters.
Example use cases:
Include parameters only if your environment dictates it
Include parameters depending on the value of a user-specified parameter
Provide tab completion and intellisense for parameters, depending on the environment
Please keep in mind that all dynamic parameters you create, will not have corresponding variables created.
Use New-DynamicParameter with 'CreateVariables' switch in your main code block,
('Process' for advanced functions) to create those variables.
Alternatively, manually reference $PSBoundParameters for the dynamic parameter value.
This function has two operating modes:
1. All dynamic parameters created in one pass using pipeline input to the function. This mode allows to create dynamic parameters en masse,
with one function call. There is no need to create and maintain custom RuntimeDefinedParameterDictionary.
2. Dynamic parameters are created by separate function calls and added to the RuntimeDefinedParameterDictionary you created beforehand.
Then you output this RuntimeDefinedParameterDictionary to the pipeline. This allows more fine-grained control of the dynamic parameters,
with custom conditions and so on.
.NOTES
Credits to jrich523 and ramblingcookiemonster for their initial code and inspiration:
https://github.com/RamblingCookieMonster/PowerShell/blob/master/New-DynamicParam.ps1
http://ramblingcookiemonster.wordpress.com/2014/11/27/quick-hits-credentials-and-dynamic-parameters/
http://jrich523.wordpress.com/2013/05/30/powershell-simple-way-to-add-dynamic-parameters-to-advanced-function/
Credit to BM for alias and type parameters and their handling
.PARAMETER Name
Name of the dynamic parameter
.PARAMETER Type
Type for the dynamic parameter. Default is string
.PARAMETER Alias
If specified, one or more aliases to assign to the dynamic parameter
.PARAMETER Mandatory
If specified, set the Mandatory attribute for this dynamic parameter
.PARAMETER Position
If specified, set the Position attribute for this dynamic parameter
.PARAMETER HelpMessage
If specified, set the HelpMessage for this dynamic parameter
.PARAMETER DontShow
If specified, set the DontShow for this dynamic parameter.
This is the new PowerShell 4.0 attribute that hides parameter from tab-completion.
http://www.powershellmagazine.com/2013/07/29/pstip-hiding-parameters-from-tab-completion/
.PARAMETER ValueFromPipeline
If specified, set the ValueFromPipeline attribute for this dynamic parameter
.PARAMETER ValueFromPipelineByPropertyName
If specified, set the ValueFromPipelineByPropertyName attribute for this dynamic parameter
.PARAMETER ValueFromRemainingArguments
If specified, set the ValueFromRemainingArguments attribute for this dynamic parameter
.PARAMETER ParameterSetName
If specified, set the ParameterSet attribute for this dynamic parameter. By default parameter is added to all parameters sets.
.PARAMETER AllowNull
If specified, set the AllowNull attribute of this dynamic parameter
.PARAMETER AllowEmptyString
If specified, set the AllowEmptyString attribute of this dynamic parameter
.PARAMETER AllowEmptyCollection
If specified, set the AllowEmptyCollection attribute of this dynamic parameter
.PARAMETER ValidateNotNull
If specified, set the ValidateNotNull attribute of this dynamic parameter
.PARAMETER ValidateNotNullOrEmpty
If specified, set the ValidateNotNullOrEmpty attribute of this dynamic parameter
.PARAMETER ValidateRange
If specified, set the ValidateRange attribute of this dynamic parameter
.PARAMETER ValidateLength
If specified, set the ValidateLength attribute of this dynamic parameter
.PARAMETER ValidatePattern
If specified, set the ValidatePattern attribute of this dynamic parameter
.PARAMETER ValidateScript
If specified, set the ValidateScript attribute of this dynamic parameter
.PARAMETER ValidateSet
If specified, set the ValidateSet attribute of this dynamic parameter
.PARAMETER Dictionary
If specified, add resulting RuntimeDefinedParameter to an existing RuntimeDefinedParameterDictionary.
Appropriate for custom dynamic parameters creation.
If not specified, create and return a RuntimeDefinedParameterDictionary
Appropriate for a simple dynamic parameter creation.
#>
[CmdletBinding(DefaultParameterSetName = 'DynamicParameter')]
Param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')]
[ValidateNotNullOrEmpty()]
[string]$Name,
[Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')]
[System.Type]$Type = [int],
[Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')]
[string[]]$Alias,
[Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')]
[switch]$Mandatory,
[Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')]
[int]$Position,
[Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')]
[string]$HelpMessage,
[Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')]
[switch]$DontShow,
[Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')]
[switch]$ValueFromPipeline,
[Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')]
[switch]$ValueFromPipelineByPropertyName,
[Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')]
[switch]$ValueFromRemainingArguments,
[Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')]
[string]$ParameterSetName = '__AllParameterSets',
[Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')]
[switch]$AllowNull,
[Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')]
[switch]$AllowEmptyString,
[Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')]
[switch]$AllowEmptyCollection,
[Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')]
[switch]$ValidateNotNull,
[Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')]
[switch]$ValidateNotNullOrEmpty,
[Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')]
[ValidateCount(2,2)]
[int[]]$ValidateCount,
[Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')]
[ValidateCount(2,2)]
[int[]]$ValidateRange,
[Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')]
[ValidateCount(2,2)]
[int[]]$ValidateLength,
[Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')]
[ValidateNotNullOrEmpty()]
[string]$ValidatePattern,
[Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')]
[ValidateNotNullOrEmpty()]
[scriptblock]$ValidateScript,
[Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')]
[ValidateNotNullOrEmpty()]
[string[]]$ValidateSet,
[Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DynamicParameter')]
[ValidateNotNullOrEmpty()]
[ValidateScript({
if(!($_ -is [System.Management.Automation.RuntimeDefinedParameterDictionary]))
{
Throw 'Dictionary must be a System.Management.Automation.RuntimeDefinedParameterDictionary object'
}
$true
})]
$Dictionary = $false,
[Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'CreateVariables')]
[switch]$CreateVariables,
[Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'CreateVariables')]
[ValidateNotNullOrEmpty()]
[ValidateScript({
# System.Management.Automation.PSBoundParametersDictionary is an internal sealed class,
# so one can't use PowerShell's '-is' operator to validate type.
if($_.GetType().Name -notmatch 'Dictionary') {
Throw 'BoundParameters must be a System.Management.Automation.PSBoundParametersDictionary object'
}
$true
})]
$BoundParameters
)
Begin {
$InternalDictionary = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameterDictionary
function _temp { [CmdletBinding()] Param() }
$CommonParameters = (Get-Command _temp).Parameters.Keys
}
Process {
if($CreateVariables) {
$BoundKeys = $BoundParameters.Keys | Where-Object { $CommonParameters -notcontains $_ }
ForEach($Parameter in $BoundKeys) {
if ($Parameter) {
Set-Variable -Name $Parameter -Value $BoundParameters.$Parameter -Scope 1 -Force
}
}
}
else {
$StaleKeys = @()
$StaleKeys = $PSBoundParameters.GetEnumerator() |
ForEach-Object {
if($_.Value.PSobject.Methods.Name -match '^Equals$') {
# If object has Equals, compare bound key and variable using it
if(!$_.Value.Equals((Get-Variable -Name $_.Key -ValueOnly -Scope 0))) {
$_.Key
}
}
else {
# If object doesn't has Equals (e.g. $null), fallback to the PowerShell's -ne operator
if($_.Value -ne (Get-Variable -Name $_.Key -ValueOnly -Scope 0)) {
$_.Key
}
}
}
if($StaleKeys) {
$StaleKeys | ForEach-Object {[void]$PSBoundParameters.Remove($_)}
}
# Since we rely solely on $PSBoundParameters, we don't have access to default values for unbound parameters
$UnboundParameters = (Get-Command -Name ($PSCmdlet.MyInvocation.InvocationName)).Parameters.GetEnumerator() |
# Find parameters that are belong to the current parameter set
Where-Object { $_.Value.ParameterSets.Keys -contains $PsCmdlet.ParameterSetName } |
Select-Object -ExpandProperty Key |
# Find unbound parameters in the current parameter set
Where-Object { $PSBoundParameters.Keys -notcontains $_ }
# Even if parameter is not bound, corresponding variable is created with parameter's default value (if specified)
$tmp = $null
ForEach ($Parameter in $UnboundParameters) {
$DefaultValue = Get-Variable -Name $Parameter -ValueOnly -Scope 0
if(!$PSBoundParameters.TryGetValue($Parameter, [ref]$tmp) -and $DefaultValue) {
$PSBoundParameters.$Parameter = $DefaultValue
}
}
if($Dictionary) {
$DPDictionary = $Dictionary
}
else {
$DPDictionary = $InternalDictionary
}
# Shortcut for getting local variables
$GetVar = {Get-Variable -Name $_ -ValueOnly -Scope 0}
# Strings to match attributes and validation arguments
$AttributeRegex = '^(Mandatory|Position|ParameterSetName|DontShow|HelpMessage|ValueFromPipeline|ValueFromPipelineByPropertyName|ValueFromRemainingArguments)$'
$ValidationRegex = '^(AllowNull|AllowEmptyString|AllowEmptyCollection|ValidateCount|ValidateLength|ValidatePattern|ValidateRange|ValidateScript|ValidateSet|ValidateNotNull|ValidateNotNullOrEmpty)$'
$AliasRegex = '^Alias$'
$ParameterAttribute = New-Object -TypeName System.Management.Automation.ParameterAttribute
switch -regex ($PSBoundParameters.Keys) {
$AttributeRegex {
Try {
$ParameterAttribute.$_ = . $GetVar
}
Catch {
$_
}
continue
}
}
if($DPDictionary.Keys -contains $Name) {
$DPDictionary.$Name.Attributes.Add($ParameterAttribute)
}
else {
$AttributeCollection = New-Object -TypeName Collections.ObjectModel.Collection[System.Attribute]
switch -regex ($PSBoundParameters.Keys) {
$ValidationRegex {
Try {
$ParameterOptions = New-Object -TypeName "System.Management.Automation.${_}Attribute" -ArgumentList (. $GetVar) -ErrorAction Stop
$AttributeCollection.Add($ParameterOptions)
}
Catch { $_ }
continue
}
$AliasRegex {
Try {
$ParameterAlias = New-Object -TypeName System.Management.Automation.AliasAttribute -ArgumentList (. $GetVar) -ErrorAction Stop
$AttributeCollection.Add($ParameterAlias)
continue
}
Catch { $_ }
}
}
$AttributeCollection.Add($ParameterAttribute)
$Parameter = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameter -ArgumentList @($Name, $Type, $AttributeCollection)
$DPDictionary.Add($Name, $Parameter)
}
}
}
End {
if(!$CreateVariables -and !$Dictionary) {
$DPDictionary
}
}
}
function Get-IniContent { function Get-IniContent {
<# <#
.SYNOPSIS .SYNOPSIS
@ -4299,13 +4656,13 @@ for connection to the target domain.
.EXAMPLE .EXAMPLE
Find-DomainObjectPropertyOutlier -User Find-DomainObjectPropertyOutlier -ClassName 'User'
Enumerates users in the current domain with 'outlier' properties filled in. Enumerates users in the current domain with 'outlier' properties filled in.
.EXAMPLE .EXAMPLE
Find-DomainObjectPropertyOutlier -Group -Domain external.local Find-DomainObjectPropertyOutlier -ClassName 'Group' -Domain external.local
Enumerates groups in the external.local forest/domain with 'outlier' properties filled in. Enumerates groups in the external.local forest/domain with 'outlier' properties filled in.
@ -4504,6 +4861,11 @@ Wildcards accepted. Also accepts DOMAIN\user format.
Switch. Only return user objects with non-null service principal names. Switch. Only return user objects with non-null service principal names.
.PARAMETER UACFilter
Dynamic parameter that accepts one or more values from $UACEnum, including
"NOT_X" negation forms. To see all possible values, run '0|ConvertFrom-UACValue -ShowAll'.
.PARAMETER AdminCount .PARAMETER AdminCount
Switch. Return users with '(adminCount=1)' (meaning are/were privileged). Switch. Return users with '(adminCount=1)' (meaning are/were privileged).
@ -4616,6 +4978,12 @@ Search for users with a primary group ID other than 513 ('domain users') and onl
.EXAMPLE .EXAMPLE
Get-DomainUser -UACFilter DONT_REQ_PREAUTH,NOT_PASSWORD_EXPIRED
Find users who doesn't require Kerberos preauthentication and DON'T have an expired password.
.EXAMPLE
$SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword)
Get-DomainUser -Credential $Cred Get-DomainUser -Credential $Cred
@ -4735,6 +5103,14 @@ The raw DirectoryServices.SearchResult object, if -Raw is enabled.
$Raw $Raw
) )
DynamicParam {
$UACValueNames = [Enum]::GetNames($UACEnum)
# add in the negations
$UACValueNames = $UACValueNames | ForEach-Object {$_; "NOT_$_"}
# create new dynamic parameter
New-DynamicParameter -Name UACFilter -ValidateSet $UACValueNames -Type ([array])
}
BEGIN { BEGIN {
$SearcherArguments = @{} $SearcherArguments = @{}
if ($PSBoundParameters['Domain']) { $SearcherArguments['Domain'] = $Domain } if ($PSBoundParameters['Domain']) { $SearcherArguments['Domain'] = $Domain }
@ -4751,6 +5127,11 @@ The raw DirectoryServices.SearchResult object, if -Raw is enabled.
} }
PROCESS { PROCESS {
#bind dynamic parameter to a friendly variable
if ($PSBoundParameters -and ($PSBoundParameters.Count -ne 0)) {
New-DynamicParameter -CreateVariables -BoundParameters $PSBoundParameters
}
if ($UserSearcher) { if ($UserSearcher) {
$IdentityFilter = '' $IdentityFilter = ''
$Filter = '' $Filter = ''
@ -4827,6 +5208,19 @@ The raw DirectoryServices.SearchResult object, if -Raw is enabled.
$Filter += "$LDAPFilter" $Filter += "$LDAPFilter"
} }
# build the LDAP filter for the dynamic UAC filter value
$UACFilter | Where-Object {$_} | ForEach-Object {
if ($_ -match 'NOT_.*') {
$UACField = $_.Substring(4)
$UACValue = [Int]($UACEnum::$UACField)
$Filter += "(!(userAccountControl:1.2.840.113556.1.4.803:=$UACValue))"
}
else {
$UACValue = [Int]($UACEnum::$_)
$Filter += "(userAccountControl:1.2.840.113556.1.4.803:=$UACValue)"
}
}
$UserSearcher.filter = "(&(samAccountType=805306368)$Filter)" $UserSearcher.filter = "(&(samAccountType=805306368)$Filter)"
Write-Verbose "[Get-DomainUser] filter string: $($UserSearcher.filter)" Write-Verbose "[Get-DomainUser] filter string: $($UserSearcher.filter)"
@ -5569,6 +5963,11 @@ A SamAccountName (e.g. WINDOWS10$), DistinguishedName (e.g. CN=WINDOWS10,CN=Comp
SID (e.g. S-1-5-21-890171859-3433809279-3366196753-1124), GUID (e.g. 4f16b6bc-7010-4cbf-b628-f3cfe20f6994), SID (e.g. S-1-5-21-890171859-3433809279-3366196753-1124), GUID (e.g. 4f16b6bc-7010-4cbf-b628-f3cfe20f6994),
or a dns host name (e.g. windows10.testlab.local). Wildcards accepted. or a dns host name (e.g. windows10.testlab.local). Wildcards accepted.
.PARAMETER UACFilter
Dynamic parameter that accepts one or more values from $UACEnum, including
"NOT_X" negation forms. To see all possible values, run '0|ConvertFrom-UACValue -ShowAll'.
.PARAMETER Unconstrained .PARAMETER Unconstrained
Switch. Return computer objects that have unconstrained delegation. Switch. Return computer objects that have unconstrained delegation.
@ -5670,6 +6069,12 @@ Returns all MS SQL servers in the testlab.local domain.
.EXAMPLE .EXAMPLE
Get-DomainComputer -UACFilter TRUSTED_FOR_DELEGATION,SERVER_TRUST_ACCOUNT -Properties dnshostname
Return the dns hostnames of servers trusted for delegation.
.EXAMPLE
Get-DomainComputer -SearchBase "LDAP://OU=secret,DC=testlab,DC=local" -Unconstrained Get-DomainComputer -SearchBase "LDAP://OU=secret,DC=testlab,DC=local" -Unconstrained
Search the specified OU for computeres that allow unconstrained delegation. Search the specified OU for computeres that allow unconstrained delegation.
@ -5783,6 +6188,14 @@ The raw DirectoryServices.SearchResult object, if -Raw is enabled.
$Raw $Raw
) )
DynamicParam {
$UACValueNames = [Enum]::GetNames($UACEnum)
# add in the negations
$UACValueNames = $UACValueNames | ForEach-Object {$_; "NOT_$_"}
# create new dynamic parameter
New-DynamicParameter -Name UACFilter -ValidateSet $UACValueNames -Type ([array])
}
BEGIN { BEGIN {
$SearcherArguments = @{} $SearcherArguments = @{}
if ($PSBoundParameters['Domain']) { $SearcherArguments['Domain'] = $Domain } if ($PSBoundParameters['Domain']) { $SearcherArguments['Domain'] = $Domain }
@ -5799,6 +6212,11 @@ The raw DirectoryServices.SearchResult object, if -Raw is enabled.
} }
PROCESS { PROCESS {
#bind dynamic parameter to a friendly variable
if ($PSBoundParameters -and ($PSBoundParameters.Count -ne 0)) {
New-DynamicParameter -CreateVariables -BoundParameters $PSBoundParameters
}
if ($CompSearcher) { if ($CompSearcher) {
$IdentityFilter = '' $IdentityFilter = ''
$Filter = '' $Filter = ''
@ -5868,6 +6286,18 @@ The raw DirectoryServices.SearchResult object, if -Raw is enabled.
Write-Verbose "[Get-DomainComputer] Using additional LDAP filter: $LDAPFilter" Write-Verbose "[Get-DomainComputer] Using additional LDAP filter: $LDAPFilter"
$Filter += "$LDAPFilter" $Filter += "$LDAPFilter"
} }
# build the LDAP filter for the dynamic UAC filter value
$UACFilter | Where-Object {$_} | ForEach-Object {
if ($_ -match 'NOT_.*') {
$UACField = $_.Substring(4)
$UACValue = [Int]($UACEnum::$UACField)
$Filter += "(!(userAccountControl:1.2.840.113556.1.4.803:=$UACValue))"
}
else {
$UACValue = [Int]($UACEnum::$_)
$Filter += "(userAccountControl:1.2.840.113556.1.4.803:=$UACValue)"
}
}
$CompSearcher.filter = "(&(samAccountType=805306369)$Filter)" $CompSearcher.filter = "(&(samAccountType=805306369)$Filter)"
Write-Verbose "[Get-DomainComputer] Get-DomainComputer filter string: $($CompSearcher.filter)" Write-Verbose "[Get-DomainComputer] Get-DomainComputer filter string: $($CompSearcher.filter)"
@ -5928,6 +6358,11 @@ A SamAccountName (e.g. harmj0y), DistinguishedName (e.g. CN=harmj0y,CN=Users,DC=
SID (e.g. S-1-5-21-890171859-3433809279-3366196753-1108), or GUID (e.g. 4c435dd7-dc58-4b14-9a5e-1fdb0e80d201). SID (e.g. S-1-5-21-890171859-3433809279-3366196753-1108), or GUID (e.g. 4c435dd7-dc58-4b14-9a5e-1fdb0e80d201).
Wildcards accepted. Wildcards accepted.
.PARAMETER UACFilter
Dynamic parameter that accepts one or more values from $UACEnum, including
"NOT_X" negation forms. To see all possible values, run '0|ConvertFrom-UACValue -ShowAll'.
.PARAMETER Domain .PARAMETER Domain
Specifies the domain to use for the query, defaults to the current domain. Specifies the domain to use for the query, defaults to the current domain.
@ -6100,6 +6535,14 @@ The raw DirectoryServices.SearchResult object, if -Raw is enabled.
$Raw $Raw
) )
DynamicParam {
$UACValueNames = [Enum]::GetNames($UACEnum)
# add in the negations
$UACValueNames = $UACValueNames | ForEach-Object {$_; "NOT_$_"}
# create new dynamic parameter
New-DynamicParameter -Name UACFilter -ValidateSet $UACValueNames -Type ([array])
}
BEGIN { BEGIN {
$SearcherArguments = @{} $SearcherArguments = @{}
if ($PSBoundParameters['Domain']) { $SearcherArguments['Domain'] = $Domain } if ($PSBoundParameters['Domain']) { $SearcherArguments['Domain'] = $Domain }
@ -6116,6 +6559,10 @@ The raw DirectoryServices.SearchResult object, if -Raw is enabled.
} }
PROCESS { PROCESS {
#bind dynamic parameter to a friendly variable
if ($PSBoundParameters -and ($PSBoundParameters.Count -ne 0)) {
New-DynamicParameter -CreateVariables -BoundParameters $PSBoundParameters
}
if ($ObjectSearcher) { if ($ObjectSearcher) {
$IdentityFilter = '' $IdentityFilter = ''
$Filter = '' $Filter = ''
@ -6169,6 +6616,19 @@ The raw DirectoryServices.SearchResult object, if -Raw is enabled.
$Filter += "$LDAPFilter" $Filter += "$LDAPFilter"
} }
# build the LDAP filter for the dynamic UAC filter value
$UACFilter | Where-Object {$_} | ForEach-Object {
if ($_ -match 'NOT_.*') {
$UACField = $_.Substring(4)
$UACValue = [Int]($UACEnum::$UACField)
$Filter += "(!(userAccountControl:1.2.840.113556.1.4.803:=$UACValue))"
}
else {
$UACValue = [Int]($UACEnum::$_)
$Filter += "(userAccountControl:1.2.840.113556.1.4.803:=$UACValue)"
}
}
if ($Filter -and $Filter -ne '') { if ($Filter -and $Filter -ne '') {
$ObjectSearcher.filter = "(&$Filter)" $ObjectSearcher.filter = "(&$Filter)"
} }
@ -12654,21 +13114,14 @@ for connection to the target domain.
.EXAMPLE .EXAMPLE
Find-GPOLocation Get-DomainGPOUserLocalGroupMapping
Find all user/group -> machine relationships where the user/group is a member Find all user/group -> machine relationships where the user/group is a member
of the local administrators group on target machines. of the local administrators group on target machines.
.EXAMPLE .EXAMPLE
Find-GPOLocation -UserName dfm -Domain dev.testlab.local Get-DomainGPOUserLocalGroupMapping -Identity dfm -Domain dev.testlab.local
Find all computers that dfm user has local administrator rights to in
the dev.testlab.local domain.
.EXAMPLE
Find-GPOLocation -UserName dfm -Domain dev.testlab.local
Find all computers that dfm user has local administrator rights to in Find all computers that dfm user has local administrator rights to in
the dev.testlab.local domain. the dev.testlab.local domain.
@ -19750,7 +20203,7 @@ $Mod = New-InMemoryModule -ModuleName Win32
# [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPositionalParameters', Scope='Function', Target='psenum')] # [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPositionalParameters', Scope='Function', Target='psenum')]
# used to parse the 'samAccountType' property for users/computers/groups # used to parse the 'samAccountType' property for users/computers/groups
$SamAccountTypeEnum = psenum $Mod PowerView.GroupTypeEnum UInt32 @{ $SamAccountTypeEnum = psenum $Mod PowerView.SamAccountTypeEnum UInt32 @{
DOMAIN_OBJECT = '0x00000000' DOMAIN_OBJECT = '0x00000000'
GROUP_OBJECT = '0x10000000' GROUP_OBJECT = '0x10000000'
NON_SECURITY_GROUP_OBJECT = '0x10000001' NON_SECURITY_GROUP_OBJECT = '0x10000001'
@ -19765,7 +20218,7 @@ $SamAccountTypeEnum = psenum $Mod PowerView.GroupTypeEnum UInt32 @{
} }
# used to parse the 'grouptype' property for groups # used to parse the 'grouptype' property for groups
$GroupTypeEnum = psenum $Mod PowerView.SamAccountTypeEnum UInt32 @{ $GroupTypeEnum = psenum $Mod PowerView.GroupTypeEnum UInt32 @{
CREATED_BY_SYSTEM = '0x00000001' CREATED_BY_SYSTEM = '0x00000001'
GLOBAL_SCOPE = '0x00000002' GLOBAL_SCOPE = '0x00000002'
DOMAIN_LOCAL_SCOPE = '0x00000004' DOMAIN_LOCAL_SCOPE = '0x00000004'