0

I'm trying to use SslStream to connect to a website to pass a request, but I'm getting the following IOException:

Unable to read data from the transport connection: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.

In order to make testing this more efficient i created a standalone program and copied the client code example code from here: http://msdn.microsoft.com/en-us/library/system.net.security.sslstream(v=vs.110).aspx and then passed in the request based on the other party's API.

            string Request = "The Request";
            TcpClient client = new TcpClient();
            client.ReceiveTimeout = 10000; //10 seconds
            SslStream sslStream;
            string server = "ssl.website.com";
            client.Connect(server, 12345);
            sslStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null );

            sslStream.AuthenticateAsClient(server,null, SslProtocols.Tls12, false);

            StringBuilder messageData = new StringBuilder();
            byte[] len = BitConverter.GetBytes(SslClient.GetLen(Request));

            messageData.AppendLine("Writing length of data " + SslClient.GetLen(Request).ToString());
            sslStream.Write(len);
            byte[] msg = Encoding.UTF8.GetBytes(Request);

            sslStream.Write(msg);
            sslStream.Flush();

            byte[] buffer = new byte[2048];

            messageData.AppendLine("Writing data " + System.Text.Encoding.UTF8.GetString(msg));
            messageData.AppendLine("Is Authenticated? " + sslStream.IsAuthenticated.ToString());
            int bytes = -1;

            try
            {
                do
                {
                    bytes = sslStream.Read(buffer, 0, buffer.Length);

                    Decoder decoder = Encoding.UTF8.GetDecoder();
                    char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
                    decoder.GetChars(buffer, 0, bytes, chars, 0);
                    messageData.AppendLine(chars.ToString());

                    if (messageData.ToString().IndexOf("<EOF>") != -1)
                    {
                        break;
                    }

                } while (bytes != 0);
            }
            catch(Exception ex)
            {
                messageData.AppendLine(ex.Message);
            }

            return messageData.ToString();
        }


        public static bool ValidateServerCertificate(
              object sender,
              X509Certificate certificate,
              X509Chain chain,
              SslPolicyErrors sslPolicyErrors)
        {
            if (sslPolicyErrors == SslPolicyErrors.None)
                return true;
            return false;
        }

        public static Int16 GetLen(string Request)
        {
            return Convert.ToInt16(Encoding.UTF8.GetBytes(Request).Length);

        }

The part where it's failing is sslStream.Read(buffer, 0, buffer.Length). This never returns and is where the IOException is coming from.

The people i'm trying to connect to say that the SSL handshake is failing, but I don't see any indication of that on our end. It always makes it to sslStread.Read and then fails. They've said sometimes they are receiving the request and sending the response, but I haven't yet seen a response returned.

Thanks

  • Please inline sample in your post and explain why you can't use existing `WebClient`/`HttpWebRequest` classes. – Alexei Levenkov Jun 25 '14 at 20:28
  • Ok, i added the code. It's pretty much just copying that MSDN example. Should I be using WebClient / HttpWebRequest? –  Jun 25 '14 at 20:41
  • Unless you have strong reason to go with such low level API as `SslStream` I'd recommend using `WebClient` to send web requests. For debugging your code - chekc port/dns are correct and see if ValidateServerCertificate get called. – Alexei Levenkov Jun 25 '14 at 21:08
  • I verified that validateServerCertificate is getting called. It results in SslPolicyErrors.None, so no problems. I just tried using WebClient without success. It times out. I will put my code for that above. –  Jun 25 '14 at 22:15
  • Code looks fine. There is likely not code related problem with the service. Not sure what next steps you should take. – Alexei Levenkov Jun 25 '14 at 23:14
  • Thanks for your help. I think i need to ask the partner for working sample code, since they *must* have tested it at some point. Ill try to remember to post an update here with the solution when i find one. –  Jun 26 '14 at 12:50
  • Your solution should be posted as an answer, not as an edit to your question. – Trisped Jun 27 '14 at 16:47
  • Ok, i moved it as an answer. thanks! –  Jun 27 '14 at 20:39

1 Answers1

0

After some testing sessions with the partner it turned out to be a simple bug in my code. The length bytes had to be flipped to the network byte order. I did this using IPAddress.HostToNetworkOrder

            byte[] len = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(SslClient.GetLen(Request)));

            messageData.AppendLine("Writing length of data " + SslClient.GetLen(Request).ToString());
            sslStream.Write(len);