|
Forums -> Security Library Forum
|
by Stuart Ballard posted on 2003/10/21 |
|
I'm trying to use the Org.Mentalis.Security.Ssl Secure* classes on both the server and client for an application I'm writing.
The server side of my application is getting a System.IO.IOException ---> System.ObjectDisposedException: Cannot access a disposed object named "Org.Mentalis.Security.Ssl.Shared.SocketController" when the client tries to connect. Since I'm not directly creating any such object, I'm not sure how to diagnose this failure. On the client side, it just hangs.
Do you have any ideas on how I should diagnose this?
I confess to being not-entirely-up-to-speed on all the issues surrounding SSL - all I want is basic encryption equivalent to what you get when you first connect to an SSH server without independently verifying the fingerprint - in other words, I'm okay with not defending against MITM attacks. But as I understand it I still have to create a cert, and I may have messed up that process because I didn't really know what I was doing. Is this a possible cause of my problems? |
by Pieter Philippaerts [Pieter at mentalis dot org] posted on 2003/10/21 |
|
Can you post the settings (SecurityOptions instance) you're using for the client side?
In particular, what are you using as the VerificationType? If you are using CredentialVerification.Auto or CredentialVerification.AutoWithoutCName, the SecureSocket on the client side will automatically close the connection if the server certificate could not be fully verified. In this case, it's normal that the server socket throws an exception. You can try using CredentialVerification.Manual [look at the example projects] or CredentialVerification.None [use this for testing purposes only].
If this didn't help, could you post some relevant source code and a stack trace of the exception you're seeing? |
by Stuart Ballard posted on 2003/10/22 |
|
Ahh, that explains it, probably.
I didn't set any options that I wasn't sure I needed, so I didn't set VerificationType at all. Whatever the default value is was used, which is presumably one of the two you listed.
Given my requirements as stated above (I don't care about MITM attacks), would "None" actually be a reasonable value for my needs? Or is "None" insecure in some way beyond just not checking the identity of the server, which I don't care about anyway? |
by Pieter Philippaerts [Pieter at mentalis dot org] posted on 2003/10/22 |
|
Yes, the default VerificationType is Auto so this can be causing the problem.
If you set the VerificationType to None, the only attack against the system is a man in the middle attack. So if you don't care about those attacks, you can use the VerificationType.None setting. |
by Stuart Ballard posted on 2003/10/24 |
|
This got me further, but now I'm getting a different error. The stack trace is as follows:
System.IO.IOException: An I/O exception occurred. ---> System.Net.Sockets.SocketException: An attempt was made to reference a token that does not exist
at Org.Mentalis.Security.Ssl.SecureSocket.BeginSend(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, AsyncCallback callback, Object state)
at Org.Mentalis.Security.Ssl.SecureSocket.Send(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
at Org.Mentalis.Security.Ssl.SecureNetworkStream.Write(Byte[] buffer, Int32 offset, Int32 size)
--- End of inner exception stack trace ---
at Org.Mentalis.Security.Ssl.SecureNetworkStream.Write(Byte[] buffer, Int32 offset, Int32 size)
at System.IO.StreamWriter.Flush(Boolean flushStream, Boolean flushEncoder)
at System.IO.StreamWriter.set_AutoFlush(Boolean value)
at HMMServer.HMMController.Run() in c:\devprojects\hmmserver\hmmcontroller.cs:line 74
The relevant section of my code (with unrelated stuff trimmed out) looks more or less like this:
--- Server Side ---
SecurityOptions opts = new SecurityOptions(SecureProtocol.Tls1);
opts.Certificate = HMMService.ServerCert; // initialized elsewhere, although maybe not correctly - shouldn't matter with CV.None though, right?
opts.VerificationType = CredentialVerification.None;
SecureTcpListener listener = new SecureTcpListener(9998, opts);
listener.Start();
SecureTcpClient tc = listener.AcceptTcpClient();
SecureNetworkStream stream = tc.GetStream();
StreamReader reader = new StreamReader(stream);
StreamWriter writer = new StreamWriter(stream);
writer.WriteLine("Some stuff");
// The exception shows up on this next line
writer.AutoFlush = true;
--- Client side (not sure how far this gets or what happens to it) ---
SecurityOptions opts = new SecurityOptions(SecureProtocol.Tls1);
opts.VerificationType = CredentialVerification.None;
SecureTcpClient tc = new SecureTcpClient(hostName, 9998, opts);
SecureNetworkStream stream = tc.GetStream();
StreamReader reader = new StreamReader(stream);
StreamWriter writer = new StreamWriter(stream);
writer.AutoFlush = true;
writer.WriteLine("Other Stuff");
for (string s = reader.ReadLine(); s != null; s = reader.ReadLine())
{
// do some stuff
}
|
by Pieter Philippaerts [Pieter at mentalis dot org] posted on 2003/10/24 |
|
You've initialized both the client and the server socket as client sockets. This is, of course, a recipe for disaster ;-)
Try adding the following line to your server side code:
opts.Entity = ConnectionEnd.Server; |
by Pieter Philippaerts [Pieter at mentalis dot org] posted on 2003/10/24 |
|
By the way, the server socket should always have a valid certificate, regardless of the verification type. It must always be able to access the public and private key of the certificate or the handshake will fail. |
by Stuart Ballard posted on 2003/10/24 |
|
Ahh! That makes a lot of sense - I'll try it right away and report back.
Btw, it might be a good idea to make "server side" the default when you construct a SecureTcpListener - or at least throw an exception right away explaining that this isn't valid. Unless there actually is some legitimate way that a TcpListener can be the client? |
by Stuart Ballard posted on 2003/10/24 |
|
It didn't get any further but it did change the error - this one seems a little bit more generic and less useful, but maybe the stack trace will tell you something:
System.IO.IOException: An I/O exception occurred. ---> Org.Mentalis.Security.SecurityException: An error occurs while communicating with the remote host. ---> Org.Mentalis.Security.Ssl.Shared.SslException: An error occurred during the decryption and verification process.
at Org.Mentalis.Security.Ssl.Shared.RecordLayer.UnwrapMessage(RecordMessage message)
at Org.Mentalis.Security.Ssl.Shared.RecordLayer.ProcessBytes(Byte[] buffer, Int32 offset, Int32 size)
at Org.Mentalis.Security.Ssl.Shared.SocketController.OnReceive(IAsyncResult ar)
--- End of inner exception stack trace ---
at Org.Mentalis.Security.Ssl.SecureSocket.EndSend(IAsyncResult asyncResult)
at Org.Mentalis.Security.Ssl.SecureSocket.Send(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
at Org.Mentalis.Security.Ssl.SecureNetworkStream.Write(Byte[] buffer, Int32 offset, Int32 size)
--- End of inner exception stack trace ---
at Org.Mentalis.Security.Ssl.SecureNetworkStream.Write(Byte[] buffer, Int32 offset, Int32 size)
at System.IO.StreamWriter.Flush(Boolean flushStream, Boolean flushEncoder)
at System.IO.StreamWriter.set_AutoFlush(Boolean value)
at HMMServer.HMMController.Run() in c:\devprojects\hmmserver\hmmcontroller.cs:line 75 |
by Pieter Philippaerts [Pieter at mentalis dot org] posted on 2003/10/24 |
|
Simply changing that ConnectionEnd value worked on my computer. I've uploaded my version of your code here: http://www.mentalis.org/downloads/TlsTest.zip
The ZIP file includes a server.pfx file. Make sure you place this file in the directory of the executable.
A client socket can be the SSL server and likewise a server socket can be the SSL client. The ConnectionEnd value simply indicates to the library whether it must initiate the SSL handshake or whether the other side will initiate the handshake. |
by Stuart Ballard posted on 2003/10/24 |
|
Thanks! It worked when I used your pfx file. There must have been something wrong with my cert.
Out of interest, exactly how do you generate a working pfx file? I couldn't figure out which tools I was supposed to use for cert generation, which is probably why mine went so horribly wrong... |
by Pieter Philippaerts [Pieter at mentalis dot org] posted on 2003/10/24 |
|
The most common problem with certificates is that the system cannot find the associated private key. Another problem could be that it's a signing-only certificate.
We use Microsoft Certificate Services to generate certificates. It comes with the server editions of Windows 2000 and Windows Server 2003. A free alternative is OpenSSL [www.openssl.org], but it's a bit tricky to work with. |
by Pieter Philippaerts [Pieter at mentalis dot org] posted on 2003/10/24 |
|
If you wish to use OpenSSL to generate your certificates, here's something that may help you: http://www.jabberstudio.org/pipermail/jabber-net/2003-May/000082.html [look for ">From the SocketWatcher docs:"] |
|
|