Unable to read data from the transport connection - C# port from python

0

I am trying to port this python web client to C# .NET Core 3.1. I'm running on Windows 10x64 (build 19041). The linked github project contains a (secure) test web server sandbox you can develop against together with some client and server test self-cert certificates.

I am not very familiar with python (or SSL/TLS for that matter), but I can

  1. run the test suites which are included in the project - which involved starting and stopping the test server included.
  2. start up the test server and then cUrl it successfully with the included client certificates/keys/etc (so long as I instruct cUrl not to check certificate revocation)

If I run a python utility (sslyze) against the test server it indicates that it supports TLS1.3.

I have

  1. imported the client.cert.pem into my personal certificate store and the ca.cert.pem into the trusted root certificate authority. (I wasn't sure if this was correct and perhaps I needed to unpack them, but they appear to have been imported successfully)

  2. Added the following registry keys

    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Client] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001

    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Client] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001

    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001

    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.3\Client] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001

When I try and run the C# code, I get the

"IOException: Unable to read data from the transport connection"

error on the response.Result line.

I'm struggling to make any headway, now.

I'd be really grateful for any pointers as to where to look next. Many thx IA.

Here's my code

class Program
{
    
    private const string Thumbprint = "37af35e3f13c65ea0d7bbad148332924a1ce41d7";
    private const string MailBox = "alice";
    private const int Port = 8000;
    private const string BaseAddress = "127.0.0.1";
    
    private static HttpClient _client = null;

    public static void Main(string[] args)
    { 
        ConfigureHttpClient();
        var response = Handshake();

        Console.WriteLine($"Handshake succeeded: {response.StatusCode == HttpStatusCode.OK}");           
    }

    private static HttpResponseMessage Handshake()
    {
        var uri = new Uri($"https://{BaseAddress}:{Port}/messageexchange/{MailBox}");
        var response = _client.PostAsync(uri, null);            
        return response.Result;
    }

    private static void ConfigureHttpClient()
    {
        var handler = new HttpClientHandler
        {
            ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; },                 
            CheckCertificateRevocationList = false,                
            SslProtocols = SslProtocols.Tls13
                           | SslProtocols.Tls12
                           | SslProtocols.Tls11
                           | SslProtocols.Tls
        };
        var certificate = GetCertificateByThumbprint(Thumbprint);
        handler.ClientCertificates.Add(certificate);
        _client = new HttpClient(handler);                      
    }

    //Returns a certificate by searching through all likely places
    private static X509Certificate2 GetCertificateByThumbprint(string thumbprint)
    {
        X509Certificate2 certificate;
        //foreach likely certificate store name
        foreach (var name in new[] { StoreName.My, StoreName.Root })
        {
            //foreach store location
            foreach (var location in new[] { StoreLocation.CurrentUser, StoreLocation.LocalMachine })
            {
                //see if the certificate is in this store name and location
                certificate = FindThumbprintInStore(thumbprint, name, location);
                if (certificate != null)
                {
                    //return the resulting certificate
                    return certificate;
                }
            }
        }
        //certificate was not found
        throw new Exception(string.Format("The certificate with thumbprint {0} was not found", thumbprint));
    }

    private static X509Certificate2 FindThumbprintInStore(string thumbprint,
                                                          StoreName name, StoreLocation location)
    {
        //creates the store based on the input name and location e.g. name=My
        var certStore = new X509Store(name, location);
        certStore.Open(OpenFlags.ReadOnly);
        //finds the certificate in question in this store
        var certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint,
                                                         thumbprint, false);
        certStore.Close();

        if (certCollection.Count > 0)
        {
            //if it is found return
            return certCollection[0];
        }
        else
        {
            //if the certificate was not found return null
            return null;
        }
    }
}

Here's the full error stack

System.AggregateException HResult=0x80131500 Message=One or more errors occurred. (An error occurred while sending the request.)
Source=System.Private.CoreLib StackTrace: at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions) at System.Threading.Tasks.Task1.GetResultCore(Boolean waitCompletionNotification) at System.Threading.Tasks.Task1.get_Result() at IfxMeshClient.Program.Handshake() in C:\Users...\IfxMeshClient\Program.cs:line 41 at IfxMeshClient.Program.Main(String[] args) in C:\Users...\IfxMeshClient\Program.cs:line 32

Inner Exception 1: HttpRequestException: An error occurred while sending the request.

Inner Exception 2: IOException: Unable to read data from the transport connection: An established connection was aborted by the software in your host machine..

Inner Exception 3: SocketException: An established connection was aborted by the software in your host machine.

EDIT: I just wanted to add the output from sslyze as I wondered if it could be a cipher mismatch, but these ciphers appear to be available on my version of win10.

* TLS 1.3 Cipher Suites:
     Attempted to connect using 5 cipher suites.
     The server accepted the following 3 cipher suites:
        TLS_CHACHA20_POLY1305_SHA256                      256       ECDH: X25519 (253 bits)
        TLS_AES_256_GCM_SHA384                            256       ECDH: X25519 (253 bits)
        TLS_AES_128_GCM_SHA256                            128       ECDH: X25519 (253 bits)
     The group of cipher suites supported by the server has the following properties:
       Forward Secrecy                    OK - Supported
       Legacy RC4 Algorithm               OK - Not Supported
     The server is configured to prefer the following cipher suite:
        TLS_AES_256_GCM_SHA384                            256       ECDH: X25519 (253 bits) 

EDIT1: Not quite sure what to make of Fiddler output. I'm not sure if it confuses things since it refers to TLS12 and then suggests supported versions are TLS13

CONNECT 127.0.0.1:52985 HTTP/1.1
Host: 127.0.0.1:52985

A SSLv3-compatible ClientHello handshake was found. Fiddler extracted the parameters below.

Version: 3.3 (TLS/1.2)
Random: F7 09 8F A8 9A 72 AF 33 93 29 90 48 E4 A2 E2 09 CE BD 7E 27 94 0A C9 53 D4 54 6C 35 0B DF E2 E9
"Time": 12/08/2059 21:41:27
SessionID: empty
Extensions: 
    supported_versions  Tls1.3
    signature_algs  rsa_pss_rsae_sha256, rsa_pss_rsae_sha384, rsa_pss_rsae_sha512, rsa_pkcs1_sha256, rsa_pkcs1_sha384, rsa_pkcs1_sha1, ecdsa_secp256r1_sha256, ecdsa_secp384r1_sha384, ecdsa_sha1, dsa_sha1, rsa_pkcs1_sha512, ecdsa_secp521r1_sha512
    supported_groups    x25519 [0x1d], secp256r1 [0x17], secp384r1 [0x18]
    key_share   00 24 00 1D 00 20 95 34 AC 4A A5 6C D8 24 CD 50 29 2E F8 27 B4 59 D7 2C D8 C0 79 7B 14 79 B2 E8 28 6F 36 DE D4 48
    post_handshake_auth
    extended_master_secret  empty
    renegotiation_info  00
    psk_key_exchange_modes  01 01
Ciphers: 
    [1302]  TLS_AES_256_GCM_SHA384
    [1301]  TLS_AES_128_GCM_SHA256
    ...

and the response was

HTTP/1.1 200 Connection Established
FiddlerGateway: Direct
StartTime: 13:21:35.087
Connection: close

fiddler.network.https> HTTPS handshake to 127.0.0.1 (for #6) failed. System.Security.Authentication.AuthenticationException A call to SSPI failed, see inner exception. < The message received was unexpected or badly formatted

Win32 (SChannel) Native Error Code: 0x80090326

Further the combination of the fiddler output as well as the sslyze output would seem to indicate there are common ciphers as well

TLS_AES_256_GCM_SHA384
TLS_AES_128_GCM_SHA256
python
c#
ssl
.net-core
asked on Stack Overflow Nov 13, 2020 by Simon Woods • edited Nov 13, 2020 by Simon Woods

1 Answer

0

Just to say that, my issue appears to have have been that although I had imported the pem into the certificate store, I had not created a pfx which incorporated the private key file.

See this SO post - Convert a CERT/PEM certificate to a PFX certificate

Having done that I did get more response from the server but was still getting an Http 403 and the underlying error was

Cannot determine the frame size or a corrupted frame was received

According to this post .NET 4.8 TLS 1.3 Issue on Windows 10, it may be an ongoing issue.

answered on Stack Overflow Nov 13, 2020 by Simon Woods

User contributions licensed under CC BY-SA 3.0