{"action":"created","issue":{"url":"https://api.github.com/repos/dotnet/corefx/issues/38219","repository_url":"https://api.github.com/repos/dotnet/corefx","labels_url":"https://api.github.com/repos/dotnet/corefx/issues/38219/labels{/name}","comments_url":"https://api.github.com/repos/dotnet/corefx/issues/38219/comments","events_url":"https://api.github.com/repos/dotnet/corefx/issues/38219/events","html_url":"https://github.com/dotnet/corefx/issues/38219","id":452172560,"node_id":"MDU6SXNzdWU0NTIxNzI1NjA=","number":38219,"title":"HttpClient that uses client certificate without access to private key hangs indefinitely","user":{"login":"maciejw","id":336719,"node_id":"MDQ6VXNlcjMzNjcxOQ==","avatar_url":"https://avatars0.githubusercontent.com/u/336719?v=4","gravatar_id":"","url":"https://api.github.com/users/maciejw","html_url":"https://github.com/maciejw","followers_url":"https://api.github.com/users/maciejw/followers","following_url":"https://api.github.com/users/maciejw/following{/other_user}","gists_url":"https://api.github.com/users/maciejw/gists{/gist_id}","starred_url":"https://api.github.com/users/maciejw/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/maciejw/subscriptions","organizations_url":"https://api.github.com/users/maciejw/orgs","repos_url":"https://api.github.com/users/maciejw/repos","events_url":"https://api.github.com/users/maciejw/events{/privacy}","received_events_url":"https://api.github.com/users/maciejw/received_events","type":"User","site_admin":false},"labels":[{"id":497898703,"node_id":"MDU6TGFiZWw0OTc4OTg3MDM=","url":"https://api.github.com/repos/dotnet/corefx/labels/area-System.Net.Http","name":"area-System.Net.Http","color":"d4c5f9","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":5,"created_at":"2019-06-04T19:40:25Z","updated_at":"2019-06-06T10:01:05Z","closed_at":null,"author_association":"NONE","body":"I have a project that uses MIcrosoft.NETCore.App 2.2.0 and 2.1.0, a console app, it uses http clinet with client certificate to authenticate. \r\n\r\n```cs\r\nusing System;\r\nusing System.Linq;\r\nusing System.Net.Http;\r\nusing System.Net.Security;\r\nusing System.Security.Cryptography.X509Certificates;\r\nusing System.Threading.Tasks;\r\n\r\nnamespace ClientCertificatesTests\r\n{\r\n    class Program\r\n    {\r\n        public static async Task Main(string[] args)\r\n        {\r\n            using (var handler = GetHttpHandler(\"some-thumbprint\"))\r\n            {\r\n                using (var client = new HttpClient(handler))\r\n                {\r\n                    try\r\n                    {\r\n                        var response = await client.GetAsync(\"https://some-server/some-endpoint\");\r\n\r\n                        Console.WriteLine(response.StatusCode);\r\n\r\n                    }\r\n                    catch (Exception ex)\r\n                    {\r\n                        Console.WriteLine(ex);\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n        static HttpMessageHandler GetHttpHandler(string thumbPrint)\r\n        {\r\n            X509Certificate2 clientCertificate = GetCertificate(thumbPrint);\r\n\r\n            var handler = new SocketsHttpHandler\r\n            {\r\n                SslOptions = new SslClientAuthenticationOptions\r\n                {\r\n                    ClientCertificates = new X509CertificateCollection\r\n                    {\r\n                        clientCertificate\r\n                    },\r\n                }\r\n            };\r\n\r\n            return handler;\r\n        }\r\n\r\n        static X509Certificate2 GetCertificate(string thumbPrint)\r\n        {\r\n            using (X509Store certStore = new X509Store(StoreName.My, StoreLocation.LocalMachine))\r\n            {\r\n                certStore.Open(OpenFlags.ReadOnly);\r\n                var certificateCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, thumbPrint, false);\r\n\r\n                var certificate = certificateCollection.OfType<X509Certificate2>().FirstOrDefault();\r\n\r\n                if (certificate == null)\r\n                {\r\n                    throw new Exception(\"Missing certificate\");\r\n                }\r\n\r\n                return certificate;\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\n```\r\n\r\nCertificate is located in local machine personal store. When my user does not have access to private key (run from not elevated command prompt), Win32Exception is thrown with message \"The credentials supplied to the package were not recognized\" from https://github.com/dotnet/corefx/blob/3c30357d51b96339021b4ee52f38445c31248bb2/src/Common/src/Interop/Windows/SspiCli/SSPIWrapper.cs#L136, but this exception is not propagated to task and there is no continuation called, my catch block is not executed, process hangs indefinitely. \r\nThis is just an real life example, from my observation it is not specifically related to this exception, any exception thrown during that phase of ssl handshake is swallowed this way.\r\n\r\nI can even force this behavior from my code with this with this setup:\r\n```cs\r\n\r\n            var i = 0;\r\n            var handler = new SocketsHttpHandler\r\n            {\r\n                SslOptions = new SslClientAuthenticationOptions\r\n                {\r\n                    LocalCertificateSelectionCallback = (sender, targetHost, localCertificates, remoteCertificate, acceptableIssuers) =>\r\n                    {\r\n                        i++;\r\n                        if (i == 2)\r\n                            throw new Exception(\"This will hang forever!!!\");\r\n                        return localCertificates[0];\r\n                    },\r\n                    ClientCertificates = new X509CertificateCollection {\r\n                        clientCertificate\r\n                    },\r\n                }\r\n            };\r\n```\r\n\r\nThis i variable is required because my server is trying renegotiate connection and this problem will manifest itself during second local certificate selection only.\r\n\r\n\r\n"},"comment":{"url":"https://api.github.com/repos/dotnet/corefx/issues/comments/499431680","html_url":"https://github.com/dotnet/corefx/issues/38219#issuecomment-499431680","issue_url":"https://api.github.com/repos/dotnet/corefx/issues/38219","id":499431680,"node_id":"MDEyOklzc3VlQ29tbWVudDQ5OTQzMTY4MA==","user":{"login":"maciejw","id":336719,"node_id":"MDQ6VXNlcjMzNjcxOQ==","avatar_url":"https://avatars0.githubusercontent.com/u/336719?v=4","gravatar_id":"","url":"https://api.github.com/users/maciejw","html_url":"https://github.com/maciejw","followers_url":"https://api.github.com/users/maciejw/followers","following_url":"https://api.github.com/users/maciejw/following{/other_user}","gists_url":"https://api.github.com/users/maciejw/gists{/gist_id}","starred_url":"https://api.github.com/users/maciejw/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/maciejw/subscriptions","organizations_url":"https://api.github.com/users/maciejw/orgs","repos_url":"https://api.github.com/users/maciejw/repos","events_url":"https://api.github.com/users/maciejw/events{/privacy}","received_events_url":"https://api.github.com/users/maciejw/received_events","type":"User","site_admin":false},"created_at":"2019-06-06T10:01:05Z","updated_at":"2019-06-06T10:01:05Z","author_association":"NONE","body":"Sure I can, I've downloaded 3.0.0-preview5-27626-15, retargeted my project and exception is propagated correctly, this one from code snippet I've provided here as well as security exception related to certificates\r\n\r\n```\r\nSystem.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.IO.IOException: The read operation failed, see inner exception. ---> System.ComponentModel.Win32Exception: The credentials supplied to the package were not recognized\r\n   at System.Net.SSPIWrapper.AcquireCredentialsHandle(SSPIInterface secModule, String package, CredentialUse intent, SCHANNEL_CRED scc)\r\n   at System.Net.Security.SslStreamPal.AcquireCredentialsHandle(CredentialUse credUsage, SCHANNEL_CRED secureCredential)\r\n   at System.Net.Security.SslStreamPal.AcquireCredentialsHandle(X509Certificate certificate, SslProtocols protocols, EncryptionPolicy policy, Boolean isServer)\r\n   at System.Net.Security.SecureChannel.AcquireClientCredentials(Byte[]& thumbPrint)\r\n   at System.Net.Security.SecureChannel.GenerateToken(Byte[] input, Int32 offset, Int32 count, Byte[]& output)\r\n   at System.Net.Security.SecureChannel.NextMessage(Byte[] incoming, Int32 offset, Int32 count)\r\n   at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)\r\n   at System.Net.Security.SslStream.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)\r\n   at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)\r\n   at System.Net.Security.SslStream.PartialFrameCallback(AsyncProtocolRequest asyncRequest)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Net.Security.SslStream.ThrowIfExceptional()\r\n   at System.Net.Security.SslStream.CheckThrow(Boolean authSuccessCheck, Boolean shutdownCheck)\r\n   at System.Net.Security.SslStream.CheckOldKeyDecryptedData(Memory`1 buffer)\r\n   at System.Net.Security.SslStream.HandleQueuedCallback(Object& queuedStateRequest)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Net.Security.SslStream.ReadAsyncInternal[TReadAdapter](TReadAdapter adapter, Memory`1 buffer)\r\n   --- End of inner exception stack trace ---\r\n   at System.Net.Security.SslStream.ReadAsyncInternal[TReadAdapter](TReadAdapter adapter, Memory`1 buffer)\r\n   at System.Net.Http.HttpConnection.FillAsync()\r\n   at System.Net.Http.HttpConnection.ReadNextResponseHeaderLineAsync(Boolean foldedHeadersAllowed)\r\n   at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)\r\n   --- End of inner exception stack trace ---\r\n   at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)\r\n   at System.Net.Http.HttpConnectionPool.SendWithNtConnectionAuthAsync(HttpConnection connection, HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)\r\n   at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)\r\n   at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)\r\n   at DiagnosticListenerTests.Program.CallCustom(HttpClient tokenClient, String Address, String ClientId, String Scope) in C:\\Source\\tests\\....\\Program.cs:line 148\r\n\r\n```\r\n\r\nwitch was my original problem I stumbled upon. \r\n\r\n\r\n"}}
{"actor":{"display_login":"maciejw"}}