BW.Utils.GroupPolicy.WMIFilter.psm1
using namespace System.DirectoryServices.ActiveDirectory using namespace System.DirectoryServices using namespace System.Security.Principal using namespace System.Collections # .ExternalHelp BW.Utils.GroupPolicy.WMIFilter-help.xml function New-WmiFilterObject { [OutputType([WmiFilterObject])] param ( [Parameter(Mandatory, Position=1)] [ValidatePattern('^SELECT.*FROM.*WHERE.*$')] [ValidateNotNullOrEmpty()] [string] $Filter, [ValidateNotNullOrEmpty()] [string] $NameSpace = 'root\CIMv2', [ValidateSet('WQL')] [string] $Language = 'WQL', [WmiFilterList] $WmiFilterList ) $WmiFilterObject = [WmiFilterObject]@{ Filter = $Filter NameSpace = $NameSpace Language = $Language } if ( $WmiFilterList -is [WmiFilterList] ) { $WmiFilterList.Add( $WmiFilterObject ) > $null } else { # note that the comma is important so PowerShell doesn't convert to an Array return $WmiFilterObject } } # .ExternalHelp BW.Utils.GroupPolicy.WMIFilter-help.xml function New-WmiFilterList { [CmdletBinding(DefaultParameterSetName='EmptyList')] [OutputType([WmiFilterList])] param ( [Parameter(ParameterSetName='FromObject', Mandatory, Position=1)] [WmiFilterObject[]] $WmiFilterObject, [Parameter(ParameterSetName='FromString', Mandatory, Position=1)] [ValidatePattern('^SELECT.*FROM.*WHERE.*$')] [ValidateNotNullOrEmpty()] [string[]] $Filter, [Parameter(ParameterSetName='FromString')] [ValidateNotNullOrEmpty()] [string] $NameSpace = 'root\CIMv2', [Parameter(ParameterSetName='FromString')] [ValidateSet('WQL')] [string] $Language = 'WQL' ) $WmiFilterList = [WmiFilterList]::new() switch ( $PSCmdlet.ParameterSetName ) { 'FromObject' { $WmiFilterList.AddRange( $WmiFilterObject ) > $null } 'FromString' { $Filter | ForEach-Object { $WmiFilterList.Add([WmiFilterObject]@{ Filter = $Filter NameSpace = $NameSpace Language = $Language }) > $null } } } # note that the comma is important so PowerShell doesn't convert to an Array return , $WmiFilterList } # .ExternalHelp BW.Utils.GroupPolicy.WMIFilter-help.xml function Get-GPWmiFilter { [CmdletBinding(DefaultParameterSetName='Name')] param( [Parameter(Position=1, ParameterSetName='Name')] [SupportsWildcards()] [string] $Name = '*', [Parameter(Position=1, ParameterSetName='GUID')] [guid] $GUID, [Alias('DnsDomain')] [string] $DomainName = $env:USERDNSDOMAIN, [pscredential] $Credential, [Parameter(ValueFromRemainingArguments, DontShow)] $UnboundArguments ) $PSBoundParameters.Remove( 'UnboundArguments' ) > $null $DomainParams = _GetDomainParams @PSBoundParameters $NamingContext = _GetNamingContext @DomainParams -ErrorAction Stop $Searcher = _GetSearcher -SearchBase "CN=SOM,CN=WMIPolicy,CN=System,$NamingContext" -SearchFilter '(objectclass=msWMI-Som)' @DomainParams -ErrorAction Stop $Searcher.FindAll().ForEach({ $_.Properties }) | Select-Object ` @{ N='DistinguishedName' ; E={ $_.distinguishedname }}, @{ N='Name' ; E={ $_.'mswmi-name' }}, @{ N='GUID' ; E={ [guid][string]$_.'mswmi-id' }}, @{ N='Description' ; E={ $_.'mswmi-parm1' }}, @{ N='Author' ; E={ $_.'mswmi-author' }}, @{ N='Filters' ; E={ , [WmiFilterList][string]$_.'mswmi-parm2' }} | Where-Object { ( $PSCmdlet.ParameterSetName -eq 'Name' -and $_.Name -like $Name ) -or ( $PSCmdlet.ParameterSetName -eq 'GUID' -and $_.GUID -eq $GUID ) } $Searcher.Dispose() } # .ExternalHelp BW.Utils.GroupPolicy.WMIFilter-help.xml function New-GPWmiFilter { param( [Parameter(Mandatory, Position=1)] [string] $Name, [string] $Description, [guid] $GUID = ( [guid]::NewGuid() ), [Parameter(Mandatory)] [WmiFilterObject[]] $Filter, [Alias('DnsDomain')] [string] $DomainName = $env:USERDNSDOMAIN, [pscredential] $Credential ) $DomainParams = _GetDomainParams @PSBoundParameters if ( $Credential ) { $Author = $Credential.UserName } else { $Author = [WindowsIdentity]::GetCurrent().Name } # verify that the WMI filter doesn't already exist if ( $PSCmdlet.ParameterSetName -eq 'Name' -and ( Get-GPWmiFilter -Name $Name @DomainParams ) ) { Write-Error ( 'WMI filter ''{0}'' already exists in domain {1}!' -f $Name, $DomainName ) return } elseif ( $PSCmdlet.ParameterSetName -eq 'GUID' -and ( Get-GPWmiFilter -GUID $GUID @DomainParams ) ) { Write-Error ( 'WMI filter with GUID ''{0}'' already exists in domain {1}!' -f $GUID.ToString('B'), $DomainName ) return } $NamingContext = _GetNamingContext @DomainParams -ErrorAction Stop # get the container where the WMI filters are stored $SOMContainer = [adsi]"LDAP://CN=SOM,CN=WMIPolicy,CN=System,$NamingContext" if ( $Credential ) { $SOMContainer.PSBase.Username = $Credential.UserName $SOMContainer.PSBase.Password = $Credential.GetNetworkCredential().Password } # create a time stamp $Created = [datetime]::UtcNow.ToString('yyyyMMddHHmmss.ffffff-000') try { $WmiFilter = $SOMContainer.Create( 'msWMI-Som', "CN=$($GUID.ToString('B'))" ) $WmiFilter.Put( 'msWMI-Name', $Name ) $WmiFilter.Put( 'msWMI-Parm1', $Description ) $WmiFilter.Put( 'msWMI-Parm2', [WmiFilterList]::new($Filter).ToString() ) $WmiFilter.Put( 'msWMI-Author', $Author ) $WmiFilter.Put( 'msWMI-ID', $GUID.ToString('B') ) $WmiFilter.Put( 'instanceType', 4 ) $WmiFilter.Put( 'showInAdvancedViewOnly', 'TRUE' ) $WmiFilter.Put( 'distinguishedname', "CN=$($GUID.ToString('B')),$SOMContainer" ) $WmiFilter.Put( 'msWMI-ChangeDate', $Created ) $WmiFilter.Put( 'msWMI-CreationDate', $Created ) $WmiFilter.SetInfo() } catch { Write-Error ( 'Failed to create WMI filter ''{0}'' in domain {1}. You may need to first enable ''Allow System Only Change'' for the domain. You can use the Set-ADSystemOnlyChange cmdlet to make this change.' -f $Name, $DomainName ) } } # .ExternalHelp BW.Utils.GroupPolicy.WMIFilter-help.xml function Set-GPWmiFilter { [CmdletBinding(DefaultParameterSetName='Name', SupportsShouldProcess, ConfirmImpact='Medium')] param( [Parameter(Mandatory, Position=1, ParameterSetName='Name')] [string] $Name, [Parameter(Mandatory, Position=1, ParameterSetName='GUID')] [guid] $GUID, [string] $NewName, [string] $Description, [WmiFilterObject[]] $Filter, [Alias('DnsDomain')] [string] $DomainName = $env:USERDNSDOMAIN, [pscredential] $Credential ) $DomainParams = _GetDomainParams @PSBoundParameters # verify that the WMI filter exists if ( $PSCmdlet.ParameterSetName -eq 'Name' -and -not( $WmiFilterObject = Get-GPWmiFilter -Name $Name @DomainParams ) ) { Write-Error ( 'WMI filter ''{0}'' could not be found in domain {1}!' -f $Name, $DomainName ) return } elseif ( $PSCmdlet.ParameterSetName -eq 'GUID' -and -not( $WmiFilterObject = Get-GPWmiFilter -GUID $GUID @DomainParams ) ) { Write-Error ( 'WMI filter with GUID ''{0}'' could not be found in domain {1}!' -f $GUID.ToString('B'), $DomainName ) return } $WmiFilter = [adsi]"LDAP://$($WmiFilterObject.DistinguishedName)" if ( $Credential ) { $WmiFilter.PSBase.Username = $Credential.UserName $WmiFilter.PSBase.Password = $Credential.GetNetworkCredential().Password } $IsUpdated = $false if ( $NewName ) { $WmiFilter.'msWMI-Name' = $NewName $IsUpdated = $true } if ( $Description ) { $WmiFilter.'msWMI-Parm1' = $Description $IsUpdated = $true } if ( $Filter ) { $WmiFilter.'msWMI-Parm2' = [WmiFilterList]::new( $Filter ).ToString() $IsUpdated = $true } if ( $IsUpdated ) { if ( $PSCmdlet.ShouldProcess( $WmiFilterObject.Name, 'update' ) ) { try { $WmiFilter.'msWMI-ChangeDate' = [datetime]::UtcNow.ToString('yyyyMMddHHmmss.ffffff-000') $WmiFilter.CommitChanges() } catch { Write-Error ( 'Failed to update WMI filter ''{0}'' in domain {1}. You may need to first enable ''Allow System Only Change'' for the domain. You can use the Set-ADSystemOnlyChange cmdlet to make this change.' -f $Name, $DomainName ) } } } else { Write-Warning ( 'No changes made to WMI filter ''{0}'' in domain {1}.' -f $WmiFilterObject.Name, $DomainName ) } } # .ExternalHelp BW.Utils.GroupPolicy.WMIFilter-help.xml function Remove-GPWmiFilter { [CmdletBinding(DefaultParameterSetName='Name', SupportsShouldProcess, ConfirmImpact='High')] param( [Parameter(Mandatory, Position=1, ParameterSetName='Name')] [string] $Name, [Parameter(Mandatory, Position=1, ParameterSetName='GUID')] [guid] $GUID, [Alias('DnsDomain')] [string] $DomainName = $env:USERDNSDOMAIN, [pscredential] $Credential ) $DomainParams = _GetDomainParams @PSBoundParameters # verify that the WMI filter exists if ( $PSCmdlet.ParameterSetName -eq 'Name' -and -not( $WmiFilterObject = Get-GPWmiFilter -Name $Name @DomainParams ) ) { Write-Error ( 'WMI filter ''{0}'' could not be found in domain {1}!' -f $Name, $DomainName ) return } elseif ( $PSCmdlet.ParameterSetName -eq 'GUID' -and -not( $WmiFilterObject = Get-GPWmiFilter -GUID $GUID @DomainParams ) ) { Write-Error ( 'WMI filter with GUID ''{0}'' could not be found in domain {1}!' -f $GUID.ToString('B'), $DomainName ) return } $NamingContext = _GetNamingContext @DomainParams -ErrorAction Stop # verify this WMI filter isn't in use $Searcher = _GetSearcher -SearchBase "CN=Policies,CN=System,$NamingContext" -SearchFilter "(&(objectclass=groupPolicyContainer)(gPCWQLFilter=*$($WmiFilterObject.GUID.ToString('B'))*))" @DomainParams -ErrorAction Stop $LinkedGPOs = $Searcher.FindAll().ForEach({ $_.Properties }) | Select-Object ` @{ N='Name' ; E={ $_['displayName'] }}, @{ N='GUID' ; E={ [guid][string]$_['name'] }} $Searcher.Dispose(); if ( $LinkedGPOs.Count -gt 0 ) { Write-Verbose 'Linked Group Policies:' Write-Verbose '' Write-Verbose 'GUID | NAME' Write-Verbose '---------------------------------------|----------------------------------------' $LinkedGPOs | ForEach-Object { Write-Verbose ( '{1} | {0}' -f $_.Name, $_.GUID.ToString('B') ) } if ( $PSCmdlet.ParameterSetName -eq 'Name' ) { Write-Error ( 'WMI filter ''{0}'' in domain {1} could not be removed! It is linked to {2} Group Policies.' -f $Name, $DomainName, $LinkedGPOs.Count ) } else { Write-Error ( 'WMI filter with GUID ''{0}'' in domain {1} could not be removed! It is linked to {2} Group Policies.' -f $GUID.ToString('B'), $DomainName, $LinkedGPOs.Count ) } return } if ( $PSCmdlet.ShouldProcess( $WmiFilterObject.Name, 'remove' ) ) { $SOMContainer = [adsi]"LDAP://CN=SOM,CN=WMIPolicy,CN=System,$NamingContext" if ( $Credential ) { $SOMContainer.PSBase.Username = $Credential.UserName $SOMContainer.PSBase.Password = $Credential.GetNetworkCredential().Password } $WmiObject = $SOMContainer.Children.Find( "CN=$($WmiFilterObject.GUID.ToString('B'))" ) $SOMContainer.Children.Remove( $WmiObject ) $SOMContainer.Dispose() } } # .ExternalHelp BW.Utils.GroupPolicy.WMIFilter-help.xml function Set-ADSystemOnlyChange { param( [Parameter(Mandatory, ValueFromPipeline, Position=1, ParameterSetName='Enable_Remote')] [Parameter(Mandatory, ValueFromPipeline, Position=1, ParameterSetName='Disable_Remote')] [string[]] $ComputerName, [Parameter(Mandatory, ParameterSetName='Enable_Local')] [Parameter(Mandatory, ParameterSetName='Enable_Remote')] [switch] $Enable, [Parameter(Mandatory, ParameterSetName='Disable_Local')] [Parameter(Mandatory, ParameterSetName='Disable_Remote')] [switch] $Disable, [Parameter(ParameterSetName='Enable_Remote')] [Parameter(ParameterSetName='Disable_Remote')] [pscredential] $Credential ) begin { $CommandSplat = @{} if ( $Credential ) { $CommandSplat.Credential = $Credential } [ArrayList]$Computers = @() } process { $ComputerName.ForEach({ $Computers.Add( $_ ) > $null }) } end { if ( $Computers.Count -gt 0 ) { [string[]]$CommandSplat.ComputerName = $Computers } if ( $Enable ) { Write-Warning "Enabling the setting 'Allow System Only Change' should be a temporary measure. Don't foreget to revert this setting once changes are applied." } Invoke-Command @CommandSplat -ScriptBlock { # check for NTDS service if ( -not( Get-Service NTDS -ErrorAction SilentlyContinue ) ) { throw 'Must be run on a domain controller!' } # check for and create if missing the Parameters registry key $ParametersKey = Get-Item -Path 'HKLM:\System\CurrentControlSet\Services\NTDS\Parameters' -ErrorAction SilentlyContinue if ( -not $ParametersKey ) { New-Item -Path 'HKLM:\System\CurrentControlSet\Services\NTDS\Parameters' -ItemType RegistryKey > $null } # check if 'Allow System Only Change' value exists $SystemOnlyChangeValue = Get-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Services\NTDS\Parameters' -Name 'Allow System Only Change' -ErrorAction SilentlyContinue if ( -not $SystemOnlyChangeValue ) { New-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Services\NTDS\Parameters' -Name 'Allow System Only Change' -Value ([int]$Using:Enable.IsPresent) -PropertyType DWORD > $null } else { Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Services\NTDS\Parameters' -Name 'Allow System Only Change' -Value ([int]$Using:Enable.IsPresent) > $null } } } } # .ExternalHelp BW.Utils.GroupPolicy.WMIFilter-help.xml function Test-ADSystemOnlyChangeEnabled { [CmdletBinding(DefaultParameterSetName='Local')] param( [Parameter(Mandatory, ValueFromPipeline, Position=1, ParameterSetName='Remote')] [string[]] $ComputerName, [Parameter(ParameterSetName='Remote')] [pscredential] $Credential ) begin { $CommandSplat = @{} if ( $Credential ) { $CommandSplat.Credential = $Credential } [ArrayList]$Computers = @() } process { $ComputerName.ForEach({ $Computers.Add( $_ ) > $null }) } end { if ( $Computers.Count -gt 0 ) { [string[]]$CommandSplat.ComputerName = $Computers } Invoke-Command @CommandSplat -ScriptBlock { # check for NTDS service if ( -not( Get-Service NTDS -ErrorAction SilentlyContinue ) ) { throw 'Must be run on a domain controller!' } # check for and create if missing the Parameters registry key $ParametersKey = Get-Item -Path 'HKLM:\System\CurrentControlSet\Services\NTDS\Parameters' -ErrorAction SilentlyContinue if ( -not $ParametersKey ) { return $false } # check if 'Allow System Only Change' value exists $SystemOnlyChangeValue = Get-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Services\NTDS\Parameters' -Name 'Allow System Only Change' -ErrorAction SilentlyContinue | Select-Object -ExpandProperty 'Allow System Only Change' return [bool]$SystemOnlyChangeValue } } } <# .SYNOPSIS Utility function to return the selected Naming Context. #> function _GetNamingContext { [CmdletBinding()] param ( [ValidateSet( 'Default', 'Configuration', 'Schema' )] [ValidateNotNullOrEmpty()] [string] $NamingContext = 'Default', [ValidateNotNullOrEmpty()] [Alias('DnsDomain')] [string] $DomainName = $env:USERDNSDOMAIN, [pscredential] $Credential, [Parameter(ValueFromRemainingArguments, DontShow)] $UnboundArguments ) $PSBoundParameters.Remove( 'UnboundArguments' ) > $null $RootDSE = [ADSI]"LDAP://$DomainName/RootDSE" if ( $Credential ) { $RootDSE.PSBase.Username = $Credential.UserName $RootDSE.PSBase.Password = $Credential.GetNetworkCredential().Password } try { return $RootDSE.Get( $NamingContext + 'NamingContext' ) } catch { Write-Error ( 'Could not retrieve {0} for domain ''{1}'', user may not have rights to query the domain.' -f ( $NamingContext + 'NamingContext' ), $DomainName ) return } } <# .SYNOPSIS Utility function to return a Directory Searcher object. #> function _GetSearcher { [CmdletBinding()] [OutputType([System.DirectoryServices.DirectorySearcher])] param ( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string] $SearchBase, [ValidateNotNullOrEmpty()] [string] $SearchFilter = '(objectClass=*)', [Parameter()] [ValidateNotNullOrEmpty()] [Alias('DnsDomain')] [string] $DomainName = $env:USERDNSDOMAIN, [pscredential] $Credential, [Parameter(ValueFromRemainingArguments, DontShow)] $UnboundArguments ) $PSBoundParameters.Remove( 'UnboundArguments' ) > $null if ( $Credential ) { $ADSearchRoot = [DirectoryEntry]::new( "LDAP://$DomainName/$SearchBase", $Credential.UserName, $Credential.GetNetworkCredential().Password ) } else { $ADSearchRoot = [DirectoryEntry]::new( "LDAP://$DomainName/$SearchBase" ) } [DirectorySearcher]::new( $ADSearchRoot, $SearchFilter ) } <# .SYNOPSIS Utility function to generate DomainParams. #> function _GetDomainParams { param( [string] $DomainName, [pscredential] $Credential, [Parameter(ValueFromRemainingArguments, DontShow)] $UnboundArguments ) $PSBoundParameters.Remove( 'UnboundArguments' ) > $null return $PSBoundParameters } # SIG # Begin signature block # MIIesgYJKoZIhvcNAQcCoIIeozCCHp8CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQULjAetTupCHXggnw6vvcmfN5w # h2Ogghm9MIIEhDCCA2ygAwIBAgIQQhrylAmEGR9SCkvGJCanSzANBgkqhkiG9w0B # AQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNV # BAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRU # cnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTA1MDYwNzA4MDkxMFoXDTIwMDUzMDEw # NDgzOFowgZUxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2Fs # dCBMYWtlIENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEhMB8G # A1UECxMYaHR0cDovL3d3dy51c2VydHJ1c3QuY29tMR0wGwYDVQQDExRVVE4tVVNF # UkZpcnN0LU9iamVjdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6q # gT+jo2F4qjEAVZURnicPHxzfOpuCaDDASmEd8S8O+r5596Uj71VRloTN2+O5bj4x # 2AogZ8f02b+U60cEPgLOKqJdhwQJ9jCdGIqXsqoc/EHSoTbL+z2RuufZcDX65OeQ # w5ujm9M89RKZd7G3CeBo5hy485RjiGpq/gt2yb70IuRnuasaXnfBhQfdDWy/7gbH # d2pBnqcP1/vulBe3/IW+pKvEHDHd17bR5PDv3xaPslKT16HUiaEHLr/hARJCHhrh # 2JU022R5KP+6LhHC5ehbkkj7RwvCbNqtMoNB86XlQXD9ZZBt+vpRxPm9lisZBCzT # bafc8H9vg2XiaquHhnUCAwEAAaOB9DCB8TAfBgNVHSMEGDAWgBStvZh6NLQm9/rE # JlTvA73gJMtUGjAdBgNVHQ4EFgQU2u1kdBScFDyr3ZmpvVsoTYs8ydgwDgYDVR0P # AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0gBAowCDAGBgRVHSAAMEQG # A1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9BZGRUcnVz # dEV4dGVybmFsQ0FSb290LmNybDA1BggrBgEFBQcBAQQpMCcwJQYIKwYBBQUHMAGG # GWh0dHA6Ly9vY3NwLnVzZXJ0cnVzdC5jb20wDQYJKoZIhvcNAQEFBQADggEBAE1C # L6bBiusHgJBYRoz4GTlmKjxaLG3P1NmHVY15CxKIe0CP1cf4S41VFmOtt1fcOyu9 # 08FPHgOHS0Sb4+JARSbzJkkraoTxVHrUQtr802q7Zn7Knurpu9wHx8OSToM8gUmf # ktUyCepJLqERcZo20sVOaLbLDhslFq9s3l122B9ysZMmhhfbGN6vRenf+5ivFBjt # pF72iZRF8FUESt3/J90GSkD2tLzx5A+ZArv9XQ4uKMG+O18aP5cQhLwWPtijnGMd # ZstcX9o+8w8KCTUi29vAPwD55g1dZ9H9oB4DK9lA977Mh2ZUgKajuPUZYtXSJrGY # Ju6ay0SnRVqBlRUa9VEwggTmMIIDzqADAgECAhBiXE2QjNVC+6supXM/8VQZMA0G # CSqGSIb3DQEBBQUAMIGVMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNV # BAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdv # cmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTEdMBsGA1UEAxMU # VVROLVVTRVJGaXJzdC1PYmplY3QwHhcNMTEwNDI3MDAwMDAwWhcNMjAwNTMwMTA0 # ODM4WjB6MQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVy # MRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDEg # MB4GA1UEAxMXQ09NT0RPIFRpbWUgU3RhbXBpbmcgQ0EwggEiMA0GCSqGSIb3DQEB # AQUAA4IBDwAwggEKAoIBAQCqgvGEqVvYcbXSXSvt9BMgDPmb6dGPdF5u7uspSNjI # vizrCmFgzL2SjXzddLsKnmhOqnUkcyeuN/MagqVtuMgJRkx+oYPp4gNgpCEQJ0Ca # WeFtrz6CryFpWW1jzM6x9haaeYOXOh0Mr8l90U7Yw0ahpZiqYM5V1BIR8zsLbMaI # upUu76BGRTl8rOnjrehXl1/++8IJjf6OmqU/WUb8xy1dhIfwb1gmw/BC/FXeZb5n # OGOzEbGhJe2pm75I30x3wKoZC7b9So8seVWx/llaWm1VixxD9rFVcimJTUA/vn9J # AV08m1wI+8ridRUFk50IYv+6Dduq+LW/EDLKcuoIJs0ZAgMBAAGjggFKMIIBRjAf # BgNVHSMEGDAWgBTa7WR0FJwUPKvdmam9WyhNizzJ2DAdBgNVHQ4EFgQUZCKGtkqJ # yQQP0ARYkiuzbj0eJ2wwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8C # AQAwEwYDVR0lBAwwCgYIKwYBBQUHAwgwEQYDVR0gBAowCDAGBgRVHSAAMEIGA1Ud # HwQ7MDkwN6A1oDOGMWh0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZp # cnN0LU9iamVjdC5jcmwwdAYIKwYBBQUHAQEEaDBmMD0GCCsGAQUFBzAChjFodHRw # Oi8vY3J0LnVzZXJ0cnVzdC5jb20vVVROQWRkVHJ1c3RPYmplY3RfQ0EuY3J0MCUG # CCsGAQUFBzABhhlodHRwOi8vb2NzcC51c2VydHJ1c3QuY29tMA0GCSqGSIb3DQEB # BQUAA4IBAQARyT3hBeg7ZazJdDEDt9qDOMaSuv3N+Ntjm30ekKSYyNlYaDS18Ash # U55ZRv1jhd/+R6pw5D9eCJUoXxTx/SKucOS38bC2Vp+xZ7hog16oYNuYOfbcSV4T # p5BnS+Nu5+vwQ8fQL33/llqnA9abVKAj06XCoI75T9GyBiH+IV0njKCv2bBS7vzI # 7bec8ckmONalMu1Il5RePeA9NbSwyVivx1j/YnQWkmRB2sqo64sDvcFOrh+RMrjh # JDt77RRoCYaWKMk7yWwowiVp9UphreAn+FOndRWwUTGw8UH/PlomHmB+4uNqOZrE # 6u4/5rITP1UDBE0LkHLU6/u8h5BRsjgZMIIE/jCCA+agAwIBAgIQK3PbdGMRTFpb # MkryMFdySTANBgkqhkiG9w0BAQUFADB6MQswCQYDVQQGEwJHQjEbMBkGA1UECBMS # R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD # T01PRE8gQ0EgTGltaXRlZDEgMB4GA1UEAxMXQ09NT0RPIFRpbWUgU3RhbXBpbmcg # Q0EwHhcNMTkwNTAyMDAwMDAwWhcNMjAwNTMwMTA0ODM4WjCBgzELMAkGA1UEBhMC # R0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBwwHU2FsZm9y # ZDEYMBYGA1UECgwPU2VjdGlnbyBMaW1pdGVkMSswKQYDVQQDDCJTZWN0aWdvIFNI # QS0xIFRpbWUgU3RhbXBpbmcgU2lnbmVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A # MIIBCgKCAQEAv1I2gjrcdDcNeNV/FlAZZu26GpnRYziaDGayQNungFC/aS42Lwpn # P0ChSopjNZvQGcx0qhcZkSu1VSAZ+8AaOm3KOZuC8rqVoRrYNMe4iXtwiHBRZmns # d/7GlHJ6zyWB7TSCmt8IFTcxtG2uHL8Y1Q3P/rXhxPuxR3Hp+u5jkezx7M5ZBBF8 # rgtgU+oq874vAg/QTF0xEy8eaQ+Fm0WWwo0Si2euH69pqwaWgQDfkXyVHOaeGWTf # dshgRC9J449/YGpFORNEIaW6+5H6QUDtTQK0S3/f4uA9uKrzGthBg49/M+1BBuJ9 # nj9ThI0o2t12xr33jh44zcDLYCQD3npMqwIDAQABo4IBdDCCAXAwHwYDVR0jBBgw # FoAUZCKGtkqJyQQP0ARYkiuzbj0eJ2wwHQYDVR0OBBYEFK7u2WC6XvUsARL9jo2y # VXI1Rm/xMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQM # MAoGCCsGAQUFBwMIMEAGA1UdIAQ5MDcwNQYMKwYBBAGyMQECAQMIMCUwIwYIKwYB # BQUHAgEWF2h0dHBzOi8vc2VjdGlnby5jb20vQ1BTMEIGA1UdHwQ7MDkwN6A1oDOG # MWh0dHA6Ly9jcmwuc2VjdGlnby5jb20vQ09NT0RPVGltZVN0YW1waW5nQ0FfMi5j # cmwwcgYIKwYBBQUHAQEEZjBkMD0GCCsGAQUFBzAChjFodHRwOi8vY3J0LnNlY3Rp # Z28uY29tL0NPTU9ET1RpbWVTdGFtcGluZ0NBXzIuY3J0MCMGCCsGAQUFBzABhhdo # dHRwOi8vb2NzcC5zZWN0aWdvLmNvbTANBgkqhkiG9w0BAQUFAAOCAQEAen+pStKw # pBwdDZ0tXMauWt2PRR3wnlyQ9l6scP7T2c3kGaQKQ3VgaoOkw5mEIDG61v5MzxP4 # EPdUCX7q3NIuedcHTFS3tcmdsvDyHiQU0JzHyGeqC2K3tPEG5OfkIUsZMpk0uRlh # dwozkGdswIhKkvWhQwHzrqJvyZW9ljj3g/etfCgf8zjfjiHIcWhTLcuuquIwF4Mi # KRi14YyJ6274fji7kE+5Xwc0EmuX1eY7kb4AFyFu4m38UnnvgSW6zxPQ+90rzYG2 # V4lO8N3zC0o0yoX/CLmWX+sRE+DhxQOtVxzhXZIGvhvIPD+lIJ9p0GnBxcLJPufF # cvfqG5bilK+GLjCCBUwwggQ0oAMCAQICEQCV7K1bRdp1yZPPBYrFbG8VMA0GCSqG # SIb3DQEBCwUAMHwxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNo # ZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRl # ZDEkMCIGA1UEAxMbU2VjdGlnbyBSU0EgQ29kZSBTaWduaW5nIENBMB4XDTE5MTAx # NTAwMDAwMFoXDTIwMTAwNzIzNTk1OVowgZQxCzAJBgNVBAYTAlVTMQ4wDAYDVQQR # DAU2MDEyMDERMA8GA1UECAwISWxsaW5vaXMxDjAMBgNVBAcMBUVsZ2luMRowGAYD # VQQJDBExMjg3IEJsYWNraGF3ayBEcjEaMBgGA1UECgwRU2hhbm5vbiBHcmF5YnJv # b2sxGjAYBgNVBAMMEVNoYW5ub24gR3JheWJyb29rMIIBIjANBgkqhkiG9w0BAQEF # AAOCAQ8AMIIBCgKCAQEA1A3wiJRalXGleCYOLaKdlD5iZrswpu4ChSnCx8XvkWeL # R/XBQSvebJXpF99sdVwwUeouEk1i5EA2AIU88DoEw0+1XxC6DAUwYAVXmo3M+dkv # OwNXHrWwSRqNwmhABHVejGOInKsi1jYa3DPI2dFBL19Trg0ez0oXkMVwbKGDpwt9 # U7WbbjveLcAPnpvR65dk3Jhb9bmCMirCnALjaOOnFzlCUiagx9nDszzw7fYRAlf6 # EJNnicwwBujOmA59q9urwAuEA7/VXTAMpE2wmhVsM4xqscbzAPs7PSVgkOTrZR6a # 51r1HSCzrULISVZKxF0mD4/6qOElqM/X/nd7q7dmSQIDAQABo4IBrjCCAaowHwYD # VR0jBBgwFoAUDuE6qFM6MdWKvsG7rWcaA4WtNA4wHQYDVR0OBBYEFJHiTLW7XSJv # Xn/hpQzh7bxSIUZ2MA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMBMGA1Ud # JQQMMAoGCCsGAQUFBwMDMBEGCWCGSAGG+EIBAQQEAwIEEDBABgNVHSAEOTA3MDUG # DCsGAQQBsjEBAgEDAjAlMCMGCCsGAQUFBwIBFhdodHRwczovL3NlY3RpZ28uY29t # L0NQUzBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsLnNlY3RpZ28uY29tL1Nl # Y3RpZ29SU0FDb2RlU2lnbmluZ0NBLmNybDBzBggrBgEFBQcBAQRnMGUwPgYIKwYB # BQUHMAKGMmh0dHA6Ly9jcnQuc2VjdGlnby5jb20vU2VjdGlnb1JTQUNvZGVTaWdu # aW5nQ0EuY3J0MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0aWdvLmNvbTAm # BgNVHREEHzAdgRtzaGFubm9uLmdyYXlicm9va0BnbWFpbC5jb20wDQYJKoZIhvcN # AQELBQADggEBACNm23H5GuT8THomfaxBDdgN/4g4FgsClLsxhAyRyWxqnE4udxre # x1Dq3FQtdXoeXFPaaFYVH/zvmEFuh+oz65Ejomo2WPSOVKiF6NbLpxScHW2c1+yO # NHDqn/TGtx0+RrfUgOFgao/AzuRqxei90CotgUe73cpmG0JPdmV1+hnMAhojoO4g # bhfdb69y8fCaDzLoTmybz1JOfcinR12TLntNV+Def2CXaNoOV2VNKpauAiIh2BkK # 7LoabyBtMNQbMNCY33dyNq9V7tvVxdYOlPRoANB3SfATPtKQCrix7T85qrFoRHBC # SxTfYFHsyGQVno6lmMfQstJ6q+TQJz1gFcUwggX1MIID3aADAgECAhAdokgwb5sm # GNCC4JZ9M9NqMA0GCSqGSIb3DQEBDAUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UE # CBMKTmV3IEplcnNleTEUMBIGA1UEBxMLSmVyc2V5IENpdHkxHjAcBgNVBAoTFVRo # ZSBVU0VSVFJVU1QgTmV0d29yazEuMCwGA1UEAxMlVVNFUlRydXN0IFJTQSBDZXJ0 # aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xODExMDIwMDAwMDBaFw0zMDEyMzEyMzU5 # NTlaMHwxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIx # EDAOBgNVBAcTB1NhbGZvcmQxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDEkMCIG # A1UEAxMbU2VjdGlnbyBSU0EgQ29kZSBTaWduaW5nIENBMIIBIjANBgkqhkiG9w0B # AQEFAAOCAQ8AMIIBCgKCAQEAhiKNMoV6GJ9J8JYvYwgeLdx8nxTP4ya2JWYpQIZU # RnQxYsUQ7bKHJ6aZy5UwwFb1pHXGqQ5QYqVRkRBq4Etirv3w+Bisp//uLjMg+gwZ # iahse60Aw2Gh3GllbR9uJ5bXl1GGpvQn5Xxqi5UeW2DVftcWkpwAL2j3l+1qcr44 # O2Pej79uTEFdEiAIWeg5zY/S1s8GtFcFtk6hPldrH5i8xGLWGwuNx2YbSp+dgcRy # QLXiX+8LRf+jzhemLVWwt7C8VGqdvI1WU8bwunlQSSz3A7n+L2U18iLqLAevRtn5 # RhzcjHxxKPP+p8YU3VWRbooRDd8GJJV9D6ehfDrahjVh0wIDAQABo4IBZDCCAWAw # HwYDVR0jBBgwFoAUU3m/WqorSs9UgOHYm8Cd8rIDZsswHQYDVR0OBBYEFA7hOqhT # OjHVir7Bu61nGgOFrTQOMA4GA1UdDwEB/wQEAwIBhjASBgNVHRMBAf8ECDAGAQH/ # AgEAMB0GA1UdJQQWMBQGCCsGAQUFBwMDBggrBgEFBQcDCDARBgNVHSAECjAIMAYG # BFUdIAAwUAYDVR0fBEkwRzBFoEOgQYY/aHR0cDovL2NybC51c2VydHJ1c3QuY29t # L1VTRVJUcnVzdFJTQUNlcnRpZmljYXRpb25BdXRob3JpdHkuY3JsMHYGCCsGAQUF # BwEBBGowaDA/BggrBgEFBQcwAoYzaHR0cDovL2NydC51c2VydHJ1c3QuY29tL1VT # RVJUcnVzdFJTQUFkZFRydXN0Q0EuY3J0MCUGCCsGAQUFBzABhhlodHRwOi8vb2Nz # cC51c2VydHJ1c3QuY29tMA0GCSqGSIb3DQEBDAUAA4ICAQBNY1DtRzRKYaTb3moq # jJvxAAAeHWJ7Otcywvaz4GOz+2EAiJobbRAHBE++uOqJeCLrD0bs80ZeQEaJEvQL # d1qcKkE6/Nb06+f3FZUzw6GDKLfeL+SU94Uzgy1KQEi/msJPSrGPJPSzgTfTt2Sw # piNqWWhSQl//BOvhdGV5CPWpk95rcUCZlrp48bnI4sMIFrGrY1rIFYBtdF5KdX6l # uMNstc/fSnmHXMdATWM19jDTz7UKDgsEf6BLrrujpdCEAJM+U100pQA1aWy+nyAl # EA0Z+1CQYb45j3qOTfafDh7+B1ESZoMmGUiVzkrJwX/zOgWb+W/fiH/AI57SHkN6 # RTHBnE2p8FmyWRnoao0pBAJ3fEtLzXC+OrJVWng+vLtvAxAldxU0ivk2zEOS5LpP # 8WKTKCVXKftRGcehJUBqhFfGsp2xvBwK2nxnfn0u6ShMGH7EezFBcZpLKewLPVdQ # 0srd/Z4FUeVEeN0B3rF1mA1UJP3wTuPi+IO9crrLPTru8F4XkmhtyGH5pvEqCgul # ufSe7pgyBYWe6/mDKdPGLH29OncuizdCoGqC7TtKqpQQpOEN+BfFtlp5MxiS47V1 # +KHpjgolHuQe8Z9ahyP/n6RRnvs5gBHN27XEp6iAb+VT1ODjosLSWxr6MiYtaldw # HDykWC6j81tLB9wyWfOHpxptWDGCBF8wggRbAgEBMIGRMHwxCzAJBgNVBAYTAkdC # MRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQx # GDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDEkMCIGA1UEAxMbU2VjdGlnbyBSU0Eg # Q29kZSBTaWduaW5nIENBAhEAleytW0XadcmTzwWKxWxvFTAJBgUrDgMCGgUAoHgw # GAYKKwYBBAGCNwIBDDEKMAigAoAAoQKAADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGC # NwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAjBgkqhkiG9w0BCQQx # FgQUAI3kJv9z+UBHmFW+vPWReYXMq80wDQYJKoZIhvcNAQEBBQAEggEAG66otNyf # evrCS3yeP1Csyov9Gkowuj53uiLJwZm7MV/xo3LcAa1wzH5enmIXrqr6jadnzgOV # CinZSoKLeJLJAO9QVZ6IXZZpFvI22ttTy6piZGdgpQeZ0bR3NsLjBwjlrwOMhfmd # NEN0NwnioloNWG46SEHWrgyHglaJzLaSglW0aa9y1u/wegyBAXAKP62m+nZA9reZ # TQGlEJ3HTjCeC6v738JicuZv38L+6VTKIxcVQerxMQzl2IWJXNr9rOQ8RfcI81Iy # dPL+go1hbYoYI2cJGy0/t6Cyuo44wuDRR5yhn/uawdI3bs2G9AesHYf77Rim0Jq5 # t4NElJ54zfGInaGCAigwggIkBgkqhkiG9w0BCQYxggIVMIICEQIBATCBjjB6MQsw # CQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQH # EwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDEgMB4GA1UEAxMX # Q09NT0RPIFRpbWUgU3RhbXBpbmcgQ0ECECtz23RjEUxaWzJK8jBXckkwCQYFKw4D # AhoFAKBdMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8X # DTIwMDQxNjIwMjMxMlowIwYJKoZIhvcNAQkEMRYEFB0cL1srgH7yss2QFt+8mfEl # ymp0MA0GCSqGSIb3DQEBAQUABIIBAESJcXsEaPMUmxxIOtJuiFAR+nQzunyZPZ+b # cGTCRRw5Ve9Hoa1HmtrlkSoCEXW3I7Xb+sCl2gtzIoGZmajP1LssNGmRk8pr/jEu # o15n7PmrDKddHG7cV0KUz8F4nToC3zhD2owHwtvGBaC20Jmw6vvAv+2Qr5BY2mTt # evVB2PPnmhSoLh8DwWwVbVEXmnSOLv1kScpzufdJslNMheUJ7/YyJKF0TwU3gHin # 6K1KKNfhV/h6fc8TfBUe9cyCZHEyN19xicKRfsh/y1N0sN78FBzG6ak3aMXi8NKZ # gaUU4phRqO+8ZAOatrY834o5FxvhaQ8ionHVsuvBTK4FAQTTlBM= # SIG # End signature block |