SpfAnalyzer.psm1
#region Enums enum SpfAction { Pass Fail SoftFail Neutral } #endregion Enums #region Classes class Dns { [string]$Name Dns([string]$name) { $this.Name = $name } static [object[]] GetRecord([string]$Name, [Microsoft.DnsClient.Commands.RecordType]$recordType) { $retVal = @() switch($recordType) { {$_ -in ([Microsoft.DnsClient.Commands.RecordType]::A,[Microsoft.DnsClient.Commands.RecordType]::A_AAAA, [Microsoft.DnsClient.Commands.RecordType]::AAAA)} { $data = Resolve-DnsName -Name $Name -Type $_ | select-object -ExpandProperty IPAddress $data | where-object{$_ -ne $null} | foreach-object { try { $retVal += [SpfIpAddress]::Parse($recordName, $_) } catch { Write-Warning "Failed to parse $_ as IP address" } } break; } {$_ -eq [Microsoft.DnsClient.Commands.RecordType]::MX} { $data = Resolve-DnsName -Name $Name -Type MX | select-object -ExpandProperty NameExchange $data | where-object{$_ -ne $null} | foreach-object { $retVal += $_ } break; } {$_ -eq [Microsoft.DnsClient.Commands.RecordType]::TXT} { $data = Resolve-DnsName -Name $Name -Type TXT | select-object -ExpandProperty Strings $data | where-object{$_ -ne $null} | foreach-object { $retVal += $_ } break; } default { throw "Unsupported record type $recordType" } } if($retVal.Count -eq 0) {return $null} else {return $retVal} } static [object[]] GetSpfRecord([string]$Name) { $retVal = @() $data = Resolve-DnsName -Name $Name -Type TXT | select-object -ExpandProperty Strings $data | where-object{$_ -ne $null} | foreach-object { if($_ -match "^v=spf1") { $retVal += $_ } } if($retVal.Count -eq 0) {return $null} else {return $retVal} } } class SpfEntry { [string]$Prefix [string]$Value SpfEntry([string]$prefix, [string]$value) { $this.Prefix = $prefix $this.Value = $value } [string] ToString() { return "$($this.Prefix) $($this.Value)" } } class SpfIpAddress { [string]$Source [System.Net.IPAddress]$Address SpfIpAddress([string]$source, [System.Net.IPAddress]$address) { $this.Source = $source $this.Address = $address } [string] ToString() { return $this.Address.ToString() } [System.Net.IPNetwork] ToNetwork([int]$prefixLength) { return [SpfIpNetwork]::new($this.source, [IpHelper.IPAddressExtensions]::Mask($this.address,$prefixLength,$true)) } static [SpfIpAddress] Parse([string]$source, [string]$address) { $ip = [System.Net.IPAddress]::Parse($address) return [SpfIpAddress]::new($source, $ip) } } class SpfIpNetwork { hidden [System.Net.IPNetwork] $network [string]$Source [System.Net.IPAddress]$BaseAddress [int]$PrefixLength static [hashtable[]] $MemberDefinitions = @( @{ MemberType = 'ScriptProperty' MemberName = 'BaseAddress' Value = { $this.network.BaseAddress } } @{ MemberType = 'ScriptProperty' MemberName = 'PrefixLength' Value = { $this.network.PrefixLength } } ) static SpfIpNetwork() { $TypeName = [SpfIpNetwork].Name foreach ($Definition in [SpfIpNetwork]::MemberDefinitions) { Update-TypeData -TypeName $TypeName -Force @Definition } } SpfIpNetwork() {} SpfIpNetwork([string]$source, [System.Net.IPNetwork]$network) { $this.Source = $source $this.network = $network } SpfIpNetwork([string]$source, [System.Net.IPAddress]$address, [int]$prefixLength) { $this.Source = $source #need compiled helper here to overcome powershell language limitations $this.network = [IpHelper.IPAddressExtensions]::Mask($address,$prefixLength,$true) } [bool] Contains([System.Net.IPAddress]$address) { return $this.network.Contains($address) } static [SpfIpNetwork] Parse([string]$source, [string]$address) { $parts = $address.Split('/') $ip = [System.Net.IPAddress]::Parse($parts[0]) $mask = [int]$parts[1] return [SpfIpNetwork]::new($source, $ip, $mask) } [string] ToString() { return "$($this.BaseAddress)/$($this.PrefixLength)" } } class SpfRecord { hidden [string] $rawRecord [string] $Version [SpfAction] $FinalAction [string] $Source [object[]] $Entries SpfRecord([string]$source, [string]$rawRecord) { $this.rawRecord = $rawRecord $this.Version = 'spf1' $this.FinalAction = [SpfAction]::Neutral $this.Source = $source $this.Entries = @() } [string] ToString() { return "Source: $($this.Source) Record: $($this.rawRecord)" } static [SpfRecord[]] Parse([string]$source, [string]$rawRecord) { $retVal = @() $record = [SpfRecord]::new($source, $rawRecord) $retVal += $record $parts = $rawRecord.Split(' ') $continueParsing = $true foreach($part in $parts) { if($part.StartsWith('v=')) { $record.Version = $part.Substring(2) } #methods elseif ($continueParsing -and ($part.StartsWith('ip4:') -or $part.StartsWith('ip6:'))) { $ip = $part.Substring(4) if($ip -match '/') { $record.Entries += [SpfIpNetwork]::Parse($source, $ip) } else { $record.Entries += [SpfIpAddress]::Parse($source, $ip) } } elseif($continueParsing -and $part.StartsWith('include:')) { $domainName = $part.Substring(8) $record.Entries += [SpfEntry]::new('include', $domainName) $additionalRecords = [Dns]::GetSpfRecord($domainName) foreach($additionalRecord in $additionalRecords) { $retVal += [SpfRecord]::Parse($domainName, $additionalRecord) } } elseif($continueParsing -and $part.StartsWith('exists:') -or $part.StartsWith('ptr:') -or $part -eq 'ptr') { $splits = $part.Split(':') if($splits.Length -gt 1) { $record.Entries += [SpfEntry]::new($splits[0], $splits[1]) } else { $record.Entries += [SpfEntry]::new($part, $null) } } elseif($continueParsing -and ($part.StartsWith('a:') -or $part.StartsWith('a/') -or $part -eq 'a' -or $part.StartsWith('+a:') -or $part.StartsWith('+a/') -or $part -eq '+a')) { $mask = -1 $splits = $part.Split('/') if($splits.Length -gt 1) { if(-not [int]::TryParse($splits[1], [ref]$mask)) { Write-Warning "Invalid mask value in $part" } } $splits = $splits[0].Split(':') $domainName = $source if($splits.Length -gt 1) { $domainName = $splits[1] } $start = 1 if($part[0] -eq '+') { $start++ } $record.Entries += [SpfEntry]::new('a', $part.Substring($start).Replace(':','')) if($mask -eq -1) { [SpfRecord]::ParseAMechanism($domainName, $part, [ref]$record) } else { [SpfRecord]::ParseAWithMaskMechanism($domainName, $mask, $part, [ref]$record) } } elseif($continueParsing -and ($part.StartsWith('mx') -or $part.startsWith('+mx'))) { $mask = -1 $splits = $part.Split('/') if($splits.Length -gt 1) { if(-not [int]::TryParse($splits[1], [ref]$mask)) { Write-Warning "Invalid mask value in $part" } } $splits = $splits[0].Split(':') $domainName = $source if($splits.Length -gt 1) { $domainName = $splits[1] } $start = 2 if($part[0] -eq '+') { $start++ } $record.Entries += [SpfEntry]::new('mx', $part.Substring($start).Replace(':','')) $mx = [Dns]::GetRecord($domainName, [Microsoft.DnsClient.Commands.RecordType]::MX) foreach($rec in $mx) { if($null -eq $rec) {continue} $domainName = $rec -as [string] if($null -eq $domainName) {continue} if($mask -eq -1) { [SpfRecord]::ParseAMechanism($domainName, $part, [ref]$record) } else { [SpfRecord]::ParseAWithMaskMechanism($domainName, $mask, $part, [ref]$record) } } } elseif($part -eq 'all' -or $part -eq '+all') { $record.FinalAction = [SpfAction]::Pass $continueParsing = $false } elseif($part -eq '-all') { $record.FinalAction = [SpfAction]::Fail $continueParsing = $false } elseif($part -eq '~all') { $record.FinalAction = [SpfAction]::SoftFail $continueParsing = $false } elseif($part -eq '?all') { $record.FinalAction = [SpfAction]::Neutral $continueParsing = $false } #Modifiers elseif($part.StartsWith('redirect=')) { $domainName = $part.Substring(9) $record.Entries += [SpfEntry]::new('redirect', $domainName) $additionalRecords = [Dns]::GetSpfRecord($domainName) $retVal+=$additionalRecords } elseif($part.StartsWith('exp=')) { $domainName = $part.Substring(4) $record.Entries += [SpfEntry]::new('exp', $domainName) } } return $retVal } static [void] ParseAMechanism([string]$domain, [string]$rawEntry, [ref]$record) { $records = [Dns]::GetRecord($domain, [Microsoft.DnsClient.Commands.RecordType]::A_AAAA) foreach($rec in $records) { if($null -eq $rec) {continue} $ip = $rec -as [System.Net.IPAddress] if($null -eq $ip) {continue} $record.Entries += [SpfIpAddress]::new("$domain $rawEntry", $ip) } } static [void] ParseAWithMaskMechanism([string]$domain, [int]$mask, [string]$rawEntry, [ref]$record) { $records = [Dns]::GetRecord($domain, [Microsoft.DnsClient.Commands.RecordType]::A_AAAA) foreach($rec in $records) { if($null -eq $rec) {continue} $ip = $rec -as [System.Net.IPAddress] if($null -eq $ip) {continue} $record.Entries += [SpfIpNetwork]::new("$domain $rawEntry", $ip, $mask) } } } #endregion Classes #region Public commands function Get-SPFRecord { [CmdletBinding()] param ( [Parameter(Mandatory, ValueFromPipeline)] [string]$Domain ) process { $spfRecords = [Dns]::GetSpfRecord($domain) foreach($spfRecord in $spfRecords) { [SpfRecord]::Parse($domain, $spfRecord) } } } function Get-SpfRecordEntries { [CmdletBinding()] param ( [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'Record')] [SpfRecord]$SpfRecord, [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'DomainName')] [string]$Domain, [switch]$IncludeIpAddresses, [switch]$IncludeIpNetworks ) process { if ($PSCmdlet.ParameterSetName -eq 'DomainName') { Write-Verbose "Processing $Domain" [SpfRecord[]]$record = Get-SpfRecord -Domain $Domain ` } else { $record = $SpfRecord } Write-Verbose "Processing $record" $record.Entries | Where-Object{$_ -is [SpfEntry]} if($IncludeIpAddresses) { $record.Entries | Where-Object{$_ -is [SpfIpAddress]} } if($IncludeIpNetworks) { $record.Entries | Where-Object{$_ -is [SpfIpNetwork]} } } } function Get-SpfRecordIpAddress { [CmdletBinding()] param ( [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'Record')] [SpfRecord]$SpfRecord, [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'DomainName')] [string]$Domain ) process { if ($PSCmdlet.ParameterSetName -eq 'DomainName') { Write-Verbose "Processing $Domain" [SpfRecord[]]$record = Get-SpfRecord -Domain $Domain } else { $record = $SpfRecord } Write-Verbose "Processing $record" $record.Entries | Where-Object { $_ -is [SpfIpAddress] } } } function Get-SpfRecordIpNetwork { [CmdletBinding()] param ( [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'Record')] [SpfRecord]$SpfRecord, [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'DomainName')] [string]$Domain ) process { if ($PSCmdlet.ParameterSetName -eq 'DomainName') { Write-Verbose "Processing $Domain" [SpfRecord[]]$record = Get-SpfRecord -Domain $Domain } else { $record = $SpfRecord } Write-Verbose "Processing $record" $record.Entries | Where-Object { $_ -is [SpfIpNetwork] } } } function Test-SpfHost { [CmdletBinding()] param ( [Parameter(Mandatory)] [string]$Domain, [Parameter(Mandatory)] [string]$Address, [Parameter()] [string]$SenderAddress ) process { $ip = [System.Net.IPAddress]::Parse($Address) $spfRecords = Get-SPFRecord -Domain $Domain foreach($record in $spfRecords) { $record ` | Get-SpfRecordIpAddress ` | Where-Object { $_.Address -eq $ip } $record ` | Get-SpfRecordIpNetwork ` | Where-Object { $_.Contains($ip) } $record.Entries ` | Where-Object { $_.Prefix -eq 'exists' } ` | ForEach-Object { $macro = Expand-SpfMacro -Macro $_.Value -Domain $Domain -IpAddress $ip -SenderAddress $SenderAddress if($macro -match '%{.' ) { throw "Unsupported macro $macro after expansion of $( $_.Value )" } try { [Dns]::GetRecord($macro, [Microsoft.DnsClient.Commands.RecordType]::A) } catch { #silently ignore not found expanded macro } } } } } function Test-SpfRecord { param ( [Parameter(Mandatory, ValueFromPipeline)] [string]$RawRecord, [Parameter(Mandatory)] [string]$Domain ) process { [SpfRecord]::Parse($Domain, $RawRecord) } } #endregion Public commands #region Internal commands function Expand-SpfMacro { param ( [Parameter(Mandatory = $true)] [string]$Macro, [Parameter(Mandatory)] [string]$Domain, [Parameter(Mandatory)] [System.Net.IPAddress]$IpAddress, [Parameter()] [string]$SenderAddress ) process { $senderValid = [string]::IsNullOrEmpty($SenderAddress) -eq $false if($senderValid) { $senderParts = $SenderAddress.Split('@') $senderValid = $senderParts.Count -eq 2 } if($macro -match '%{i}') { $dottedIp = [IpHelper.IPAddressExtensions]::ToDotted($IpAddress) $macro = $macro -replace '%{i}', $dottedIp } if($macro -match '%{ir}') { $dottedIp = [IpHelper.IPAddressExtensions]::ToReverseDotted($IpAddress) $macro = $macro -replace '%{ir}', $dottedIp } if($macro -match '%{c}') { $macro = $macro -replace '%{c}', $IpAddress.ToString() } if($macro -match '%{d}') { $macro = $macro -replace '%{d}', $Domain } if($macro -match '%{h}') { #we assume here that domain is a HELO domain $macro = $macro -replace '%{h}', $Domain } if($macro -match '%{s}' -and $senderValid) { $macro = $macro -replace '%{s}', $SenderAddress } if($macro -match '%{l}' -and $senderValid) { $macro = $macro -replace '%{l}', $senderParts[0] } if($macro -match '%{o}' -and $senderValid) { $macro = $macro -replace '%{o}', $senderParts[1] } if($macro -match '%{v}') { if($IpAddress.AddressFamily -eq 'InterNetwork') { $macro = $macro -replace '%{v}', 'in-addr' } else { $macro = $macro -replace '%{v}', 'ipv6' } } return $macro } } #endregion Internal commands # SIG # Begin signature block # MIIt9wYJKoZIhvcNAQcCoIIt6DCCLeQCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDrApwvvz7i3GCT # 5stMrk7QmdPGltNaJ6vBoGOXTbgk56CCE2AwggWQMIIDeKADAgECAhAFmxtXno4h # MuI5B72nd3VcMA0GCSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK # EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNV # BAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0xMzA4MDExMjAwMDBaFw0z # ODAxMTUxMjAwMDBaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ # bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0 # IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB # AL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3EMB/z # G6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKyunWZ # anMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsFxl7s # Wxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU15zHL # 2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJBMtfb # BHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObURWBf3 # JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6nj3c # AORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxBYKqx # YxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5SUUd0 # viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+xq4aL # T8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjQjBAMA8GA1Ud # EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTs1+OC0nFdZEzf # Lmc/57qYrhwPTzANBgkqhkiG9w0BAQwFAAOCAgEAu2HZfalsvhfEkRvDoaIAjeNk # aA9Wz3eucPn9mkqZucl4XAwMX+TmFClWCzZJXURj4K2clhhmGyMNPXnpbWvWVPjS # PMFDQK4dUPVS/JA7u5iZaWvHwaeoaKQn3J35J64whbn2Z006Po9ZOSJTROvIXQPK # 7VB6fWIhCoDIc2bRoAVgX+iltKevqPdtNZx8WorWojiZ83iL9E3SIAveBO6Mm0eB # cg3AFDLvMFkuruBx8lbkapdvklBtlo1oepqyNhR6BvIkuQkRUNcIsbiJeoQjYUIp # 5aPNoiBB19GcZNnqJqGLFNdMGbJQQXE9P01wI4YMStyB0swylIQNCAmXHE/A7msg # dDDS4Dk0EIUhFQEI6FUy3nFJ2SgXUE3mvk3RdazQyvtBuEOlqtPDBURPLDab4vri # RbgjU2wGb2dVf0a1TD9uKFp5JtKkqGKX0h7i7UqLvBv9R0oN32dmfrJbQdA75PQ7 # 9ARj6e/CVABRoIoqyc54zNXqhwQYs86vSYiv85KZtrPmYQ/ShQDnUBrkG5WdGaG5 # nLGbsQAe79APT0JsyQq87kP6OnGlyE0mpTX9iV28hWIdMtKgK1TtmlfB2/oQzxm3 # i0objwG2J5VT6LaJbVu8aNQj6ItRolb58KaAoNYes7wPD1N1KarqE3fk3oyBIa0H # EEcRrYc9B9F1vM/zZn4wggawMIIEmKADAgECAhAIrUCyYNKcTJ9ezam9k67ZMA0G # CSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ # bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0 # IFRydXN0ZWQgUm9vdCBHNDAeFw0yMTA0MjkwMDAwMDBaFw0zNjA0MjgyMzU5NTla # MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UE # AxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNBNDA5NiBTSEEz # ODQgMjAyMSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDVtC9C # 0CiteLdd1TlZG7GIQvUzjOs9gZdwxbvEhSYwn6SOaNhc9es0JAfhS0/TeEP0F9ce # 2vnS1WcaUk8OoVf8iJnBkcyBAz5NcCRks43iCH00fUyAVxJrQ5qZ8sU7H/Lvy0da # E6ZMswEgJfMQ04uy+wjwiuCdCcBlp/qYgEk1hz1RGeiQIXhFLqGfLOEYwhrMxe6T # SXBCMo/7xuoc82VokaJNTIIRSFJo3hC9FFdd6BgTZcV/sk+FLEikVoQ11vkunKoA # FdE3/hoGlMJ8yOobMubKwvSnowMOdKWvObarYBLj6Na59zHh3K3kGKDYwSNHR7Oh # D26jq22YBoMbt2pnLdK9RBqSEIGPsDsJ18ebMlrC/2pgVItJwZPt4bRc4G/rJvmM # 1bL5OBDm6s6R9b7T+2+TYTRcvJNFKIM2KmYoX7BzzosmJQayg9Rc9hUZTO1i4F4z # 8ujo7AqnsAMrkbI2eb73rQgedaZlzLvjSFDzd5Ea/ttQokbIYViY9XwCFjyDKK05 # huzUtw1T0PhH5nUwjewwk3YUpltLXXRhTT8SkXbev1jLchApQfDVxW0mdmgRQRNY # mtwmKwH0iU1Z23jPgUo+QEdfyYFQc4UQIyFZYIpkVMHMIRroOBl8ZhzNeDhFMJlP # /2NPTLuqDQhTQXxYPUez+rbsjDIJAsxsPAxWEQIDAQABo4IBWTCCAVUwEgYDVR0T # AQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUaDfg67Y7+F8Rhvv+YXsIiGX0TkIwHwYD # VR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMG # A1UdJQQMMAoGCCsGAQUFBwMDMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYY # aHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2Fj # ZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNV # HR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRU # cnVzdGVkUm9vdEc0LmNybDAcBgNVHSAEFTATMAcGBWeBDAEDMAgGBmeBDAEEATAN # BgkqhkiG9w0BAQwFAAOCAgEAOiNEPY0Idu6PvDqZ01bgAhql+Eg08yy25nRm95Ry # sQDKr2wwJxMSnpBEn0v9nqN8JtU3vDpdSG2V1T9J9Ce7FoFFUP2cvbaF4HZ+N3HL # IvdaqpDP9ZNq4+sg0dVQeYiaiorBtr2hSBh+3NiAGhEZGM1hmYFW9snjdufE5Btf # Q/g+lP92OT2e1JnPSt0o618moZVYSNUa/tcnP/2Q0XaG3RywYFzzDaju4ImhvTnh # OE7abrs2nfvlIVNaw8rpavGiPttDuDPITzgUkpn13c5UbdldAhQfQDN8A+KVssIh # dXNSy0bYxDQcoqVLjc1vdjcshT8azibpGL6QB7BDf5WIIIJw8MzK7/0pNVwfiThV # 9zeKiwmhywvpMRr/LhlcOXHhvpynCgbWJme3kuZOX956rEnPLqR0kq3bPKSchh/j # wVYbKyP/j7XqiHtwa+aguv06P0WmxOgWkVKLQcBIhEuWTatEQOON8BUozu3xGFYH # Ki8QxAwIZDwzj64ojDzLj4gLDb879M4ee47vtevLt/B3E+bnKD+sEq6lLyJsQfmC # XBVmzGwOysWGw/YmMwwHS6DTBwJqakAwSEs0qFEgu60bhQjiWQ1tygVQK+pKHJ6l # /aCnHwZ05/LWUpD9r4VIIflXO7ScA+2GRfS0YW6/aOImYIbqyK+p/pQd52MbOoZW # eE4wggcUMIIE/KADAgECAhAP9xCe9qf4ax3LBs7uih/sMA0GCSqGSIb3DQEBCwUA # MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UE # AxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNBNDA5NiBTSEEz # ODQgMjAyMSBDQTEwHhcNMjMxMTA4MDAwMDAwWhcNMjYxMDAxMjM1OTU5WjCBnDET # MBEGCysGAQQBgjc8AgEDEwJDWjEdMBsGA1UEDwwUUHJpdmF0ZSBPcmdhbml6YXRp # b24xETAPBgNVBAUTCDA0OTIzNjkzMQswCQYDVQQGEwJDWjEOMAwGA1UEBxMFUHJh # aGExGjAYBgNVBAoTEUdyZXlDb3JiZWwgcy5yLm8uMRowGAYDVQQDExFHcmV5Q29y # YmVsIHMuci5vLjCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAJ8t/Qga # dJKtGC7EqH4pmIU73fInH+j1scmVnrJtXL8tGlKzWZ7qlWDWOJBR3owF9CVqL4IX # BGImH8Miowj6RKKqhEe9UtxiH5ipV6msnzAjTFkwqR9vjfEm9vrU1JuXWvAWAfYx # qYg92oyCEBDQxpURpZmqAVSBy9U/ScDwE4NykZGzb0oYSPtzStd8RJvtUkc4126w # YKMbVe/kdY1mDbKO9DLfpbSIj3vghrH6XeHwEb7/jAVYI7Vl+jUyyqfmYHD7FldQ # X2fZfwvoGSibY1uWvvP0/vm0yd6uDbDjCDOTQW8Lxl5wvlXEf5ewn2oaPSoa6ov3 # 1XmnxL5iT8c1LM06JFCwfHS9e0NSyNr86IiKaxQO9/MANrYciTicObtD3cBcSRDO # pEUfhc4TvA5DQZaakSduVJWPdMhxQs9iWeYMOzh5NDTB3xAx8eLBn7Uj++hjI3FQ # WGEPw4Ew6WoDsJShU0HemlDJGTPW9EZSWHGdNFr1BxXEPb4F7DbjJZn33QIDAQAB # o4ICAjCCAf4wHwYDVR0jBBgwFoAUaDfg67Y7+F8Rhvv+YXsIiGX0TkIwHQYDVR0O # BBYEFP2yViJvcgO05qXIH6aJSXB/QcEhMD0GA1UdIAQ2MDQwMgYFZ4EMAQMwKTAn # BggrBgEFBQcCARYbaHR0cDovL3d3dy5kaWdpY2VydC5jb20vQ1BTMA4GA1UdDwEB # /wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzCBtQYDVR0fBIGtMIGqMFOgUaBP # hk1odHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRDb2Rl # U2lnbmluZ1JTQTQwOTZTSEEzODQyMDIxQ0ExLmNybDBToFGgT4ZNaHR0cDovL2Ny # bDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0Q29kZVNpZ25pbmdSU0E0 # MDk2U0hBMzg0MjAyMUNBMS5jcmwwgZQGCCsGAQUFBwEBBIGHMIGEMCQGCCsGAQUF # BzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wXAYIKwYBBQUHMAKGUGh0dHA6 # Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNENvZGVTaWdu # aW5nUlNBNDA5NlNIQTM4NDIwMjFDQTEuY3J0MAkGA1UdEwQCMAAwDQYJKoZIhvcN # AQELBQADggIBADCe9Fh40HN9RneCehz5MrBy4O9WYsYCMJ7qJ9DsBT+Hed98UOKB # k/XjgSLfsj5eZRHRmz3HzhGDK1PaRI+yIUVQx96a4qL7adktmrHex3fW39Iq+tPB # rHtiEIp9rwunATeZpk+876u0AXYD1VDRWCtkL8zwZU0oqL6U/mWEIXzkryCB5N3x # xtE54jMmW7MKi1+To4yQcrK3zQ394e2dr50L+aF2fgJ5mo1/YJvzyLLhigbqpoYG # U/gjZonhNJXUaYogpHSTgUaBRlIKZ5xCnrFfJlOsbkhex4QAcdkU6XC+XyYfEQka # 7ERwgxmEoRT3NlZ8/EbrQxJP4S1H8Z29M4D3L6rXNXXmv0IbfA9FQcqEco3Y3tRW # dgdcFEwJmYTo0mCZrYTJHgkKW8xDvQ5BJISAp/ydOX5tSa71ojx1/Kp7qizqjBN/ # W77jdqJ89N1y+N/SOiHOCH9NO5pDLsHpTWW/arvjZT0I8dVYkqK0V39rh95XELI+ # NwBZvV4AsKLirjrkZU3pwCz6O99VmPkBqp9TA5wl13NdTpDHuQ6QyVT7hbC8LF5p # z6x/xO/+tEGxG+1A31UTJPmkxhhUlR+NE3ZXiXhcG72CFHYUUvqwlThPkFYe4Ygf # j9ADmss08k0JhVU5rkbrC2h+549HPlFu/XOSIrps4SXzInjHPEYuBETzMYIZ7TCC # GekCAQEwfTBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4x # QTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgQ29kZSBTaWduaW5nIFJTQTQw # OTYgU0hBMzg0IDIwMjEgQ0ExAhAP9xCe9qf4ax3LBs7uih/sMA0GCWCGSAFlAwQC # AQUAoIGEMBgGCisGAQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJKoZIhvcNAQkDMQwG # CisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZI # hvcNAQkEMSIEIJkvynMfWYUrVmhISwJDmGICqrM2TQw8IAjMfG3jx0VeMA0GCSqG # SIb3DQEBAQUABIIBgHCHOVUmkyS5gLEDYw28TpDYesmPKlu1VFSZdPMlIUHpPgJT # toJygmJ6fBk7+fA7zqavC1CzyGOJ13rXJWlGBZ9VIGbWnzRFD9xmk1BuuUATIe3O # EobclQSXgkXZ5RghkbCYCOO2u7VW8DWl11kqWEcazG367hW4/nf9/at0f/EfkbGb # PD+1/0rIUJeRl2HqDcyoSJ8B++CQk+jDWs8BiwsbAVZxPsuk12C/U4UQPNuCLu2N # DkcfehV5YHUvPMsHd5BC1qaYIUAT+S6tYO/TNlbBi3J6rA0HPZcqR7/6FqdCy4bD # zYRc64Invpi8M2c8EIY72HP+AWaQMeweg4NupsVwkO9VMqwaOqjsup36jNCUYmLi # qXke2WIyiXU9Ecfm6g6BQz9Vrjz+3RQA/jkojUmiElIt/TWIE3CBwnPMi+soLuKV # Xv+9PtwhdnGEcW0Xx3OoObWi1tMiFVDNGVF1GKA2govH6uuR63BFOsDlsFyRiYyj # MJnne11XDvrBZcNeY6GCFzowghc2BgorBgEEAYI3AwMBMYIXJjCCFyIGCSqGSIb3 # DQEHAqCCFxMwghcPAgEDMQ8wDQYJYIZIAWUDBAIBBQAweAYLKoZIhvcNAQkQAQSg # aQRnMGUCAQEGCWCGSAGG/WwHATAxMA0GCWCGSAFlAwQCAQUABCBYvhaHiMpFmFWX # fYSTpYqufxCtNTDD6ZwPSMfBgysulAIRAOnxuO5Q2taiUcuAEooAltsYDzIwMjQx # MjI4MTUzNzE1WqCCEwMwgga8MIIEpKADAgECAhALrma8Wrp/lYfG+ekE4zMEMA0G # CSqGSIb3DQEBCwUAMGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg # SW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBHNCBSU0E0MDk2IFNIQTI1 # NiBUaW1lU3RhbXBpbmcgQ0EwHhcNMjQwOTI2MDAwMDAwWhcNMzUxMTI1MjM1OTU5 # WjBCMQswCQYDVQQGEwJVUzERMA8GA1UEChMIRGlnaUNlcnQxIDAeBgNVBAMTF0Rp # Z2lDZXJ0IFRpbWVzdGFtcCAyMDI0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC # CgKCAgEAvmpzn/aVIauWMLpbbeZZo7Xo/ZEfGMSIO2qZ46XB/QowIEMSvgjEdEZ3 # v4vrrTHleW1JWGErrjOL0J4L0HqVR1czSzvUQ5xF7z4IQmn7dHY7yijvoQ7ujm0u # 6yXF2v1CrzZopykD07/9fpAT4BxpT9vJoJqAsP8YuhRvflJ9YeHjes4fduksTHul # ntq9WelRWY++TFPxzZrbILRYynyEy7rS1lHQKFpXvo2GePfsMRhNf1F41nyEg5h7 # iOXv+vjX0K8RhUisfqw3TTLHj1uhS66YX2LZPxS4oaf33rp9HlfqSBePejlYeEdU # 740GKQM7SaVSH3TbBL8R6HwX9QVpGnXPlKdE4fBIn5BBFnV+KwPxRNUNK6lYk2y1 # WSKour4hJN0SMkoaNV8hyyADiX1xuTxKaXN12HgR+8WulU2d6zhzXomJ2PleI9V2 # yfmfXSPGYanGgxzqI+ShoOGLomMd3mJt92nm7Mheng/TBeSA2z4I78JpwGpTRHiT # 7yHqBiV2ngUIyCtd0pZ8zg3S7bk4QC4RrcnKJ3FbjyPAGogmoiZ33c1HG93Vp6lJ # 415ERcC7bFQMRbxqrMVANiav1k425zYyFMyLNyE1QulQSgDpW9rtvVcIH7WvG9sq # Yup9j8z9J1XqbBZPJ5XLln8mS8wWmdDLnBHXgYly/p1DhoQo5fkCAwEAAaOCAYsw # ggGHMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoG # CCsGAQUFBwMIMCAGA1UdIAQZMBcwCAYGZ4EMAQQCMAsGCWCGSAGG/WwHATAfBgNV # HSMEGDAWgBS6FtltTYUvcyl2mi91jGogj57IbzAdBgNVHQ4EFgQUn1csA3cOKBWQ # ZqVjXu5Pkh92oFswWgYDVR0fBFMwUTBPoE2gS4ZJaHR0cDovL2NybDMuZGlnaWNl # cnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0UlNBNDA5NlNIQTI1NlRpbWVTdGFtcGlu # Z0NBLmNybDCBkAYIKwYBBQUHAQEEgYMwgYAwJAYIKwYBBQUHMAGGGGh0dHA6Ly9v # Y3NwLmRpZ2ljZXJ0LmNvbTBYBggrBgEFBQcwAoZMaHR0cDovL2NhY2VydHMuZGln # aWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0UlNBNDA5NlNIQTI1NlRpbWVTdGFt # cGluZ0NBLmNydDANBgkqhkiG9w0BAQsFAAOCAgEAPa0eH3aZW+M4hBJH2UOR9hHb # m04IHdEoT8/T3HuBSyZeq3jSi5GXeWP7xCKhVireKCnCs+8GZl2uVYFvQe+pPTSc # VJeCZSsMo1JCoZN2mMew/L4tpqVNbSpWO9QGFwfMEy60HofN6V51sMLMXNTLfhVq # s+e8haupWiArSozyAmGH/6oMQAh078qRh6wvJNU6gnh5OruCP1QUAvVSu4kqVOcJ # VozZR5RRb/zPd++PGE3qF1P3xWvYViUJLsxtvge/mzA75oBfFZSbdakHJe2BVDGI # GVNVjOp8sNt70+kEoMF+T6tptMUNlehSR7vM+C13v9+9ZOUKzfRUAYSyyEmYtsnp # ltD/GWX8eM70ls1V6QG/ZOB6b6Yum1HvIiulqJ1Elesj5TMHq8CWT/xrW7twipXT # J5/i5pkU5E16RSBAdOp12aw8IQhhA/vEbFkEiF2abhuFixUDobZaA0VhqAsMHOma # T3XThZDNi5U2zHKhUs5uHHdG6BoQau75KiNbh0c+hatSF+02kULkftARjsyEpHKs # F7u5zKRbt5oK5YGwFvgc4pEVUNytmB3BpIiowOIIuDgP5M9WArHYSAR16gc0dP2X # dkMEP5eBsX7bf/MGN4K3HP50v/01ZHo/Z5lGLvNwQ7XHBx1yomzLP8lx4Q1zZKDy # Hcp4VQJLu2kWTsKsOqQwggauMIIElqADAgECAhAHNje3JFR82Ees/ShmKl5bMA0G # CSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ # bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0 # IFRydXN0ZWQgUm9vdCBHNDAeFw0yMjAzMjMwMDAwMDBaFw0zNzAzMjIyMzU5NTla # MGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UE # AxMyRGlnaUNlcnQgVHJ1c3RlZCBHNCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBp # bmcgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDGhjUGSbPBPXJJ # UVXHJQPE8pE3qZdRodbSg9GeTKJtoLDMg/la9hGhRBVCX6SI82j6ffOciQt/nR+e # DzMfUBMLJnOWbfhXqAJ9/UO0hNoR8XOxs+4rgISKIhjf69o9xBd/qxkrPkLcZ47q # UT3w1lbU5ygt69OxtXXnHwZljZQp09nsad/ZkIdGAHvbREGJ3HxqV3rwN3mfXazL # 6IRktFLydkf3YYMZ3V+0VAshaG43IbtArF+y3kp9zvU5EmfvDqVjbOSmxR3NNg1c # 1eYbqMFkdECnwHLFuk4fsbVYTXn+149zk6wsOeKlSNbwsDETqVcplicu9Yemj052 # FVUmcJgmf6AaRyBD40NjgHt1biclkJg6OBGz9vae5jtb7IHeIhTZgirHkr+g3uM+ # onP65x9abJTyUpURK1h0QCirc0PO30qhHGs4xSnzyqqWc0Jon7ZGs506o9UD4L/w # ojzKQtwYSH8UNM/STKvvmz3+DrhkKvp1KCRB7UK/BZxmSVJQ9FHzNklNiyDSLFc1 # eSuo80VgvCONWPfcYd6T/jnA+bIwpUzX6ZhKWD7TA4j+s4/TXkt2ElGTyYwMO1uK # IqjBJgj5FBASA31fI7tk42PgpuE+9sJ0sj8eCXbsq11GdeJgo1gJASgADoRU7s7p # XcheMBK9Rp6103a50g5rmQzSM7TNsQIDAQABo4IBXTCCAVkwEgYDVR0TAQH/BAgw # BgEB/wIBADAdBgNVHQ4EFgQUuhbZbU2FL3MpdpovdYxqII+eyG8wHwYDVR0jBBgw # FoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQM # MAoGCCsGAQUFBwMIMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYYaHR0cDov # L29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2FjZXJ0cy5k # aWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNVHR8EPDA6 # MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVk # Um9vdEc0LmNybDAgBgNVHSAEGTAXMAgGBmeBDAEEAjALBglghkgBhv1sBwEwDQYJ # KoZIhvcNAQELBQADggIBAH1ZjsCTtm+YqUQiAX5m1tghQuGwGC4QTRPPMFPOvxj7 # x1Bd4ksp+3CKDaopafxpwc8dB+k+YMjYC+VcW9dth/qEICU0MWfNthKWb8RQTGId # DAiCqBa9qVbPFXONASIlzpVpP0d3+3J0FNf/q0+KLHqrhc1DX+1gtqpPkWaeLJ7g # iqzl/Yy8ZCaHbJK9nXzQcAp876i8dU+6WvepELJd6f8oVInw1YpxdmXazPByoyP6 # wCeCRK6ZJxurJB4mwbfeKuv2nrF5mYGjVoarCkXJ38SNoOeY+/umnXKvxMfBwWpx # 2cYTgAnEtp/Nh4cku0+jSbl3ZpHxcpzpSwJSpzd+k1OsOx0ISQ+UzTl63f8lY5kn # LD0/a6fxZsNBzU+2QJshIUDQtxMkzdwdeDrknq3lNHGS1yZr5Dhzq6YBT70/O3it # TK37xJV77QpfMzmHQXh6OOmc4d0j/R0o08f56PGYX/sr2H7yRp11LB4nLCbbbxV7 # HhmLNriT1ObyF5lZynDwN7+YAN8gFk8n+2BnFqFmut1VwDophrCYoCvtlUG3OtUV # mDG0YgkPCr2B2RP+v6TR81fZvAT6gt4y3wSJ8ADNXcL50CN/AAvkdgIm2fBldkKm # KYcJRyvmfxqkhQ/8mJb2VVQrH4D6wPIOK+XW+6kvRBVK5xMOHds3OBqhK/bt1nz8 # MIIFjTCCBHWgAwIBAgIQDpsYjvnQLefv21DiCEAYWjANBgkqhkiG9w0BAQwFADBl # MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 # d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv # b3QgQ0EwHhcNMjIwODAxMDAwMDAwWhcNMzExMTA5MjM1OTU5WjBiMQswCQYDVQQG # EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl # cnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0G # CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7J # IT3yithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxS # D1Ifxp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb # 7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1ef # VFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoY # OAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSa # M0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI # 8OCiEhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9L # BADMfRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfm # Q6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDr # McXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15Gkv # mB0t9dmpsh3lGwIDAQABo4IBOjCCATYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E # FgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wHwYDVR0jBBgwFoAUReuir/SSy4IxLVGL # p6chnfNtyA8wDgYDVR0PAQH/BAQDAgGGMHkGCCsGAQUFBwEBBG0wazAkBggrBgEF # BQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUFBzAChjdodHRw # Oi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0Eu # Y3J0MEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9E # aWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwEQYDVR0gBAowCDAGBgRVHSAAMA0G # CSqGSIb3DQEBDAUAA4IBAQBwoL9DXFXnOF+go3QbPbYW1/e/Vwe9mqyhhyzshV6p # Grsi+IcaaVQi7aSId229GhT0E0p6Ly23OO/0/4C5+KH38nLeJLxSA8hO0Cre+i1W # z/n096wwepqLsl7Uz9FDRJtDIeuWcqFItJnLnU+nBgMTdydE1Od/6Fmo8L8vC6bp # 8jQ87PcDx4eo0kxAGTVGamlUsLihVo7spNU96LHc/RzY9HdaXFSMb++hUD38dglo # hJ9vytsgjTVgHAIDyyCwrFigDkBjxZgiwbJZ9VVrzyerbHbObyMt9H5xaiNrIv8S # uFQtJ37YOtnwtoeW/VvRXKwYw02fc7cBqZ9Xql4o4rmUMYIDdjCCA3ICAQEwdzBj # MQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xOzA5BgNVBAMT # MkRpZ2lDZXJ0IFRydXN0ZWQgRzQgUlNBNDA5NiBTSEEyNTYgVGltZVN0YW1waW5n # IENBAhALrma8Wrp/lYfG+ekE4zMEMA0GCWCGSAFlAwQCAQUAoIHRMBoGCSqGSIb3 # DQEJAzENBgsqhkiG9w0BCRABBDAcBgkqhkiG9w0BCQUxDxcNMjQxMjI4MTUzNzE1 # WjArBgsqhkiG9w0BCRACDDEcMBowGDAWBBTb04XuYtvSPnvk9nFIUIck1YZbRTAv # BgkqhkiG9w0BCQQxIgQg/vA3tY8aUg/upn/FTGyXsgFPQqMFVriika8BYcNlSc4w # NwYLKoZIhvcNAQkQAi8xKDAmMCQwIgQgdnafqPJjLx9DCzojMK7WVnX+13PbBdZl # uQWTmEOPmtswDQYJKoZIhvcNAQEBBQAEggIAG1a6hRraxbergnV/uP8KeG3VvRjJ # dUyEVxgOlky1PTVq3IPcKn1079oheyJIds18nRZ8XtB1kNprjz6QXMT1Okx6KAHy # iFldTMg40b9jyx3iSexoayjSRZN4Z3aF1hdRPC2HeJkLo0YO9zCOGUeKQc/9DcRP # 9zN51xM91jkkrTlqJ/H5ZS52Lh1y2Rp0M4wgVWFUcp3GuHNNdqy/FeYMpyWUoPBZ # UE45vAWVwMbA70QOrarQ/aKjzho53gvEjv42BZ0dcwq2WLxFzlZNNrdlJ4Fy0Miq # AckFGhYXFDH0WPTf03pdL4knTU/ak8AA995pT+9nlvxrvSKjsHokPn4HGbd6GkdS # sJzJUOZ3J4fQO3ICxW1+00eq7HwqHtJSE6o5pzN8eVhP8OsfBSqZK4ILD5YGP6vZ # W45bU1L7iI+CHh8VKCPrHB/mkUw3pvk/A2KSMThLW17XOLx69pWE6zNWiKPBWAI7 # HxbhXE8eA7By4DuIXA32jAry8wnnsyhI2u4Ha2+rB8czVBbdM3LPaDDPHROCTdZW # HpUI+9RcMxJUseJW8cvTGA0oKZldq0uMrW4KmDXvTp5O183hDMTvAEVGZTPW3zQD # n6wZO2FC0ELBYlosgrGEp+dbI405veRbRX8cwL9spihL+2LFoJLjWlzw/kgF3mjT # KxHJuPVWkYnJGl8= # SIG # End signature block |