KEMBAR78
Regression: NSUrlSessionHandler.ServerCertificateCustomValidationCallback behavior change · Issue #23764 · dotnet/macios · GitHub
Skip to content

Regression: NSUrlSessionHandler.ServerCertificateCustomValidationCallback behavior change #23764

@dotMorten

Description

@dotMorten

Apple platform

iOS

Framework version

net9.0-*

Affected platform version

9.0.300

Description

The ServerCertificateCustomValidationCallback has started returning a new value for SslPolicyErrors for the test code provided below.

Steps to Reproduce

Repro method. This used to pass and match behavior of HttpClientHandler and SocketsHttpHandler.

        [TestMethod]
        public async Task RemoteCertificate_ForceFailure()
        {
            // Verifies that the default certificate validator is called for a normal request, and that it can be forced to fail
            int calls = 0;
            Exception callbackAssertFail = null;

#if __IOS__
            var handler = new NSUrlSessionHandler();
            handler.ServerCertificateCustomValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
#else
            var handler = new System.Net.Http.SocketsHttpHandler();
            handler.SslOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
#endif
            {
                Interlocked.Increment(ref calls);
                try
                {
                    Assert.AreEqual(SslPolicyErrors.None, sslPolicyErrors, "sslPolicyErrors"); // Fails on iOS since 9.0.300. Now returns `RemoteCertificateChainErrors`
                }
                catch (Exception ex)
                {
                    callbackAssertFail = ex;
                }
                return false;
            };

            var client = new HttpClient(handler);
            // Disable keep-alive and cache to force reconnection for each request
            client.DefaultRequestHeaders.ConnectionClose = true;
            client.DefaultRequestHeaders.CacheControl = new CacheControlHeaderValue { NoCache = true, NoStore = true };

            var responseTask = client.GetAsync(new Uri("https://sha256.badssl.com/")); // valid certificate
            try { await responseTask; }
            catch (HttpRequestException) { /* expected */ }
            
            // Expect our validator to be called once
            Assert.AreEqual(1, calls, "numCalls");
            if (callbackAssertFail != null)
            {
                throw callbackAssertFail;
            }
        }

Did you find any workaround?

No

Relevant logs

No response

Metadata

Metadata

Assignees

Labels

enhancementThe issue or pull request is an enhancement

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions