ms81
ms81

Reputation: 31

Client / Server Handshake fails using RestSharp, but works fine on Postman and when using Fiddler as proxy. Certificate length 0

This is my very first post. Firstly, I would like to thank everybody for all the contribution you have made to this site, as this made my work as a junior dev so much easier!

I have a problem with server handshake using RestSharp. I am adding certificate to RestSharp POST request, but it seems not to validate it properly. However exactly same post request with certificate added to Postman or running same code via Fiddler as a proxy seems to work fine.

I receive error: Error: System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel.

I am completely lost. I replaced information I did not want to share with xxxxxxxxxx.

            ServicePointManager.DefaultConnectionLimit = 9999;
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            ServicePointManager.ServerCertificateValidationCallback +=
               (sender, certificate, chain, sslPolicyErrors) => true;

            var client = new RestClient("xxxxxxxxxxxxxxxxxxx");


            X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
            store.Open(OpenFlags.ReadOnly);
            X509Certificate2Collection collection = store.Certificates.Find(X509FindType.FindBySubjectName, "xxxxxxxxx", true);

            client.ClientCertificates = new X509CertificateCollection();
            client.ClientCertificates.AddRange(collection);
            client.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;


            var request = new RestRequest(Method.POST);
            request.AddHeader("X-IBM-Client-Id", "xxxxxxxxxxxxxxx");
            request.AddHeader("X-IBM-Client-Secret", "xxxxxxxxxxxxxxxxxxxxxxxx");
            request.AddHeader("Accept", "*/*");
            request.AddHeader("Content-Type", "application/json");

            var jsonToSend = JsonConvert.SerializeObject(requestBody);
            request.AddParameter("application/json; charset=utf-8", jsonToSend, ParameterType.RequestBody);
            request.RequestFormat = DataFormat.Json;


            SecurityShower.ShowRestSharpRequest(client, request);

            IRestResponse response = client.Execute(request);


            return String.IsNullOrEmpty(response.Content) ? response.ErrorMessage : response.Content;

I run Wireshark and found out that during handshake client (us) sends certfifcate lenght 0, so I take certificate is not included despite you can clearly see I added cert to RestSharp client. And it shows when I debug.

Please have a look at Wireshark snapshots:

wireshark snapshot 1

wireshark snapshot 2

I think it all comes down to how the Fiddler and Postman handle their handshake and cert. But it is still a mystery (or misery for that matter!) to me why .Net handles the process differently to those apps!

EDIT: Additional info.

I have added this code:

ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(ValidateServerCertificate);

(...)

  public static bool ValidateServerCertificate(
            object sender,
            X509Certificate certificate,
            X509Chain chain,
            SslPolicyErrors sslPolicyErrors)
        {

            Console.WriteLine("Validation of server cert.");
                return true;

}

And I discovered that this piece of code is not executed.

Anyway - I am not sure how to go deeper into abstraction using .net, I do not know how to programmatically influance handshake procedure... or if it is even possible in .net... :(

Upvotes: 2

Views: 2288

Answers (1)

ms81
ms81

Reputation: 31

After the response from server side people we found out my program was written correctly. The issue (apart from poor communication from API provider!) was our certificate which the server was unable to consume. I was sending self-signed cert to the server running some old version of Windows Server. I was told the certificate I have been using is correct, however the Server, during handshake, was sending Trusted Certificate List which my cert could not match so my .Net written program was sending certificate length 0. Which is consistent with TLS 1.2 protocol. After uploading certificate chain that included certificate that matched one of authorities from trusted certificate list provided by server connection was established and all works as intended.

Thank you for all the answers and happy coding!

Upvotes: 1

Related Questions