13

Due to Heartbleed, our Gateway Server was updated and this problem presented itself.

Due to POODLE, SSLv3 is no longer supported.

  • Note, the problem is only present on Win7+ boxes; WinXP boxes work without issue (same code, different OS = problem); granted WinXP is no longer a valid OS, just wanted to make note of functionality.

Client application (.NET 2.0) sits on a Windows 7 (or 8) box. Server runs within a DMZ behind a Gateway Server. Just to note, I found that this problem is no longer present on .NET 4.0+ - however due to legacy code, I do not have the luxury of updating.

Gateway Server is a pass through box on which Apache HTTP Server with SSL run. Its location is outside the DMZ, and it is used to access the Server which is inside the DMZ. Versions of software running on the Gateway server are Apache/2.2.25 (Win32), mod_jk/1.2.39, mod_ssl/2.2.25, OpenSSL/1.0.1g

Here is the code used on the Client application (with an exorbitant amount of logging added) ... note, 'serverName' typically contains a value such as "https://some.url.com"

private bool ConnectAndAuthenicate(string serverName, out TcpClient client, out SslStream sslStream)
{
    client = null;
    sslStream = null;
    try
    {
        client = new TcpClient(serverName, 443); // Create a TCP/IP client; ctor attempts connection
        Log("ConnectAndAuthenicate: Client CONNECTED"));

        sslStream = new SslStream(client.GetStream(), false, ValidateServerCertificate, null);
        Log("ConnectAndAuthenicate: SSL Stream CREATED"));
    }
    catch (Exception x)
    {
        Log("ConnectAndAuthenicate: EXCEPTION >> CONNECTING to server: {0}", x.ToString()));

        if (x is SocketException)
        {
            SocketException s = x as SocketException;
            Log("ConnectAndAuthenicate: EXCEPTION >> CONNECTING to server: Socket.ErrorCode: {0}", s.ErrorCode));
        }
        if (client != null) { client.Close(); client = null; }
        if (sslStream != null) { sslStream.Close(); sslStream = null; }
    }

    if (sslStream == null) return false;

    try
    {
        sslStream.ReadTimeout = 10000; // wait 10 seconds for a response ...
        Log("ConnectAndAuthenicate: AuthenticateAsClient CALLED ({0})", serverName));
        sslStream.AuthenticateAsClient(serverName);
        Log("ConnectAndAuthenicate: AuthenticateAsClient COMPLETED SUCCESSFULLY"));
        return true;
    }
    catch (Exception x)
    {
        Log("ConnectAndAuthenicate: EXCEPTION >> AuthenticateAsClient: {0}", x.ToString()));
        client.Close(); client = null;
        sslStream.Close(); sslStream = null;
    }
    return false;
}

Note - answers posted pertaining to ServicePointManager have absolutely no effect on the outcome of this application.

Every time that AuthenicateAsClient() is called when application is run on Win 7+ box, the exception occurs - if application is run on WinXP box, code works properly without exceptions.

Any ideas for solutions are very welcome.

Community
  • 1
  • 1
Bret
  • 2,283
  • 4
  • 20
  • 28

1 Answers1

7

Following the trail of setting the ServicePointManager.SecurityProtocol static ctor with a SecurityProtocolType, I found mention of another enum called SslPolicy -- further research found that AuthenicateAsClient has an overload that takes SslPolicy as an argument.

Changing this line in the above code fixed this problem:

sslStream.AuthenticateAsClient(serverName, null, SslPolicy.Tls, false);
Bret
  • 2,283
  • 4
  • 20
  • 28
  • 1
    If you've run into this problem - chances are high that you might have the "System.Net.WebException: The operation has timed out" exception when you attempt to HttpWebRequest.GetResponse() It should be noted that the setting ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3; fixed the GetResponse() time outs. – Bret Aug 22 '14 at 14:49
  • 2
    Regarding [POODLE](http://en.wikipedia.org/wiki/POODLE) and no longer supporting SSLv3, you can change the `ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;` instead of `Ssl3` – Bret Nov 18 '14 at 15:36
  • 2
    To clarify `this problem is no longer present on .NET 4.0+` -- if you specify SecurityProtocolType.Tls AND are using .NET 2.0, then there are two scenarios that can occur based on which OS that is being used. In XP/2003, this setup works fine -- however, when using Win7/8/2008+, using .Tls fails -- using Wireshark, you can see the interaction that occurs. .NET 2.0 does not supply the `ServerName` value that is part of the TLS extension packet data - therefore, a warning message is returned. In Win7+ OS versions, .NET 2.0 throws an exception for this. In XP/2003, it is ignored and works. – Bret Mar 06 '15 at 16:58
  • ... starting with .NET 4.0, the `ServerName` is properly submitted in the packet data and there is no longer a returned warning message. – Bret Mar 06 '15 at 16:59
  • For more details about this `ServerName` fiasco, you can read about it [here](https://stackoverflow.com/questions/27257525/migrating-from-sslv3-to-tlsv1) – Bret Mar 10 '15 at 19:06
  • There's no overload for AuthenticateAsClient that takes SslPolicy as an argument. The most close constructor signature argument is of type SslProtocols. There's no way this snippet of code could work – ciencia Nov 18 '21 at 17:18
  • @ciencia - it did work once upon a time (.NET 2.0) - the available overloads have expectedly changed along the way - if you're not stuck on .NET 2.0 (like I was at the time), you might be dealing with a different issue – Bret Feb 17 '22 at 13:53