.NET Forum / .NET Framework / New Users / July 2007
Problem with SslStream when using Windows Vista
|
|
Thread rating:  |
Dave - 09 Jul 2007 20:26 GMT Hi.
When my client program runs under XP and calls a server (solaris in this case) via an SslStream all is well. The client may make multiple calls and multiple authentication calls and be fine. I expressly "clean up" everything streamwise and socketwise and all is well. Running the client under Vista, when the second authentication call is made it returns the following SSPI error:
"A call to the SSPI failed, see inner exception"
which reads "the Local Security Authority cannot be contacted"
Well that was pretty mystifying so I looked at what was going on with ethereal. Apparently, on the second authentication go-round Vista asks the server to re-use a session Id. The server responds and then Vista rejects a re-used session Id (even though it asked to do that).
What I have found out is that the .net framework caches SslStream sessions automatically, I have not found any way to turn this off for Vista - any ideas on how to do this or to get Vista to use the cached SessionId which it requested?
Here is a link to a sample that seemingly generates the same flaw that I have described.
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1222194&SiteID=1
Thanks Dave
Jeffrey Tan[MSFT] - 10 Jul 2007 06:38 GMT Hi Dave,
The session resumption can be turned off by setting the maximum cache size \ time to a very small value. But this is a horrible workaround (not advised) http://msdn2.microsoft.com/en-us/library/aa922895.aspx
To help to find the root cause, is it possible for you to provide a little sample project to demonstrate this problem? Once I can give it a local reproduce, it would be easier to troubleshoot it and find a solution.
Thanks.
Best regards, Jeffrey Tan Microsoft Online Community Support ================================================== Get notification to my posts through email? Please refer to http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif ications.
Note: The MSDN Managed Newsgroup support offering is for non-urgent issues where an initial response from the community or a Microsoft Support Engineer within 1 business day is acceptable. Please note that each follow up response may take approximately 2 business days as the support professional working with you may need further investigation to reach the most efficient resolution. The offering is not appropriate for situations that require urgent, real-time or phone-based interactions or complex project analysis and dump analysis issues. Issues of this nature are best handled working with a dedicated Microsoft Support Engineer by contacting Microsoft Customer Support Services (CSS) at http://msdn.microsoft.com/subscriptions/support/default.aspx. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights.
Dave - 10 Jul 2007 14:03 GMT I provided a link in the first post to a sample project provided by another individual.
If you need something more just tell me and I will try to put it together.
> Hi Dave, > [quoted text clipped - 31 lines] > This posting is provided "AS IS" with no warranties, and confers no > rights. Dave - 10 Jul 2007 14:13 GMT Are you referring to the ClientCacheTime or MaximumCachSize ? MaximumCachSize is defined as: The maximum number of elements in a session cache.
> Hi Dave, > [quoted text clipped - 31 lines] > This posting is provided "AS IS" with no warranties, and confers no > rights. Dave - 10 Jul 2007 14:17 GMT Here is a sample that someone else posted and I had a link to in my first post:
___
Exception: A call to SSPI failed, see inner exception. Inner exception: The Local Security Authority cannot be contacted Authentication failed - closing the connection.
I've reviewed tracing information and it doesn't really help. What seems to occur is an internal error and then the client side connection is shutdown.
System.Net Information: 0 : [3804] AcceptSecurityContext(In-Buffer length=1333, Out-Buffer length=0, returned code=InternalError).
Anyone with any hints it would be much appreciated.
The code for the server & client follow.
--- server.cs -- using System; using System.Collections; using System.Net; using System.Net.Sockets; using System.Net.Security; using System.Security.Authentication; using System.Text; using System.Security.Cryptography.X509Certificates; using System.IO; using System.Threading;
namespace Examples.System.Net { public class SslTcpServer { private X509Certificate _serverCertificate = null; private Thread _thread; private int _port = 0;
// The certificate parameter specifies the name of the file // containing the machine certificate. void RunServer() { // Create a TCP/IP (IPv4) socket and listen for incoming connections. TcpListener listener = new TcpListener(IPAddress.Any, 0); listener.Start(); lock(this) { _port = ((IPEndPoint)listener.LocalEndpoint).Port; Monitor.Pulse(this); } Console.WriteLine("Waiting for a client to connect on port " + _port); TcpClient client = listener.AcceptTcpClient(); ProcessClient(client); listener.Stop(); }
void ProcessClient(TcpClient client) { // A client has connected. Create the // SslStream using the client's network stream. SslStream sslStream = new SslStream(client.GetStream(), false); try { sslStream.AuthenticateAsServer( _serverCertificate, false, SslProtocols.Tls, true);
// Set timeouts for the read and write to 5 seconds. sslStream.ReadTimeout = 5000; sslStream.WriteTimeout = 5000; // Read a message from the client. Console.WriteLine("Waiting for client message..."); string messageData = ReadMessage(sslStream); Console.WriteLine("Received: {0}", messageData);
// Write a message to the client. byte[] message = Encoding.UTF8.GetBytes("Hello from the server.<EOF>"); Console.WriteLine("Sending hello message."); sslStream.Write(message); } 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."); sslStream.Close(); client.Close(); } finally { // The client stream will be closed with the sslStream // because we specified this behavior when creating // the sslStream. sslStream.Close(); client.Close(); } }
string ReadMessage(SslStream sslStream) { // Read the message sent by the client. // The client signals the end of the message using the // "<EOF>" marker. byte [] buffer = new byte[2048]; StringBuilder messageData = new StringBuilder(); int bytes = -1; do { // Read the client's test message. bytes = sslStream.Read(buffer, 0, buffer.Length);
// Use Decoder class to convert from bytes to UTF8 // in case a character spans two buffers. Decoder decoder = Encoding.UTF8.GetDecoder(); char[] chars = new char[decoder.GetCharCount(buffer,0,bytes)]; decoder.GetChars(buffer, 0, bytes, chars,0); messageData.Append (chars); // Check for EOF or an empty message. if (messageData.ToString().IndexOf("<EOF>") != -1) { break; } } while (bytes !=0);
return messageData.ToString(); }
public SslTcpServer() { _serverCertificate = new X509Certificate2("s_rsa_nopass_ca1.pfx", "password"); _thread = new Thread(new ThreadStart(RunServer)); _thread.Name = "SslTcpServer"; _thread.Start(); }
public int GetPort() { lock(this) { while(_port == 0) { Monitor.Wait(this); } } return _port; } }
public class FactoryServer { void ProcessClient(TcpClient client) { try { SslTcpServer server = new SslTcpServer(); int port = server.GetPort(); NetworkStream stream = client.GetStream(); byte[] msg = Encoding.UTF8.GetBytes(port.ToString()); stream.Write(msg, 0, msg.Length); byte[] term = new byte[1]; term[0] = 0; stream.Write(term, 0, 1); stream.Flush(); int bytes = stream.Read(term, 0, 1); } finally { client.Close(); } }
public void Run() { TcpListener listener = new TcpListener(IPAddress.Any, 8080); listener.Start(); while (true) { Console.WriteLine("Waiting for a client to connect..."); // Application blocks while waiting for an incoming connection. // Type CNTL-C to terminate the server. TcpClient client = listener.AcceptTcpClient(); ProcessClient(client); } }
}
public class Server { public static int Main(string[] args) { FactoryServer server = new FactoryServer(); server.Run(); return 0; } } } -- client.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; using System.Threading;
namespace Examples.System.Net { public class SslTcpClient { private static Hashtable certificateErrors = new Hashtable();
public static bool ValidateServerCertificate( object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; }
public static void RunClient(int port) { TcpClient client = new TcpClient("127.0.0.1", port); NetworkStream stream = client.GetStream(); Console.WriteLine("Client connected."); // Create an SSL stream that will close the client's stream. SslStream sslStream = new SslStream( stream, false, new RemoteCertificateValidationCallback( ValidateServerCertificate), null); try { //sslStream.AuthenticateAsClient("localhost", null, SslProtocols.Default, false); sslStream.AuthenticateAsClient("localhost"); } 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; } // Encode a test message into a byte array. // Signal the end of the message using the "<EOF>". byte[] messsage = Encoding.UTF8.GetBytes("Hello from the client.<EOF>"); // Send hello message to the server. sslStream.Write(messsage); sslStream.Flush(); // Read message from the server. string serverMessage = ReadMessage(sslStream); Console.WriteLine("Server says: {0}", serverMessage); // Close the client connection. client.Close(); Console.WriteLine("Client closed."); } static string ReadMessage(SslStream sslStream) { // Read the message sent by the server. // The end of the message is signaled using the // "<EOF>" marker. byte [] buffer = new byte[2048]; StringBuilder messageData = new StringBuilder(); int bytes = -1; do { bytes = sslStream.Read(buffer, 0, buffer.Length);
// Use Decoder class to convert from bytes to UTF8 // in case a character spans two buffers. Decoder decoder = Encoding.UTF8.GetDecoder(); char[] chars = new char[decoder.GetCharCount(buffer,0,bytes)]; decoder.GetChars(buffer, 0, bytes, chars,0); messageData.Append (chars); // Check for EOF. if (messageData.ToString().IndexOf("<EOF>") != -1) { break; } } while (bytes != 0);
return messageData.ToString(); }
private static int ReadPort(NetworkStream stream) { byte[] msg = new byte[1024]; int curr = 0; do { int bytes = stream.Read(msg, curr, 1); if(bytes == 0) { Console.WriteLine("Error reading port"); return 1; } if(msg[curr] == 0) { break; } ++curr; } while(curr < msg.Length); if(curr == msg.Length) { Console.WriteLine("Error reading port"); return 1; }
Decoder decoder = Encoding.UTF8.GetDecoder(); char[] chars = new char[decoder.GetCharCount(msg,0,msg.Length-1)]; decoder.GetChars(msg, 0, msg.Length-1, chars,0); StringBuilder messageData = new StringBuilder(); messageData.Append(chars); return Int32.Parse(messageData.ToString()); }
public static int Main(string[] args) { TcpClient client = new TcpClient("127.0.0.1", 8080); NetworkStream stream = client.GetStream(); Console.WriteLine("Client connected."); int port = ReadPort(stream); Console.WriteLine("Connecting to " + port);
// Write termination byte drop the client. byte[] term = new byte[1]; term[0] = 0; stream.Write(term, 0, 1); client.Close();
SslTcpClient.RunClient(port); return 0; } } }
> Hi Dave, > [quoted text clipped - 31 lines] > This posting is provided "AS IS" with no warranties, and confers no > rights. Jeffrey Tan[MSFT] - 11 Jul 2007 08:50 GMT Hi Dave,
I have created an empty server project in my Win2003 machine and copied your code in it. Then I copied your client code in a project on another Vista machine. Finally, I obtained a password protected pfx file from my colleague and modify the server code to use it.
However, when I run the server and the the client project under debugger, I did not get any exception like you got.
Is there anything I miss in the above steps? Thanks.
Best regards, Jeffrey Tan Microsoft Online Community Support ================================================== Get notification to my posts through email? Please refer to http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif ications.
Note: The MSDN Managed Newsgroup support offering is for non-urgent issues where an initial response from the community or a Microsoft Support Engineer within 1 business day is acceptable. Please note that each follow up response may take approximately 2 business days as the support professional working with you may need further investigation to reach the most efficient resolution. The offering is not appropriate for situations that require urgent, real-time or phone-based interactions or complex project analysis and dump analysis issues. Issues of this nature are best handled working with a dedicated Microsoft Support Engineer by contacting Microsoft Customer Support Services (CSS) at http://msdn.microsoft.com/subscriptions/support/default.aspx. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights.
Dave - 12 Jul 2007 21:34 GMT Jeffrey,
I have another client example to give you. Could you possibly give me an email address to send it to you, I would prefer not posting it on the new group in its current form.
Dave
> Hi Dave, > [quoted text clipped - 31 lines] > This posting is provided "AS IS" with no warranties, and confers no > rights. Jeffrey Tan[MSFT] - 13 Jul 2007 07:42 GMT Hi Dave,
Yes, you may send the reproduce project to jetan@online.microsoft.com(remove "online."). Please also send the detailed steps to reproduce the problem, thanks.
Best regards, Jeffrey Tan Microsoft Online Community Support ================================================== Get notification to my posts through email? Please refer to http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif ications.
Note: The MSDN Managed Newsgroup support offering is for non-urgent issues where an initial response from the community or a Microsoft Support Engineer within 1 business day is acceptable. Please note that each follow up response may take approximately 2 business days as the support professional working with you may need further investigation to reach the most efficient resolution. The offering is not appropriate for situations that require urgent, real-time or phone-based interactions or complex project analysis and dump analysis issues. Issues of this nature are best handled working with a dedicated Microsoft Support Engineer by contacting Microsoft Customer Support Services (CSS) at http://msdn.microsoft.com/subscriptions/support/default.aspx. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights.
Dave - 13 Jul 2007 20:47 GMT Jeffrey,
Are you running the connect multiple times during the same run time session? Don't exit the program. You might need to create a form and add a connect and then close button. Then go through the sequence of connecting then disconnecting, then reconnecting.
On the second attempt to connect you will receive the error. I just did what you did, I put an ssl listener program on a windows 2003 server and ran a client on a vista box. I generates the same error on the second attempt to connect.
Dave
> Hi Dave, > [quoted text clipped - 31 lines] > This posting is provided "AS IS" with no warranties, and confers no > rights. Jeffrey Tan[MSFT] - 16 Jul 2007 07:17 GMT Hi Dave,
Thank you for the feedback.
Yes, I have tried to run the SSLClient on the Vista machine for more than 2 times. However, both will work without any error. It is strange that I can not reproduce this error.
I have received your sample project through email. However, when I try to connect your server(I run it without any modification), I will get "No such host is known" SocketException. It seems that I can not connect your server in my CorpNet.
Is it possible for you to provide client/server pair projects that can reproduce this problem? I think reproducing it locally is easier than connecting out of CorpNet.
I will wait for your further feedback, thanks.
Best regards, Jeffrey Tan Microsoft Online Community Support ================================================== Get notification to my posts through email? Please refer to http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif ications.
Note: The MSDN Managed Newsgroup support offering is for non-urgent issues where an initial response from the community or a Microsoft Support Engineer within 1 business day is acceptable. Please note that each follow up response may take approximately 2 business days as the support professional working with you may need further investigation to reach the most efficient resolution. The offering is not appropriate for situations that require urgent, real-time or phone-based interactions or complex project analysis and dump analysis issues. Issues of this nature are best handled working with a dedicated Microsoft Support Engineer by contacting Microsoft Customer Support Services (CSS) at http://msdn.microsoft.com/subscriptions/support/default.aspx. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights.
Dave - 10 Jul 2007 15:59 GMT Jeffrey,
Those keys are for windows CE and mobile not for windows Vista.
Dave
> Hi Dave, > [quoted text clipped - 31 lines] > This posting is provided "AS IS" with no warranties, and confers no > rights. Jeffrey Tan[MSFT] - 11 Jul 2007 10:26 GMT Hi Dave,
Oh, yes, please look into this: http://technet2.microsoft.com/windowsserver/en/library/3f98fdd9-ed64-49f7-9c 20-a2d4581dfbea1033.mspx
Best regards, Jeffrey Tan Microsoft Online Community Support ================================================== Get notification to my posts through email? Please refer to http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif ications.
Note: The MSDN Managed Newsgroup support offering is for non-urgent issues where an initial response from the community or a Microsoft Support Engineer within 1 business day is acceptable. Please note that each follow up response may take approximately 2 business days as the support professional working with you may need further investigation to reach the most efficient resolution. The offering is not appropriate for situations that require urgent, real-time or phone-based interactions or complex project analysis and dump analysis issues. Issues of this nature are best handled working with a dedicated Microsoft Support Engineer by contacting Microsoft Customer Support Services (CSS) at http://msdn.microsoft.com/subscriptions/support/default.aspx. ================================================== This posting is provided "AS IS" with no warranties, and confers no rights.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|