[Mono-list] SSL/TLS client to an Erlang server

Sebastien Pouliot sebastien.pouliot at gmail.com
Mon Apr 27 08:25:03 EDT 2009


On Sun, 2009-04-26 at 08:50 +0100, Essien Essien wrote:
> Hi,
> 
> I used to do C# development up till about 3 years ago, but I've not
> had to do any C# untill recently, so I'm not sure if that makes me a
> Mono newbie or not :)
> 
> I have an Erlang server to which I want to connect a C# client to over
> SSL/TLS, and so far, I've been able to figure out the code side of
> things from the docs.
> 
> I'm testing with self-signed certificates, created with openssl, and
> I've been able to figure out how to convert PEM certs to DER format
> which .NET/Mono seems to require.

why don't you use mono-provided tools to create your self-signed
certificate ?

googling for "mono self signed certificate" returns a bunch of helpful
hits, including:
http://mono-project.com/UsingClientCertificatesWithXSP
http://pages.infinit.net/ctech/20041129-0607.html

> I've also been able to figure out that I need to usethe certmgr
> command line tool to manager certs in the mono cert stores.
> 
> My problem right now is that so far, my self-signed certs created with
> openssl then converted and imported into mono certificate stores
> "Trust" and "CA" do not work against my erlang server.
> 
> My commands which I use are below:
> 
> To create the cert:
> 
> $ openssl genrsa -out key.pem 1024
> $ openssl req -new -x509 -key key.pem -sha1 -nodes -out cert.pem
> 
> To convert to DER cert for use in Mono
> 
> $ openssl x509 -in cert.pem -outform DER -out cert.cer
> 
> To import into mono's "Trust" store
> 
> $ certmgr -add -c Trust cert.cer
> 
> I've attached my C# code here. I compile it with:
> 
> $ gmcs jsonevents_ssl.cs
> 
> And when I run with:
> 
> $mono jsonevents_ssl.exe
> 
> I get the following:
> 
> [essiene at audrey ~]$ mono ssltest.exe
> Starting
> Client connected.
> Ceritificate error: RemoteCertificateChainErrors
> 
> Unhandled Exception: System.IO.IOException: The authentication or
> decryption has failed. ---> Mono.Security.Protocol.Tls.TlsException:
> Invalid certificate received from server.
>   at
> Mono.Security.Protocol.Tls.Handshake.Client.TlsServerCertificate.validateCertificates
> (Mono.Security.X509.X509CertificateCollection certificates) [0x00000]
>   at
> Mono.Security.Protocol.Tls.Handshake.Client.TlsServerCertificate.ProcessAsTls1
> () [0x00000]
>   at
> Mono.Security.Protocol.Tls.Handshake.Client.TlsServerCertificate.ProcessAsSsl3
> () [0x00000]
>   at Mono.Security.Protocol.Tls.Handshake.HandshakeMessage.Process ()
> [0x00000]
>   at (wrapper remoting-invoke-with-check)
> Mono.Security.Protocol.Tls.Handshake.HandshakeMessage:Process ()
>   at
> Mono.Security.Protocol.Tls.ClientRecordProtocol.ProcessHandshakeMessage
> (Mono.Security.Protocol.Tls.TlsStream handMsg) [0x00000]
>   at
> Mono.Security.Protocol.Tls.RecordProtocol.InternalReceiveRecordCallback
> (IAsyncResult asyncResult) [0x00000]
>   --- End of inner exception stack trace ---
>   at Mono.Security.Protocol.Tls.SslStreamBase.AsyncHandshakeCallback
> (IAsyncResult asyncResult) [0x00000]
> [essiene at audrey ~]$
> 
> 
> 
> Any one have any ideas what I could be doing wrong... after much
> googling, I'm
> not sure what is wrong.

Try to split out your problem, like

* can you use any other tool (like openssl) to connect to your server ?

* if so what does it log (e.g. debug mode if any with your tool) ?

* have you tried wireshark to see what's happening at the protocol
level ?

> 
> Also, incase anyone wants to try to run it, I have attached the Erlang
> Server Test as an Escript.
> If you have Erlang installed, it will run without being compiled. Just
> make it executable and run. Also, remember to change Lines 14, 15 and
> 16 to point to the proper paths where you have stored the PEM cert and
> keyfile created above.
> 
> 
> cheers,
> Essien
> 
> 
> 
> 
> 
> 
> 
> C# source
> attachment
> (jsonevents_ssl.cs)
> 
> using System;
> using System.Collections;
> using System.Net;
> using System.Net.Security;
> using System.Net.Sockets;
> using System.Security.Authentication;
> using System.Text;
> using System.Security.Cryptography.X509Certificates;
> using System.IO;
> 
> namespace JsonEvents.Ssl.Test
> {
>     public class JsonEventsClient
>     {
>         public static void Main(String[] args)
>         {
>             Console.WriteLine("Starting");
>             RunClient("localhost", "ssl.rabbitmq.org");
>             Console.WriteLine("Finished");
>         }
> 
>         //private static Hashtable certificateErrors = new
> Hashtable();
> 
>         public static bool ValidateServerCertificate(
>                 object sender,
>                 X509Certificate certificate,
>                 X509Chain chain,
>                 SslPolicyErrors sslPolicyErrors)
>         {
>             if(sslPolicyErrors == SslPolicyErrors.None)
>                 return true;
> 
>             Console.WriteLine("Ceritificate error: {0}",
> sslPolicyErrors);
> 
>             return false;

what happens if you always return true ? 

since this remove the certificate check - so it will tell you if your
problem is related to certificate/config or to your own code.


>         }
> 
>         public static void RunClient(string machineName, string
> serverName)
>         {
>             TcpClient client = new TcpClient(machineName, 8196);
> 
>             Console.WriteLine("Client connected.");
> 
>             SslStream sslStream = new SslStream(
>                     client.GetStream(),
>                     false,
>                     new
> RemoteCertificateValidationCallback(ValidateServerCertificate),
>                     null);
> 
>             try
>             {
>                 sslStream.AuthenticateAsClient(
>                         serverName, 
>                         null,
>                         SslProtocols.Ssl3,

why are you limiting the code to SSL3 ? instead of using the Default
which will adjust itself (SSL3 or TLS1) with your server ?

>                         false);
>             }
>             catch (AuthenticationException e)
>             {
>                 Console.WriteLine("Exception: {0}", e.Message);
>                 if(e.InnerException != null)
>                 {
>                     Console.WriteLine("Inner exception: {0}",
> e.InnerException.Message);
>                 }
> 
>                 Console.WriteLine("Authentication failed - closing the
> connection.");
>                 client.Close();
>                 return;
>             }
> 
>             Loop(sslStream);
>             client.Close();
>         }
> 
>         static void Loop(SslStream sslStream)
>         {
>             while (true)
>             {
>                 Console.WriteLine("Waiting for server message");
>                 string serverMessage = ReadMessage(sslStream);
>                 Console.WriteLine(" > {0}", serverMessage);
>             }
>         }
> 
>         static string ReadMessage(SslStream sslStream)
>         {
>             byte[] buffer = new byte[2048];
>             StringBuilder messageData = new StringBuilder();
>             int bytes = -1;
>             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.Append(chars);
>             } while(bytes != 0);
> 
>             return messageData.ToString();
>         }
>     }
> }



More information about the Mono-list mailing list