.NET Framework Bookmark and Share   
 index > .NET Framework Networking and Communication > Connecting to SSL Tcp Server getting RemoteCertificateChainErrors
 

Connecting to SSL Tcp Server getting RemoteCertificateChainErrors

hi,

I am using the example code for SslTcpServer from the msdn with openssl. I took the following steps to set up things :

  1. Create a Private Key using the openssl command : openssl genrsa -out privkey.pem 2048
  2. Create a certificate using the open ssl command: openssl req -newkey rsa:1024 -nodes -x509 -keyout privkey.pem -out cacert.pem -days 365 -config openssl.cnf
  3. Convert the certificate to PKCS#12 format using openssl command (where I specify the certificate name as TESTCERT) : openssl pkcs12 -export -in cacert.crt -inkey privkey.key -out bundle.p12
  4. Launch MMC and import the bundle.p12 into the Personal store (With the "make keys exportable" selected and NO PASSWORD). And now I can see the TESTCERT in the Personal store.
  5. I then export the certificate with the private key to a .pfx file (although I never use it)
  6. Run the server (example code from msdn ) passing it the certificate name as parameter from command line (See the simple Server code below): SslTcpServer.exe bundle.p12 (The server starts successfully and waits for client connections) NOTE: Client authentication set to FALSE
  7. Run the client (example code from msdn ) on a different machine to connect to the SSL server (See simple client code below) from command line: SslTcpClient.exe TESTCERT
PROBLEM : When I try to connect to the server using the openssl client : openssl s_client -connect 192.168.0.1:47935, it works fine. But when I try the Windows client (code below) it says :

>SslTcpClient.exe 192.168.0.1 TESTCERT
Client connected.
Certificate error: RemoteCertificateChainErrors
Exception: The remote certificate is invalid according to the validation procedure.
Authentication failed - closing the connection.


SERVER CODE (from MSDN)
using System;<br/>
using System.Collections;<br/>
using System.Net;<br/>
using System.Net.Sockets;<br/>
using System.Net.Security;<br/>
using System.Security.Authentication;<br/>
using System.Text;<br/>
using System.Security.Cryptography.X509Certificates;<br/>
using System.IO;<br/>
<br/>
namespace Enable<br/>
{<br/>
    public sealed class SslTcpServer<br/>
    {<br/>
        static X509Certificate serverCertificate = null;<br/>
        // The certificate parameter specifies the name of the file <br/>
        // containing the machine certificate.<br/>
        public static void RunServer(string certificate)<br/>
        {<br/>
            serverCertificate = X509Certificate.CreateFromCertFile(certificate);<br/>
            // Create a TCP/IP (IPv4) socket and listen for incoming connections.<br/>
            TcpListener listener = new TcpListener(IPAddress.Any, 47935);<br/>
            listener.Start();<br/>
            while (true)<br/>
            {<br/>
                Console.WriteLine("Waiting for a client to connect...");<br/>
                // Application blocks while waiting for an incoming connection.<br/>
                // Type CNTL-C to terminate the server.<br/>
                TcpClient client = listener.AcceptTcpClient();<br/>
                ProcessClient(client);<br/>
            }<br/>
        }<br/>
        static void ProcessClient(TcpClient client)<br/>
        {<br/>
            // A client has connected. Create the <br/>
            // SslStream using the client's network stream.<br/>
            SslStream sslStream = new SslStream(<br/>
                client.GetStream(), false);<br/>
            // Authenticate the server but don't require the client to authenticate.<br/>
            try<br/>
            {<br/>
                sslStream.AuthenticateAsServer(serverCertificate,<br/>
                    false, SslProtocols.Tls, true);<br/>
                // Display the properties and settings for the authenticated stream.<br/>
                DisplaySecurityLevel(sslStream);<br/>
                DisplaySecurityServices(sslStream);<br/>
                DisplayCertificateInformation(sslStream);<br/>
                DisplayStreamProperties(sslStream);<br/>
<br/>
                // Set timeouts for the read and write to 5 seconds.<br/>
                sslStream.ReadTimeout = 5000;<br/>
                sslStream.WriteTimeout = 5000;<br/>
                // Read a message from the client.   <br/>
                Console.WriteLine("Waiting for client message...");<br/>
<br/>
                string messageData = string.Empty;<br/>
                <br/>
                try<br/>
                {<br/>
                    messageData = ReadMessage(sslStream);<br/>
                    Console.WriteLine("Received: {0}", messageData);<br/>
                }<br/>
                catch { }<br/>
                <br/>
                <br/>
<br/>
                // Write a message to the client.<br/>
                byte[] message = Encoding.UTF8.GetBytes("Hello from the server.<EOF>");<br/>
                Console.WriteLine("Sending hello message.");<br/>
                sslStream.Write(message);<br/>
            }<br/>
            catch (AuthenticationException e)<br/>
            {<br/>
                Console.WriteLine("Exception: {0}", e.Message);<br/>
                if (e.InnerException != null)<br/>
                {<br/>
                    Console.WriteLine("Inner exception: {0}", e.InnerException.Message);<br/>
                }<br/>
                Console.WriteLine("Authentication failed - closing the connection.");<br/>
                sslStream.Close();<br/>
                client.Close();<br/>
                return;<br/>
            }<br/>
            finally<br/>
            {<br/>
                // The client stream will be closed with the sslStream<br/>
                // because we specified this behavior when creating<br/>
                // the sslStream.<br/>
                sslStream.Close();<br/>
                client.Close();<br/>
            }<br/>
        }<br/>
        static string ReadMessage(SslStream sslStream)<br/>
        {<br/>
            // Read the  message sent by the client.<br/>
            // The client signals the end of the message using the<br/>
            // "<EOF>" marker.<br/>
            byte[] buffer = new byte[2048];<br/>
            StringBuilder messageData = new StringBuilder();<br/>
            int bytes = -1;<br/>
            do<br/>
            {<br/>
                // Read the client's test message.<br/>
                bytes = sslStream.Read(buffer, 0, buffer.Length);<br/>
<br/>
                // Use Decoder class to convert from bytes to UTF8<br/>
                // in case a character spans two buffers.<br/>
                Decoder decoder = Encoding.UTF8.GetDecoder();<br/>
                char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];<br/>
                decoder.GetChars(buffer, 0, bytes, chars, 0);<br/>
                messageData.Append(chars);<br/>
                // Check for EOF or an empty message.<br/>
                if (messageData.ToString().IndexOf("<EOF>") != -1)<br/>
                {<br/>
                    break;<br/>
                }<br/>
            } while (bytes != 0);<br/>
<br/>
            return messageData.ToString();<br/>
        }<br/>
        static void DisplaySecurityLevel(SslStream stream)<br/>
        {<br/>
            Console.WriteLine("Cipher: {0} strength {1}", stream.CipherAlgorithm, stream.CipherStrength);<br/>
            Console.WriteLine("Hash: {0} strength {1}", stream.HashAlgorithm, stream.HashStrength);<br/>
            Console.WriteLine("Key exchange: {0} strength {1}", stream.KeyExchangeAlgorithm, stream.KeyExchangeStrength);<br/>
            Console.WriteLine("Protocol: {0}", stream.SslProtocol);<br/>
        }<br/>
        static void DisplaySecurityServices(SslStream stream)<br/>
        {<br/>
            Console.WriteLine("Is authenticated: {0} as server? {1}", stream.IsAuthenticated, stream.IsServer);<br/>
            Console.WriteLine("IsSigned: {0}", stream.IsSigned);<br/>
            Console.WriteLine("Is Encrypted: {0}", stream.IsEncrypted);<br/>
        }<br/>
        static void DisplayStreamProperties(SslStream stream)<br/>
        {<br/>
            Console.WriteLine("Can read: {0}, write {1}", stream.CanRead, stream.CanWrite);<br/>
            Console.WriteLine("Can timeout: {0}", stream.CanTimeout);<br/>
        }<br/>
        static void DisplayCertificateInformation(SslStream stream)<br/>
        {<br/>
            Console.WriteLine("Certificate revocation list checked: {0}", stream.CheckCertRevocationStatus);<br/>
<br/>
            X509Certificate localCertificate = stream.LocalCertificate;<br/>
            if (stream.LocalCertificate != null)<br/>
            {<br/>
                Console.WriteLine("Local cert was issued to {0} and is valid from {1} until {2}.",<br/>
                    localCertificate.Subject,<br/>
                    localCertificate.GetEffectiveDateString(),<br/>
                    localCertificate.GetExpirationDateString());<br/>
            }<br/>
            else<br/>
            {<br/>
                Console.WriteLine("Local certificate is null.");<br/>
            }<br/>
            // Display the properties of the client's certificate.<br/>
            X509Certificate remoteCertificate = stream.RemoteCertificate;<br/>
            if (stream.RemoteCertificate != null)<br/>
            {<br/>
                Console.WriteLine("Remote cert was issued to {0} and is valid from {1} until {2}.",<br/>
                    remoteCertificate.Subject,<br/>
                    remoteCertificate.GetEffectiveDateString(),<br/>
                    remoteCertificate.GetExpirationDateString());<br/>
            }<br/>
            else<br/>
            {<br/>
                Console.WriteLine("Remote certificate is null.");<br/>
            }<br/>
        }<br/>
        private static void DisplayUsage()<br/>
        {<br/>
            Console.WriteLine("To start the server specify:");<br/>
            Console.WriteLine("serverSync certificateFile.cer");<br/>
            Environment.Exit(1);<br/>
        }<br/>
        public static void Main(string[] args)<br/>
        {<br/>
            string certificate = null;<br/>
            if (args == null || args.Length < 1)<br/>
            {<br/>
                DisplayUsage();<br/>
            }<br/>
            certificate = args[0];<br/>
            SslTcpServer.RunServer(certificate);<br/>
            //return certificate;<br/>
        }<br/>
    }<br/>
}<br/>

CLIENT CODE (from MSDN)
using System;<br/>
using System.Collections;<br/>
using System.Net;<br/>
using System.Net.Security;<br/>
using System.Net.Sockets;<br/>
using System.Security.Authentication;<br/>
using System.Text;<br/>
using System.Security.Cryptography.X509Certificates;<br/>
using System.IO;<br/>
<br/>
namespace Enable<br/>
{<br/>
    public class SslTcpClient<br/>
    {<br/>
        private static Hashtable certificateErrors = new Hashtable();<br/>
<br/>
        // The following method is invoked by the RemoteCertificateValidationDelegate.<br/>
        public static bool ValidateServerCertificate(<br/>
              object sender,<br/>
              X509Certificate certificate,<br/>
              X509Chain chain,<br/>
              SslPolicyErrors sslPolicyErrors)<br/>
        {<br/>
            if (sslPolicyErrors == SslPolicyErrors.None)<br/>
                return true;<br/>
<br/>
            Console.WriteLine("Certificate error: {0}", sslPolicyErrors);<br/>
<br/>
            // Do not allow this client to communicate with unauthenticated servers.<br/>
            return false;<br/>
        }<br/>
        public static void RunClient(string machineName, string serverName)<br/>
        {<br/>
            // Create a TCP/IP client socket.<br/>
            // machineName is the host running the server application.<br/>
            TcpClient client = new TcpClient(machineName, 47935);<br/>
            Console.WriteLine("Client connected.");<br/>
            // Create an SSL stream that will close the client's stream.<br/>
            SslStream sslStream = new SslStream(<br/>
                client.GetStream(),<br/>
                false,<br/>
                new RemoteCertificateValidationCallback(ValidateServerCertificate),<br/>
                null<br/>
                );<br/>
            // The server name must match the name on the server certificate.<br/>
            try<br/>
            {<br/>
                sslStream.AuthenticateAsClient(serverName);<br/>
            }<br/>
            catch (AuthenticationException e)<br/>
            {<br/>
                Console.WriteLine("Exception: {0}", e.Message);<br/>
                if (e.InnerException != null)<br/>
                {<br/>
                    Console.WriteLine("Inner exception: {0}", e.InnerException.Message);<br/>
                }<br/>
                Console.WriteLine("Authentication failed - closing the connection.");<br/>
                client.Close();<br/>
                return;<br/>
            }<br/>
            // Encode a test message into a byte array.<br/>
            // Signal the end of the message using the "<EOF>".<br/>
            byte[] messsage = Encoding.UTF8.GetBytes("Hello from the client.<EOF>");<br/>
            // Send hello message to the server. <br/>
            sslStream.Write(messsage);<br/>
            sslStream.Flush();<br/>
            // Read message from the server.<br/>
            string serverMessage = ReadMessage(sslStream);<br/>
            Console.WriteLine("Server says: {0}", serverMessage);<br/>
            // Close the client connection.<br/>
            client.Close();<br/>
            Console.WriteLine("Client closed.");<br/>
        }<br/>
        static string ReadMessage(SslStream sslStream)<br/>
        {<br/>
            // Read the  message sent by the server.<br/>
            // The end of the message is signaled using the<br/>
            // "<EOF>" marker.<br/>
            byte[] buffer = new byte[2048];<br/>
            StringBuilder messageData = new StringBuilder();<br/>
            int bytes = -1;<br/>
            do<br/>
            {<br/>
                bytes = sslStream.Read(buffer, 0, buffer.Length);<br/>
<br/>
                // Use Decoder class to convert from bytes to UTF8<br/>
                // in case a character spans two buffers.<br/>
                Decoder decoder = Encoding.UTF8.GetDecoder();<br/>
                char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];<br/>
                decoder.GetChars(buffer, 0, bytes, chars, 0);<br/>
                messageData.Append(chars);<br/>
                // Check for EOF.<br/>
                if (messageData.ToString().IndexOf("<EOF>") != -1)<br/>
                {<br/>
                    break;<br/>
                }<br/>
            } while (bytes != 0);<br/>
<br/>
            return messageData.ToString();<br/>
        }<br/>
        private static void DisplayUsage()<br/>
        {<br/>
            Console.WriteLine("To start the client specify:");<br/>
            Console.WriteLine("clientSync machineName [serverName]");<br/>
            Environment.Exit(1);<br/>
        }<br/>
        public static int Main(string[] args)<br/>
        {<br/>
            string serverCertificateName = null;<br/>
            string machineName = null;<br/>
            <br/>
            if (args == null || args.Length < 1)<br/>
            {<br/>
                DisplayUsage();<br/>
            }<br/>
            // User can specify the machine name and server name.<br/>
            // Server name must match the name on the server's certificate. <br/>
            machineName = args[0];<br/>
            if (args.Length < 2)<br/>
            {<br/>
                serverCertificateName = machineName;<br/>
            }<br/>
            else<br/>
            {<br/>
                serverCertificateName = args[1];<br/>
            }<br/>
            SslTcpClient.RunClient(machineName, serverCertificateName);<br/>
            return 0;<br/>
        }<br/>
    }<br/>
}<br/>

I am also testing it with the following C++ client (code copied from IBM site see below) and I get the following error :

>StandAloneTCPClient.exe
Client: socket() is OK.
Client: connect() is OK.
Client: gonna call SSL_set_fd
Client: SSL_set_fd called
Client: gonna call SSL_connect
SSL error #1 in accept,program terminated


The C++ client code is :

#include <tpf/tpfeq.h>
#include <tpf/tpfio.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "stdafx.h"

// #include <sys/socket.h>
#include "Winsock2.h"
#include <errno.h>
#include <sys/types.h>

#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>

/* define HOME to be dir for key and certificate files... */
#define HOME "/certs/"
/* Make these what you want for certificate & key files */

// DON“T USE DEFINES!!!!!!!!!!!!!!!!
// #define CERT_FILE HOME  "C:\\some\\openssl\\dir\\mycert2.pem"
// #define KEY_FILE  HOME  "C:\\some\\openssl\\dir\\mycert2.pem"

/*Cipher list to be used*/
// #define CIPHER_LIST "AES128-SHA"
// AES128-SHA

// void QSSN(void)
void exampleSSL(void)
{
	int err, count;
	char buff[32];
	
	/*SSL PART*/
	SSL_METHOD *meth;
	SSL_CTX *ctx;

	// WSA initialize
    WORD wVersionRequested;
	WSADATA wsaData;
    wVersionRequested = MAKEWORD(2, 2);
    err = WSAStartup(wVersionRequested, &wsaData);

	/* SSL Part*/
	SSL_library_init();
	SSL_load_error_strings();

	SSLeay_add_ssl_algorithms();

	meth = SSLv23_client_method();

	/*Create a new context block*/
	ctx = SSL_CTX_new(meth);
	if (!ctx) 
	{
		printf("Error creating the context.\n");
		exit(0);
	}

	/*Set cipher list*/
	// #define CIPHER_LIST "AES128-SHA"
	const char* cipherlist = "AES128-SHA";
	if (SSL_CTX_set_cipher_list(ctx, cipherlist) <= 0) 
	{
		printf("Error setting the cipher list.\n");
		exit(0);
	}

	/* Set for server verification*/
	SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL);

	/* Connect to the server, TCP/IP layer,*/
	// SOCKET socketfd;
	// socketfd = socket(AF_INET, SOCK_STREAM, 0);
  
	SOCKET socketfd;
	socketfd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
	if (socketfd == INVALID_SOCKET)
	{
		printf("Client: Error at socket(): %ld.\n", WSAGetLastError());
		WSACleanup();
		return;
	}
	else
		printf("Client: socket() is OK.\n");

	// sockaddr
	sockaddr_in clientService;

	clientService.sin_family = AF_INET;
	clientService.sin_addr.s_addr = inet_addr("192.168.0.201");
		// inet_addr("127.0.0.1");	
		// inet_addr("87.194.161.236");
	clientService.sin_port = htons(47935); // htons(55555);

	// Connect to server.
	err = connect(socketfd, (struct sockaddr*)&clientService, sizeof(clientService));
	if (err < 0) 
	{
		// printf("Socket returned error #%d,program terminated\n",sock_errno());
		int error = WSAGetLastError();
		printf("Socket returned error #%d,program terminated\n", error);
		SSL_CTX_free(ctx);
		exit(0);
	}
	else
	{
		printf("Client: connect() is OK.\n");
	}

	// And now the bloody SSL thing
	
	// Create new ssl object
	SSL* myssl;
	myssl = (SSL*) SSL_new(ctx);
	if(!myssl) 
	{
	   printf("Error creating SSL structure.\n");
	   exit(0);
	}

	// Bind the socket to the SSL structure
	printf("Client: gonna call SSL_set_fd \n");
	SSL_set_fd(myssl, socketfd);
	printf("Client: SSL_set_fd called \n");

	// ...

	// Connect to the server, SSL layer.
	printf("Client: gonna call SSL_connect \n");

	err = SSL_connect(myssl);
	// Check for error in connect.
	if (err < 1) {
	   err = SSL_get_error(myssl, err);
	   printf("SSL error #%d in accept,program terminated\n", err);

	   if(err == 5)
	   {
		   // printf("sockerrno is:%d\n",sock_errno());
		   int error = WSAGetLastError();
		   printf("sockerrno is:%d\n", error);
	   }
	  
	   // close(socketfd);
	   SSL_free(myssl);
	   SSL_CTX_free(ctx);
	   exit(0);
	}
	else
	{
		printf("Client: SSL connect() is OK.\n");
	}
	printf("Client: SSL_connect called \n");

	/*Print out connection details*/
	printf("SSL connection on socket %x,Version: %s, Cipher: %s\n",
		   socketfd,
		   SSL_get_version(myssl),
		   SSL_get_cipher(myssl));

	/*Send message to the server.*/
	err=SSL_write(myssl,"Hello there!!!!",sizeof("Hello there!!!!")+1);
	/*Check for error in write.*/
	if(err<1) 
	{
	   err=SSL_get_error(myssl,err);
	   printf("Error #%d in write,program terminated\n",err);
	   /********************************/
	   /* If err=6 it means the Server */
	   /* issued an SSL_shutdown. You  */
	   /* must respond with a shutdown */
	   /* to complete a graceful       */
	   /* shutdown                     */
	   /********************************/
	   if(err==6)
	   {
		 SSL_shutdown(myssl);
	   }
	   SSL_free(myssl);
	   // close(socketfd);
	   SSL_CTX_free(ctx);
	   exit(0);
	}

	/*Read servers response.*/
	err = SSL_read (myssl, buff, sizeof(buff));
	/*Check for error in read.*/
	if (err < 1) 
	{
	   err=SSL_get_error(myssl,err);
	   printf("Error #%d in read,program terminated\n",err);
	   /********************************/
	   /* If err=6 it means the client */
	   /* issued an SSL_shutdown. You */
	   /* must respond with a shutdown */
	   /* to complete a graceful */
	   /* shutdown */
	   /********************************/
		if(err==6)
	    {
			SSL_shutdown(myssl);
		}
		SSL_free(myssl);
		// close(socketfd);
		SSL_CTX_free(ctx);
		exit(0);
	}

	printf("Server said: %s\n",buff);

	err=SSL_shutdown(myssl);
	count = 1;
	/***********************************/
	/* Try SSL_shutdown() 5 times to   */
	/* wait for the remote application */
	/* to issue SSL_shutdown().        */
	/***********************************/

	while(true) 
	{
	}

	err=SSL_shutdown(myssl);

	// close(socketfd);
	SSL_free(myssl);
	SSL_CTX_free(ctx);
	exit(0);
}

sz_146

Good Luck... I find that anything related to Security is the most difficult to work on because the responses are intentionally cryptic. It takes a well seasoned veteran of doing this type of thing to be able to translate cryptic information into application knowledge.

If I were in your shoes, having this problem I would first suspect that the certificate I created did indeed have an issue (per the response).
So, I would then see if there was any other way (in a current working application) to apply that samecertificate and see if it works.
Ifit didn't work that would tell me the issue is in the certificate.

If I couldn't test that certificate any other way than through the program, I would have to attempt to separate thethree layers. Is it a certificate issue? or Is it aapplication issue or Is it a Server issue.

I would start a the other side first by determining what type of certificate is needed, and whether or not I met the requirements in the certificate. Then I'd try to determine if there is anything related to the WAY in which the certificate is sent that is a requirement for example I noticed in the code that you are making reference to AES128-SHA. What if the server only know 3DES, or L2TP or both or all three?

Then finially I would look toward the application via the "seek and find" method of just trying different things.

Hope this helps.

AcousticGuitar
Thanks AcousticGuitar . I do suspect it is the certificate. But I will dig into it and see if I can get to the bottom of it.
sz_146
I am recieving the exact same error trying to connect a client written in C# to a JAVA server that isusing a certificate generated using openSSL. Has anybody found a solution to this?
FatSlacker

Ok the way I got my problem solved was I found that the windowsserver was runningin TLS mode while theclientwas in SSL mode. Changing the client to TLS mode worked !!!
Other changes I have been through invovled the certificate installation whichis a bit tricky in Windows.

  • Proposed As Answer byFeroze Daud Thursday, September 17, 2009 7:00 PM
  •  
sz_146

I found the problem. Our server team published the certificate in the wrong location. Once it was added to the Trusted Root Certification Authorities using the certificate MMC snap-in the problem disappeared

FatSlacker

You can use google to search for other answers

Custom Search

More Threads

• TCP communication sometimes works, sometimes not
• XMLDocument.Load Proxy Error 407
• Failure to send mail
• Automate file download
• TCP Connections and Web Service Calls (Reposted from WebServices newsgroup)
• Can send mail (attach file winword(doc)) but can't read an attach file
• TcpClient connection timeout
• FtpWebResponse downloads images unreadable
• Winsock error: TCP Provider, error: 0 login when trying to connect
• SMTP authentication using CRAM-MD5 or DIGEST-MD5