Private/AzStackHci.Network.Helpers.ps1

# ////////////////////////////////////////////////////////////////////////////
# Strict Mode v1 (PS 5.1 safe) - surfaces reads of uninitialised variables at runtime.
Set-StrictMode -Version 1.0

# Test if proxy is enabled and return boolean
function Get-Proxy
{
    <#
    .SYNOPSIS
        Check if proxy is enabled and return boolean and proxy server uri
    #>


    begin {
        # Write-Debug "Get-Proxy: Beginning proxy detection process"
    }

    process {
        $line1, $line2, $line3, $JsonLines = netsh winhttp show advproxy
        $ProxyInformation = $JsonLines | ConvertFrom-Json -ErrorAction SilentlyContinue
        # Return True/False and the Proxy server uri as a PSObject
        $ProxyReturnVariable = New-Object PsObject -Property @{
            # True/False
            Enabled = [bool]$ProxyInformation.Proxy
            # Proxy server URI
            Server = $ProxyInformation.Proxy
            # Arc Gateway scenario can carry distinct HTTP and HTTPS proxies in a single
            # 'http=customerproxy:8080;https=localhost:40343' string. These are parsed out
            # below (null when a single, un-prefixed proxy is configured — Server holds it).
            HttpProxy = $null
            HttpsProxy = $null
            # Proxy bypass configuration (v0.6.8). Two independent sources are captured so the
            # RFC1918 / Private-Link classification can VERIFY whether a private-endpoint FQDN is
            # correctly excluded from the forward proxy (rather than merely advising it):
            # ProxyBypass - the WinHTTP 'Bypass List' (comma-separated, '*' wildcard). Read from
            # the TEXT `netsh winhttp show proxy` output below; the advproxy JSON
            # parsed above does not expose the bypass entries.
            # NoProxyEnv - the machine NO_PROXY environment variable (comma-separated; entries
            # may be CIDR ranges, '.'-prefixed domain suffixes, hostnames or IPs).
            # Since Azure Local 2506 this is configured automatically at Arc
            # registration, so it is the authoritative bypass fallback.
            ProxyBypass = @()
            NoProxyEnv  = @()
        }
        # Initialised here so the later `if($ProxyStrings)` read is safe under Set-StrictMode v1.0
        # even when the proxy server string contains no ';' (no semicolon -> never assigned below).
        $ProxyStrings = $null

        # ------------------------------------------------------------------------
        # Capture the WinHTTP 'Bypass List' (v0.6.8) from the human-readable
        # `netsh winhttp show proxy` output. It prints a 'Bypass List : a,b,c' line
        # when a static WinHTTP proxy is configured. Best-effort: never throws.
        try {
            $winHttpProxyText = netsh winhttp show proxy 2>$null
            if ($winHttpProxyText) {
                $bypassLine = $winHttpProxyText | Where-Object { $_ -match '(?i)Bypass\s*List' } | Select-Object -First 1
                if ($bypassLine) {
                    $bypassRaw = ($bypassLine -split ':', 2)[1]
                    if (-not [string]::IsNullOrWhiteSpace($bypassRaw)) {
                        $ProxyReturnVariable.ProxyBypass = @(
                            $bypassRaw -split ',' |
                                ForEach-Object { $_.Trim() } |
                                Where-Object { $_ -and $_ -ne '(none)' }
                        )
                    }
                }
            }
        } catch {
            Write-Debug "Get-Proxy: failed to read WinHTTP bypass list: $($_.Exception.Message)"
        }

        # Capture the NO_PROXY environment variable (machine scope first, then the
        # current process scope as a fallback). Best-effort: never throws.
        try {
            $noProxyRaw = [Environment]::GetEnvironmentVariable('NO_PROXY', 'Machine')
            if ([string]::IsNullOrWhiteSpace($noProxyRaw)) {
                $noProxyRaw = $env:NO_PROXY
            }
            if (-not [string]::IsNullOrWhiteSpace($noProxyRaw)) {
                $ProxyReturnVariable.NoProxyEnv = @(
                    $noProxyRaw -split ',' |
                        ForEach-Object { $_.Trim() } |
                        Where-Object { $_ }
                )
            }
        } catch {
            Write-Debug "Get-Proxy: failed to read NO_PROXY environment variable: $($_.Exception.Message)"
        }

        # Check if the Proxy is enabled and if the proxy server is set
        if($ProxyReturnVariable.Enabled) {
            if(-not($ProxyReturnVariable.Server)){
                # In case the proxy server is not set from netsh winhttp show advproxy output
                $proxyUri = [Uri]$null
                $ProxyTest = [System.Net.WebRequest]::GetSystemWebProxy()
                $ProxyTest.Credentials = [System.Net.CredentialCache]::DefaultCredentials
                # use a known URL to test the proxy server, but http, in case of Arc Gateway, to prevent "localhost" from being returned
                # This is a known URL that should be accessible from any network
                $TestUrl = [System.Uri]::new("http://oneocsp.microsoft.com")
                # Test the proxy server using a known URL
                $proxyUri = $ProxyTest.GetProxy($TestUrl)
                if($proxyUri -eq $TestUrl) {
                    # Proxy is not required, so do not use it
                    $ProxyReturnVariable.Enabled = $false
                    Write-HostAzS "`t`nNo proxy server detected, using direct connection...`n" -ForegroundColor Green
                } else {
                    # Proxy is required, so use it
                    $ProxyReturnVariable.Server = $proxyUri
                }
            }
            # Check if the proxy server string has a semi-colon which can be used for Arc Gateway
            if(-not [string]::IsNullOrWhiteSpace($ProxyReturnVariable.Server) -and $ProxyReturnVariable.Server -match ";"){
                # In case the proxy server is set from netsh winhttp show advproxy output
                [array]$ProxyStrings = $ProxyReturnVariable.Server.ToString().Split(";")
            }
            if($ProxyStrings){
                # Check if the proxy server string has a semi-colon which can be used for Arc Gateway
                # Multiple proxy servers detected
                Write-HostAzS "`n`tArc Gateway scenario detected (possible), as multiple proxy servers detected ('netsh winhttp show advproxy')..."
                ForEach($ProxyServer in $ProxyStrings){
                    # Trim the proxy server string
                    $ProxyServer = $ProxyServer.Trim()
                    if($ProxyServer -like "http=*"){
                        # HTTP proxy server (should be customer proxy server)
                        # Check if the proxy server is set from netsh winhttp show advproxy output
                        $ProxyReturnVariable.HttpProxy = $ProxyServer.Substring(5)
                        Write-HostAzS "`tHTTP Proxy server detected, using proxy: $($ProxyServer)" -ForegroundColor Green    
                    } elseif($ProxyServer -like "https=*"){
                        # HTTPS proxy server (might be Arc Gateway Agent, "localhost")
                        # Check if the proxy server is set from netsh winhttp show advproxy output
                        $ProxyReturnVariable.HttpsProxy = $ProxyServer.Substring(6)
                        Write-HostAzS "`tHTTPS Proxy server detected, using proxy: $($ProxyServer)" -ForegroundColor Green    
                    } else {
                        # Other proxy server detected
                        # Check if the proxy server is set from netsh winhttp show advproxy output
                        Write-HostAzS "`tProxy server detected, using proxy: $($ProxyServer)" -ForegroundColor Green    
                    }
                } # End ForEach
                Write-HostAzS ""
            } else {
                # Single proxy detected
                # A single proxy can still carry an 'http=' / 'https=' prefix (no semicolon);
                # parse it so HttpProxy / HttpsProxy are populated for consumers in that case too.
                $singleProxy = $ProxyReturnVariable.Server.ToString().Trim()
                if($singleProxy -like "http=*"){
                    $ProxyReturnVariable.HttpProxy = $singleProxy.Substring(5)
                } elseif($singleProxy -like "https=*"){
                    $ProxyReturnVariable.HttpsProxy = $singleProxy.Substring(6)
                }
                Write-HostAzS "`t`nProxy server detected, using proxy: $($ProxyReturnVariable.Server)`n" -ForegroundColor Green
            }

        } else {
            # Proxy is NOT enabled
            # No proxy server detected, so use direct connection
            Write-HostAzS "`t`nNo proxy server detected, using direct connection...`n" -ForegroundColor Green
        }

    } # End of process block

    end {
        # Write-Debug "Get-Proxy: Proxy detection process completed"

        # Return the ProxyReturnVariable object
        Return $ProxyReturnVariable
    }
} # End Function Get-Proxy


# ////////////////////////////////////////////////////////////////////////////
# Determine whether an IPv4 address falls inside a CIDR range (v0.6.8).
# IPv4-only — the Azure Local NO_PROXY bypass CIDRs (10.0.0.0/8, 172.16.0.0/12,
# 192.168.0.0/16, infra subnets) are all IPv4. Best-effort: never throws.
function Test-IpInCidr
{
    <#
    .SYNOPSIS
        Return $true if the given IPv4 address is contained within the given CIDR range.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)][string]$IpAddress,
        [Parameter(Mandatory = $true)][string]$Cidr
    )
    try {
        $parts = $Cidr -split '/'
        if ($parts.Count -ne 2) { return $false }
        $network = [System.Net.IPAddress]::Parse($parts[0].Trim())
        $prefix  = [int]$parts[1].Trim()
        if ($prefix -lt 0 -or $prefix -gt 32) { return $false }
        $ip = [System.Net.IPAddress]::Parse($IpAddress.Trim())
        $ipBytes  = $ip.GetAddressBytes()
        $netBytes = $network.GetAddressBytes()
        # IPv4 only (4 bytes). Reverse for little-endian BitConverter on both.
        if ($ipBytes.Length -ne 4 -or $netBytes.Length -ne 4) { return $false }
        [array]::Reverse($ipBytes)
        [array]::Reverse($netBytes)
        $ipInt  = [uint64][System.BitConverter]::ToUInt32($ipBytes, 0)
        $netInt = [uint64][System.BitConverter]::ToUInt32($netBytes, 0)
        # /0 matches everything. Otherwise compare only the top $prefix (network) bits by
        # right-shifting away the (32 - prefix) host bits on both operands. Using -shr avoids
        # the unreliable uint64 -shl mask construction in Windows PowerShell.
        if ($prefix -eq 0) { return $true }
        $hostBits = 32 - $prefix
        return (($ipInt -shr $hostBits) -eq ($netInt -shr $hostBits))
    } catch {
        return $false
    }
} # End Function Test-IpInCidr


# ////////////////////////////////////////////////////////////////////////////
# Verify whether an endpoint (FQDN + its resolved IP) is excluded from the forward
# proxy via either the WinHTTP bypass list or the NO_PROXY environment variable (v0.6.8).
#
# Private-endpoint traffic (RFC1918 addresses) MUST bypass the proxy and route over
# ExpressRoute / Site-to-Site VPN. This helper turns the module's previous *advisory*
# ("ensure this FQDN is on the bypass list") into a *verified* check, honouring the two
# different bypass syntaxes documented for Azure Local:
# * WinHTTP / WinInet : '*' wildcard (e.g. '*.blob.core.windows.net', '192.168.1.*')
# * NO_PROXY env var : '.'-prefix / bare-suffix domains and CIDR ranges
# (e.g. '.contoso.com', '10.0.0.0/8')
# Matching is case-insensitive. Returns a result object; never throws.
function Test-EndpointBypassed
{
    <#
    .SYNOPSIS
        Return a result object indicating whether an FQDN/IP is on a proxy bypass source.
    .OUTPUTS
        [pscustomobject] @{ Bypassed = [bool]; Source = 'WinHTTP'|'NO_PROXY'|''; MatchedRule = [string] }
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)][string]$Fqdn,
        [Parameter()][string]$IpAddress,
        [Parameter()][string[]]$WinHttpBypass = @(),
        [Parameter()][string[]]$NoProxyEnv = @()
    )

    $result = [pscustomobject]@{ Bypassed = $false; Source = ''; MatchedRule = '' }
    if ([string]::IsNullOrWhiteSpace($Fqdn)) { return $result }
    $normalizedFqdn = $Fqdn.Trim().ToLower().TrimEnd('.')

    # --- WinHTTP / WinInet bypass entries ('*' wildcard) ---
    foreach ($entry in $WinHttpBypass) {
        if ([string]::IsNullOrWhiteSpace($entry)) { continue }
        $e = $entry.Trim().ToLower()
        # Escape everything, then turn the escaped '*' back into '.*' for a full-string match.
        $pattern = '^' + ([regex]::Escape($e) -replace '\\\*', '.*') + '$'
        if ($normalizedFqdn -match $pattern) {
            $result.Bypassed = $true; $result.Source = 'WinHTTP'; $result.MatchedRule = $entry
            return $result
        }
        if ($IpAddress -and ($IpAddress -match $pattern)) {
            $result.Bypassed = $true; $result.Source = 'WinHTTP'; $result.MatchedRule = $entry
            return $result
        }
    }

    # --- NO_PROXY env entries ('.'-prefix / bare suffix + CIDR) ---
    foreach ($entry in $NoProxyEnv) {
        if ([string]::IsNullOrWhiteSpace($entry)) { continue }
        $e = $entry.Trim().ToLower()
        if ($e -match '^\d{1,3}(\.\d{1,3}){3}/\d{1,2}$') {
            # CIDR range — match against the resolved IP (NO_PROXY uses CIDR, not wildcards).
            if ($IpAddress -and (Test-IpInCidr -IpAddress $IpAddress -Cidr $e)) {
                $result.Bypassed = $true; $result.Source = 'NO_PROXY'; $result.MatchedRule = $entry
                return $result
            }
            continue
        }
        # A leading '.' means "this domain and any subdomain"; a bare domain is treated the
        # same way (suffix match) plus an exact-host match.
        $suffix = $e.TrimStart('.')
        if ($normalizedFqdn -eq $suffix -or $normalizedFqdn.EndsWith('.' + $suffix)) {
            $result.Bypassed = $true; $result.Source = 'NO_PROXY'; $result.MatchedRule = $entry
            return $result
        }
        if ($IpAddress -and ($IpAddress -eq $e)) {
            $result.Bypassed = $true; $result.Source = 'NO_PROXY'; $result.MatchedRule = $entry
            return $result
        }
    }

    return $result
} # End Function Test-EndpointBypassed


# ////////////////////////////////////////////////////////////////////////////
# This function retrieves the SSL certificate chain from a remote HTTPS endpoint
# It uses the System.Net.Http.HttpClient class to make the request and capture the certificate chain.
#
# Renamed from Get-SslCertificateChain in v0.6.6 to avoid a name collision with the
# AzStackHci.EnvironmentChecker module (10.2509+), which exports a function with the
# same name but a different parameter set. Because Get-AzStackHciEnvironmentCheckerModule
# Import-Module's that module from inside our module's session state, EnvironmentChecker's
# exported Get-SslCertificateChain shadowed our private helper, breaking certificate-detail
# capture for every HTTPS endpoint with: "A parameter cannot be found that matches
# parameter name 'AllowAutoRedirect'". Renaming the private helper resolves the conflict
# permanently.
function Get-AzSHciSslCertificateChain
{
    <#
    .SYNOPSIS
        Retrieve remote ssl certificate & chain from https endpoint for Desktop and Core
    .NOTES
        Credit: https://github.com/markekraus
    #>

    [CmdletBinding()]
    param (
        [system.uri]
        $url,

        [Parameter()]
        [bool]
        $AllowAutoRedirect,

        [Parameter()]
        [string]
        $Proxy
    )

    begin {
        # Write-Debug "Get-AzSHciSslCertificateChain: Beginning SSL certificate chain retrieval for '$url'"
    }

    process {
    try
    {
        $cs = @'
    using System;
    using System.Collections.Generic;
    using System.Net.Http;
    using System.Net.Security;
    using System.Security.Cryptography.X509Certificates;
 
    namespace CertificateCapture
    {
        public class Utility
        {
            public static Func<HttpRequestMessage,X509Certificate2,X509Chain,SslPolicyErrors,Boolean> ValidationCallback =
                (message, cert, chain, errors) => {
                    CapturedCertificates.Clear();
                    var newCert = new X509Certificate2(cert);
                    var newChain = new X509Chain();
                    newChain.Build(newCert);
                    CapturedCertificates.Add(new CapturedCertificate(){
                        Certificate = newCert,
                        CertificateChain = newChain,
                        PolicyErrors = errors,
                        URI = message.RequestUri
                    });
                    return true;
                };
            public static List<CapturedCertificate> CapturedCertificates = new List<CapturedCertificate>();
        }
 
        public class CapturedCertificate
        {
            public X509Certificate2 Certificate { get; set; }
            public X509Chain CertificateChain { get; set; }
            public SslPolicyErrors PolicyErrors { get; set; }
            public Uri URI { get; set; }
        }
    }
'@


        try
        {
            if (-not ('CertificateCapture.Utility' -as [type]))
            {
                if ($PSEdition -ne 'Core')
                {
                    Add-Type -AssemblyName System.Net.Http
                    Add-Type $cs -ReferencedAssemblies System.Net.Http
                }
                else
                {
                    Add-Type $cs
                }
            }
        }
        catch
        {
            if ($_.Exception.Message -notmatch 'Definition of new types is not supported in this language mode')
            {
                throw "Language mode does not allow this test Error: $_"
            }
        }

        # Reset resources so exceptional setup paths remain safe in the finally block.
        $Certs = $null
        $Handler = $null
        $Client = $null
        $Request = $null

        # Create a new list to hold captured certificates.
        $Certs = [CertificateCapture.Utility]::CapturedCertificates
        # Clear any previously captured certificates.
        $Certs.Clear()
        # Create the HttpClientHandler.
        $Handler = [System.Net.Http.HttpClientHandler]::new()
        # This is important to capture the certificate chain of the first endpoint, not redirected endpoints.
        if($AllowAutoRedirect -eq $false)
        {
            # Set the handler to not allow auto redirects
            # https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpclienthandler.allowautoredirect
            $Handler.AllowAutoRedirect = $false
        }
        if ($Proxy)
        {
            $Handler.Proxy = New-Object System.Net.WebProxy($proxy)
        }
        # Set the ServerCertificateCustomValidationCallback to our custom callback.
        $Handler.ServerCertificateCustomValidationCallback = [CertificateCapture.Utility]::ValidationCallback
        # Create the HttpClient with the handler
        $Client = [System.Net.Http.HttpClient]::new($Handler)
        # Set a timeout to 15 seconds (reduced from 60s to limit impact of unresponsive backend pool servers):
        $Client.Timeout = [timespan]::FromTicks($script:CERT_CAPTURE_TIMEOUT_TICKS)
        try {
            # Setup the request to the URL.
            $Request = $Client.GetAsync($url)
            # Wait for the request to complete calling the Result method.
            $Null = $Request.Result
            # Check if the request is completed and that certificates were captured.
            if(($Request.IsCompleted) -and $Certs){
                # Return the captured certificate chain
                Write-Debug "Successfully obtained SSL certificate chain from endpoint: '$url'"
                return $Certs.CertificateChain
            } else {
                # Return null if no certificates were captured.
                Write-Debug "Failed to obtain SSL certificate chain from endpoint: '$url'"
                return $null
            }
        }
        finally {
            # Dispose IDisposable resources to prevent socket/handle leaks
            if ($Request) { $Request.Dispose() }
            if ($Client)  { $Client.Dispose() }
            if ($Handler) { $Handler.Dispose() }
        }

    }
    catch
    {
        throw $_
    }
    } # End of process block

    end {
        # Write-Debug "Get-AzSHciSslCertificateChain: SSL certificate chain retrieval completed"
    }
} # End Function Get-AzSHciSslCertificateChain

# SIG # Begin signature block
# MIInOQYJKoZIhvcNAQcCoIInKjCCJyYCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBwKL0TS5XcAu2N
# e6qmTuppom+MNTCj18VVThMtujL2XqCCDMkwggYEMIID7KADAgECAhMzAAACHPrN
# xZvoL37EAAAAAAIcMA0GCSqGSIb3DQEBCwUAMFcxCzAJBgNVBAYTAlVTMR4wHAYD
# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBD
# b2RlIFNpZ25pbmcgUENBIDIwMjQwHhcNMjYwNDE2MTg1OTQxWhcNMjcwNDE1MTg1
# OTQxWjB0MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE
# BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYD
# VQQDExVNaWNyb3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IB
# DwAwggEKAoIBAQDVsZfgOKmM31HPfoWOoNEiw0SlCiIxUMC0I9NMWbucKOw/e9lP
# oAoehQVu6SG65V4EPzrYsnBnFPNoi4/HoOdjhz1qkrEt4I6tEcxXU6oOeY9zGveC
# /3iBeuhLYxM3M/PkcUoebF+Nednm8OkdSPoDu8imViHPQq/8CQUu0WRR4rE+dMRf
# rpVqfmNi2qWCX94T4MsepijGVkwE//tJg0ryAiYdHT34LSnlG/RSBZmQRGWZ5g8j
# qnKjRParSqMft1gvjuUTVgtWNZfgcLFSK5Wa0myrq8OPcgTGGsRgun+tnSS+IxDT
# xVsAPH1OzvPjwomguByhUe/OcvUN0D5Wmp7xAgMBAAGjggGqMIIBpjAOBgNVHQ8B
# Af8EBAMCB4AwHwYDVR0lBBgwFgYKKwYBBAGCN0wIAQYIKwYBBQUHAwMwHQYDVR0O
# BBYEFNoH7a2YDjOSwpkp6DHcmUS7J+0yMFQGA1UdEQRNMEukSTBHMS0wKwYDVQQL
# EyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxFjAUBgNVBAUT
# DTIzMDAxMis1MDc1NjkwHwYDVR0jBBgwFoAUf1k/VCHarU/vBeXmo9ctBpQSCDEw
# YAYDVR0fBFkwVzBVoFOgUYZPaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9w
# cy9jcmwvTWljcm9zb2Z0JTIwQ29kZSUyMFNpZ25pbmclMjBQQ0ElMjAyMDI0LmNy
# bDBtBggrBgEFBQcBAQRhMF8wXQYIKwYBBQUHMAKGUWh0dHA6Ly93d3cubWljcm9z
# b2Z0LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwQ29kZSUyMFNpZ25pbmcl
# MjBQQ0ElMjAyMDI0LmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IC
# AQAUnEqhaRXe0T3hIJjvdQErEkrA/7bByjn6t5IArODkkRjzkYwtKMc2yYj2quaN
# rLutWw2YZcngKPy1b71YyDJQTy4NDRwaSh9Tw5thrk3NmcPrAHia5vtcBJ1CgtKK
# 7mQbIcQ22d/N3813ayCDDFewu1+jsZmX+r/aTEqaOM4TVxVtRSkuCy8nAXKuChOK
# Li/zA4XuH8iEYqIsj2YoNaeSxVmeGiERXpKdo3dDmYi0kO5w2D8VS4c3+9h6gElY
# BaAAg/dYErBg27qT3vv0zRDJhJufvCNylA8S7/+8H5E/PV5cng6na9VV/w9OV3qu
# uND6zdGa2EX38Glp50F9AIQk3p2xXmcvorDeM4XJ7UlWYBi6g80J1SSOQnInCYFE
# msfUNn3+1AaTJKSJL83quKArTac2pKhu0Yzzzrzo6HrsRiQKzpnRBb1/dMa6P3hz
# 75XbMRBctNsFhZC07WCmjExdLg2eHW5uV0TY8D5+6wozJf7vF3+WHkYPO85Z+BC6
# U4FkNbYNycZ9cE4j1tXRdyDCfml6c0HWPHjNVDObrv9lKt3qUqFpX38VCqVCyNOO
# 1UcXfQiVjJw32U2WUKZjt/neJKHEBsm9kFsLuWzkQ53+qcaSaytmsCnk2gOglrlD
# 5d3kKyvvAw+rzm0lT8K38P6PLxfZQHhu4W8dV7Av8N2ZmDCCBr0wggSloAMCAQIC
# EzMAAAA5O7Y3Gb8GHWcAAAAAADkwDQYJKoZIhvcNAQEMBQAwgYgxCzAJBgNVBAYT
# AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD
# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBS
# b290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDExMB4XDTI0MDgwODIwNTQxOFoX
# DTM2MDMyMjIyMTMwNFowVzELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29m
# dCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9zb2Z0IENvZGUgU2lnbmluZyBQ
# Q0EgMjAyNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANgBnB7jOMeq
# lRYHNa265v4IY9fH8TKhemHfPINe1gpLaV3dhg324WwH06LcHbpnsBukCDNitryo
# 0dtS/EW6I/yEL/bLSY8hKpbfQuWusBPr9qazYcDxCW/qnjb5JsI1s8bNOg3bVATv
# QVL4tcf03aTycsz8QeCdM0l/yHRObJ9QqazM1r6VPEOJ7LL+uEEb73w6QCuhs89a
# 1uv1zerOYMnsneRRwCbpyW11IcggU0cRKDDq1pjVJzIbIF6+oiXXbReOsgeI8zu1
# FyQfK0fVkaya8SmVHQ/tOf23mZ4W9k0Ri22QW9p3UgSC5OUDktKxxcCmGL6tXLfO
# GSWHIIV4YrTJTT6PNty5REojHJuZHArkF9VnHTERWoTjAzfI3kP+5b4alUdhgAZ7
# ttOu1bVnXfHaqPYl2rPs20ji03LOVWsh/radgE17es5hL+t6lV0eVHrVhsssROWJ
# uz2MXMCt7iw7lFPG9LXKGjsmonn2gotGdHIuEg5JnJMJVmixd5LRlkmgYRZKzhxS
# CwyoGIq0PhaA7Y+VPct5pCHkijcIIDm0nlkK+0KyepolcqGm0T/GYQRMhHJlGOOm
# VQop36wUVUYklUy++vDWeEgEo4s7hxN6mIbf2MSIQ/iIfMZgJxC69oukMUXCrOC3
# SkE/xIkgpfl22MM1itkZ35nNXkMolU1lAgMBAAGjggFOMIIBSjAOBgNVHQ8BAf8E
# BAMCAYYwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFH9ZP1Qh2q1P7wXl5qPX
# LQaUEggxMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMA8GA1UdEwEB/wQFMAMB
# Af8wHwYDVR0jBBgwFoAUci06AjGQQ7kUBU7h6qfHMdEjiTQwWgYDVR0fBFMwUTBP
# oE2gS4ZJaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMv
# TWljUm9vQ2VyQXV0MjAxMV8yMDExXzAzXzIyLmNybDBeBggrBgEFBQcBAQRSMFAw
# TgYIKwYBBQUHMAKGQmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMv
# TWljUm9vQ2VyQXV0MjAxMV8yMDExXzAzXzIyLmNydDANBgkqhkiG9w0BAQwFAAOC
# AgEAFJQfOChP7onn6fLIMKrSlN1WYKwDFgAddymOUO3FrM8d7B/W/iQ6DxXsDn7D
# 5W4wMwYeLystcEqfkjz4NURRgazyMu5yRzQh4LqjA4tStTcJh1opExo7nn5PuPBY
# nbu0+THSuVHTe0VTTPVhily/piFrDo3axQ9P4C+Ol5yet+2gTfekICS5xS+cYfSI
# vgn0JksVBVMYVI5QFu/qhnLhsEFEUzG8fvv0hjgkO+lkpV9ty6GkN4vdnd7ya6Q6
# aR9y34aiM1qmxaxBi6OUnyNl6fkuun/diTFnYDLTppOkr/mg5WSfCiDVMNCxtj4w
# PKC5OmHm1DQIt/MNokbbH3UGsFP1QbzsLocuSqLCvH09Io3fDPTmscR9Y75G4qX7
# RTX8AdBPo0I6OEojf39zuFZt0qOHm65YWQE69cZM2ueE1MB05dNNgHK9gTE7zKvK
# /fg8B2qjW88MT/WF5V5uvZGtqa9FSL2RazArA+rDPuf6JGYz4HpgMZHB4S6szWSK
# YBv0VisCzfxgeU+dquXW9bd0auYlOB58DPcOYKdc3Se94g+xL4pcEhbB54JOgAkw
# YTu/9dLeH2pDqeJZAABVDWRQCaXfO5LgyKwKCLYXpigrZYCjUSBcr+Ve8PFWMhVT
# Ql0v4q8J/AUmQN5W4n101cY2L4A7GTQG1h32HHAvfQESWP0xghnGMIIZwgIBATBu
# MFcxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x
# KDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMjQCEzMAAAIc
# +s3Fm+gvfsQAAAAAAhwwDQYJYIZIAWUDBAIBBQCggZAwGQYJKoZIhvcNAQkDMQwG
# CisGAQQBgjcCAQQwLwYJKoZIhvcNAQkEMSIEIMN0xT1ITxjMpJqj05BmXrvQxDFP
# gP13EMzF6lEpxn8LMEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8AcwBv
# AGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEBBQAE
# ggEAKSOsz+IC8MJHBJLdIK6VdnjsnmAXoVIseYFcewflPbuE+0WpCo1bxlHVTYvp
# IRU01dDkYa/2I82e2iyk9Hk4ej6CdFbWmpal5adng9qyPaoIi3502dV8rZT48la8
# t4elyO9HdUYRNk/GuviyT2DgDrYovUPr4prXxupmt8Sz02+bh77QIAd8GdEvadEs
# 7lSQbJN+sVm/wJ45veqNbIMYbMCK+Y6O1o7GqNeocOmT9C+Re8/Y2zHkgS4HJleL
# PEMoAEbBy/3qJU3+KtGFTMiOVoJuqkdmzFLAYcxGWB+CVV77X/9CsRo8LnSGS3gB
# QOkNKHvupz0kPDklC55fDQ0niqGCF5YwgheSBgorBgEEAYI3AwMBMYIXgjCCF34G
# CSqGSIb3DQEHAqCCF28wghdrAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFRBgsqhkiG
# 9w0BCRABBKCCAUAEggE8MIIBOAIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFlAwQC
# AQUABCBhhxLDE/ZHmYLYo5VsCuaBE7g7Sr2yucahen3dVSaluAIGaoTEPWtzGBIy
# MDI2MDgyODE0NTUzNS4zNlowBIACAfSggdGkgc4wgcsxCzAJBgNVBAYTAlVTMRMw
# EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN
# aWNyb3NvZnQgQ29ycG9yYXRpb24xJTAjBgNVBAsTHE1pY3Jvc29mdCBBbWVyaWNh
# IE9wZXJhdGlvbnMxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVTTjo4NjAzLTA1RTAt
# RDk0NzElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaCCEe0w
# ggcgMIIFCKADAgECAhMzAAACJYDHN8bNqndJAAEAAAIlMA0GCSqGSIb3DQEBCwUA
# MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS
# ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMT
# HU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMB4XDTI2MDIxOTE5NDAwMVoX
# DTI3MDUxNzE5NDAwMVowgcsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5n
# dG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9y
# YXRpb24xJTAjBgNVBAsTHE1pY3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlvbnMxJzAl
# BgNVBAsTHm5TaGllbGQgVFNTIEVTTjo4NjAzLTA1RTAtRDk0NzElMCMGA1UEAxMc
# TWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZTCCAiIwDQYJKoZIhvcNAQEBBQAD
# ggIPADCCAgoCggIBAKbxEg/R4sDjpVwI+i++aqwiU3qqSbPkiwdaZRTSd5Sqny4b
# Fp16j5LBYELBDlqVkj8M12ld/KJktlHpdiClE8XN6kiXs4INvg20SyQkIhkORAw3
# Csf1jBTK7vUYaKCwsjF6V4e0De62hVN4eNLVvxSfA5FG2ScqTKtQCtPpmkHauh0h
# yZwty/fHfDCBiU6zQUSDkSxWtlvss1z+d3RtcOn4dM5Za6Lx6hNXAl4vFxU/zr2g
# XyWLlJTzVpra0Ynr8mx6OLP0kxbxIlcoFPYMJcw5SQKwaOic9lGp++gxIhBmC1o5
# PIAmWu+zLRNnvxesaqjKC1CKZCds4Avgo0tIK5blNkRAZMcs5AkaCCBvePmAoLvv
# z5Eg8kD6f+GYcn/HipP8dNM+hV4wJy4EpatBdHX7+lhq7cXB7S1YjIb4tbORGv9k
# 08+6lwDZhyLeqfwdH1HC9CimpI0nCfZGLpqbwBDJ9VXL8EHDS3qOmhE+PAq+5SN8
# LOlp7p247FC1DVcM308DbKX2wOSj/4BdX9I57x5rxChBy/ezcSuQb4unqGe/Do4w
# +JqfiCA2RG2C0HuujU6Kik5Rcmf1jkQ7clQBc1y4z2b7kzLVUS68bK2AAfe7GayV
# Odbdhut9rNrJIJJKdaSFo5nfeGBu5RB8fufY0UQBRz9wXN+YJBSKRaKycljLAgMB
# AAGjggFJMIIBRTAdBgNVHQ4EFgQUsTjSqhdO4wdfcB9lS7WfyfHaH3cwHwYDVR0j
# BBgwFoAUn6cVXQBeYl2D9OXSZacbUzUZ6XIwXwYDVR0fBFgwVjBUoFKgUIZOaHR0
# cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIwVGlt
# ZS1TdGFtcCUyMFBDQSUyMDIwMTAoMSkuY3JsMGwGCCsGAQUFBwEBBGAwXjBcBggr
# BgEFBQcwAoZQaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9N
# aWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcnQwDAYDVR0T
# AQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAOBgNVHQ8BAf8EBAMCB4Aw
# DQYJKoZIhvcNAQELBQADggIBAAed9zbJTKgdlu+/JUoW5eHkfHEci8hpH0lakh8h
# MmVz8qLTeO5H69yTOre2nl8Ufksvt4gVdEi6h7Ayy9Z4Wta5+utbgeGaELCSoCt8
# DULTGT4dpizY7jxhLExf2WBLWRNMhvdix+gV0Wkq6s9/adzZh3jAuD4WDCaTGR7I
# TcxQpWdrxJl5WkSOdLm5wVyTiys/ArY5EB/vQjbcYbI+GqAgpmmE1eFKxxMBCzIi
# oHkbAMx1FXksrfs19ThibG8JiHdMVgT8aHTVDrIm9/0fGIRmnBb6hSTSCu4ehuDe
# yAhHmt+BSjyXfS9SdoNgxw8AKVoUwL9BsdlJpSFZdkbU45wynSD29hA0sMSoVfaO
# Wq6/NVJLC0e2bUpOV0KNEQP6R0LJtw/Fs9qXAmKBdzUGwj0KK2dN/SWPBv02Rn8l
# Ujz8PratdfOHPgXe7SJUbPCdwZrFHEcb9e/idOumQ556mhhs0FsxZLYbWo/dePul
# V/T7ipHIConSy2NCOhU4kiZU9ZGPPk9HcOfpp1BUwEkMzqAOuPWtlMVWAK1OKOoZ
# lIbO9ekaQXe9izITpkOZr+QZ2JR7mxp4jqUfro+JZZeCrG3uzLYTO/TIiNJW/54w
# 5PZAxSJnpYJzuBW0CZel94i6z42aAW8z4hzVfnx7gj0QvhlICJ1KlZbQZlMs0LTa
# avIuMIIHcTCCBVmgAwIBAgITMwAAABXF52ueAptJmQAAAAAAFTANBgkqhkiG9w0B
# AQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNV
# BAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAG
# A1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAw
# HhcNMjEwOTMwMTgyMjI1WhcNMzAwOTMwMTgzMjI1WjB8MQswCQYDVQQGEwJVUzET
# MBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMV
# TWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1T
# dGFtcCBQQ0EgMjAxMDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOTh
# pkzntHIhC3miy9ckeb0O1YLT/e6cBwfSqWxOdcjKNVf2AX9sSuDivbk+F2Az/1xP
# x2b3lVNxWuJ+Slr+uDZnhUYjDLWNE893MsAQGOhgfWpSg0S3po5GawcU88V29YZQ
# 3MFEyHFcUTE3oAo4bo3t1w/YJlN8OWECesSq/XJprx2rrPY2vjUmZNqYO7oaezOt
# gFt+jBAcnVL+tuhiJdxqD89d9P6OU8/W7IVWTe/dvI2k45GPsjksUZzpcGkNyjYt
# cI4xyDUoveO0hyTD4MmPfrVUj9z6BVWYbWg7mka97aSueik3rMvrg0XnRm7KMtXA
# hjBcTyziYrLNueKNiOSWrAFKu75xqRdbZ2De+JKRHh09/SDPc31BmkZ1zcRfNN0S
# idb9pSB9fvzZnkXftnIv231fgLrbqn427DZM9ituqBJR6L8FA6PRc6ZNN3SUHDSC
# D/AQ8rdHGO2n6Jl8P0zbr17C89XYcz1DTsEzOUyOArxCaC4Q6oRRRuLRvWoYWmEB
# c8pnol7XKHYC4jMYctenIPDC+hIK12NvDMk2ZItboKaDIV1fMHSRlJTYuVD5C4lh
# 8zYGNRiER9vcG9H9stQcxWv2XFJRXRLbJbqvUAV6bMURHXLvjflSxIUXk8A8Fdsa
# N8cIFRg/eKtFtvUeh17aj54WcmnGrnu3tz5q4i6tAgMBAAGjggHdMIIB2TASBgkr
# BgEEAYI3FQEEBQIDAQABMCMGCSsGAQQBgjcVAgQWBBQqp1L+ZMSavoKRPEY1Kc8Q
# /y8E7jAdBgNVHQ4EFgQUn6cVXQBeYl2D9OXSZacbUzUZ6XIwXAYDVR0gBFUwUzBR
# BgwrBgEEAYI3TIN9AQEwQTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNyb3Nv
# ZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRtMBMGA1UdJQQMMAoGCCsG
# AQUFBwMIMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAP
# BgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNX2VsuP6KJcYmjRPZSQW9fOmhjE
# MFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kv
# Y3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNybDBaBggrBgEF
# BQcBAQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9w
# a2kvY2VydHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3J0MA0GCSqGSIb3DQEB
# CwUAA4ICAQCdVX38Kq3hLB9nATEkW+Geckv8qW/qXBS2Pk5HZHixBpOXPTEztTnX
# wnE2P9pkbHzQdTltuw8x5MKP+2zRoZQYIu7pZmc6U03dmLq2HnjYNi6cqYJWAAOw
# Bb6J6Gngugnue99qb74py27YP0h1AdkY3m2CDPVtI1TkeFN1JFe53Z/zjj3G82jf
# ZfakVqr3lbYoVSfQJL1AoL8ZthISEV09J+BAljis9/kpicO8F7BUhUKz/AyeixmJ
# 5/ALaoHCgRlCGVJ1ijbCHcNhcy4sa3tuPywJeBTpkbKpW99Jo3QMvOyRgNI95ko+
# ZjtPu4b6MhrZlvSP9pEB9s7GdP32THJvEKt1MMU0sHrYUP4KWN1APMdUbZ1jdEgs
# sU5HLcEUBHG/ZPkkvnNtyo4JvbMBV0lUZNlz138eW0QBjloZkWsNn6Qo3GcZKCS6
# OEuabvshVGtqRRFHqfG3rsjoiV5PndLQTHa1V1QJsWkBRH58oWFsc/4Ku+xBZj1p
# /cvBQUl+fpO+y/g75LcVv7TOPqUxUYS8vwLBgqJ7Fx0ViY1w/ue10CgaiQuPNtq6
# TPmb/wrpNPgkNWcr4A245oyZ1uEi6vAnQj0llOZ0dFtq0Z4+7X6gMTN9vMvpe784
# cETRkPHIqzqKOghif9lwY1NNje6CbaUFEMFxBmoQtB1VM1izoXBm8qGCA1AwggI4
# AgEBMIH5oYHRpIHOMIHLMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv
# bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
# aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMScwJQYD
# VQQLEx5uU2hpZWxkIFRTUyBFU046ODYwMy0wNUUwLUQ5NDcxJTAjBgNVBAMTHE1p
# Y3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2WiIwoBATAHBgUrDgMCGgMVAFNv5so4
# 8CMIF+WHPDkRcG5JbF4OoIGDMIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgT
# Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m
# dCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENB
# IDIwMTAwDQYJKoZIhvcNAQELBQACBQDuO8dYMCIYDzIwMjYwODI4MDgzNzQ0WhgP
# MjAyNjA4MjkwODM3NDRaMHcwPQYKKwYBBAGEWQoEATEvMC0wCgIFAO47x1gCAQAw
# CgIBAAICGFkCAf8wBwIBAAICFIAwCgIFAO49GNgCAQAwNgYKKwYBBAGEWQoEAjEo
# MCYwDAYKKwYBBAGEWQoDAqAKMAgCAQACAwehIKEKMAgCAQACAwGGoDANBgkqhkiG
# 9w0BAQsFAAOCAQEAFrhFo9qD7w7O9jM3PXO5wJfgW221wJM+dVaDqLzlm0AcYHZn
# 1vuLJku24NWwrC97hlCLedTpzLMzLRde/M1wuIGkV6HFsR4zxb08ItPuKaHs45Vi
# WKJrKH9Uj79PcKD46T7NkYj/uF+raeci9jDuIqnaFNfMN/W+7ptb8z7L9BAwoYFz
# lU89D/U2L/rJX0B+y8n9fFHkprL+i72KxceZ40NuPlI8ul/QRkF3BdYAmD/wrOI6
# gvKW+5PV/IAmO8BF/FL9+6hdL1pWLz8vWCm8RN5IzwRL6Bx3ZDvMpP7TLGRrSZRp
# oSulwpN2ZX/I6vigdbRYn23SMMVu+M3W6ucXTDGCBA0wggQJAgEBMIGTMHwxCzAJ
# BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k
# MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jv
# c29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAACJYDHN8bNqndJAAEAAAIlMA0G
# CWCGSAFlAwQCAQUAoIIBSjAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwLwYJ
# KoZIhvcNAQkEMSIEIKQHZ4hjVyKE76GwOF+Pb5wLX+ZxCIv9BKPh3UMJ+pL+MIH6
# BgsqhkiG9w0BCRACLzGB6jCB5zCB5DCBvQQgVg3uiHo43fL3YKYCX+UXQJjCuNZZ
# A/p0JTFqM9IcoRAwgZgwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2Fz
# aGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv
# cnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAx
# MAITMwAAAiWAxzfGzap3SQABAAACJTAiBCCU+by/RYxP1l4F2hGzPMgUN+cKrkCD
# 3BTa3RpY53rIQzANBgkqhkiG9w0BAQsFAASCAgBmMP+mypYmUQzCCh4njkwycElM
# Fx4yB1cS7w1upaKBRDn6exEpk25I8oGgRpGLvmlq/f+KPInqfsn6XkY9Bn0nuZ7H
# GDG0nqLjOCluGN8GVTvtJtSe89ADoJJinRBFlgxChHmcza7+W7gBsD3X5e4TDxLe
# p3SHQnctwtnXWSPStN7FKDzvO4L9wyda6EXHmh6tzSzHtyPUjrotE2jmKaA+ALXr
# lpNLk2OeRrvJBJIDt7yhVz8DLlKUX8dPhIFhH3Jlp+CuLfTunL4W8F8kKg8DE5AB
# +PMTnKod4DjOcU0kH+FnKofnS/otYrFn0pMSbRfQYueWFJtHea+TTc9bfrU0Y8VJ
# ArgSQ2rLqi/f7QVLnXRc9wBIU6ZK2kV3UfuAViCDobXuCJRcsgR+oMAude/Ip5y1
# No8/Vn0wxCdn/DeYz4EfOT6MXCZvwipzzmqSFTcdzyDbFxuHWR7FrEeC+PnT9tKK
# armFAk6BdfmE37HpzhdiIFSRFKiNHlQrF2ofxGTl1a+skuShSs0Z4XsmSrcQ0c0G
# tbVKJb4PAUfr8U/XuQ9XwzaVhvK51hm6eXXeGEWWuw/6K/JXKySal4hYsXURy6Ti
# pzOIXlNnzQvmvfBZfjMeWbY5numQFEhiGmPaz3N6nzPbn8HPC24uGwckvbLF1QTI
# i0MpRrev5vtpwaF2JA==
# SIG # End signature block