[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