2

I'm using the following code to accept bad server certificates:

ServicePointManager.ServerCertificateValidationCallback = delegate(object s,
  X509Certificate cert, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
    Debug.WriteLine("Returned certificate valid");
    return true;
}

And this code to make a request:

HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://localhost/test");
req.Timeout = 5000;
try {
    Debug.WriteLine("Checking...");
    HttpWebResponse response = (HttpWebResponse)req.GetResponse();
    Debug.WriteLine("Done");
}
catch
{
    Debug.WriteLine("Error");
    //error
}

The first time I run this request it waits 5 seconds and then throws a timeout exception. The validation callback is executed successfully right before the timeout, and I can see that the correct (invalid) certificate is passed in.

If I increase the timeout to 15 seconds, it takes 15 seconds for the callback to be executed and then the request times out.

Subsequent requests (without restarting the program) have a success rate of about 90%. (10% of them timeout; the others return almost instantly.) What is going on here?

EDIT: If I unplug my network connection all the requests return successfully which makes me think it must be trying to contact a CA or something... Why does it timeout instead of throwing a security exception and how can I stop this?

EDIT 2: I commented out the timeout @ScottSmith's suggestion and all the requests now succeed! Sometimes they succeed before the old timeout period which is really confusing me. Is there any way I can get .net to stop trying to validate the certificate behind the scenes?

EDIT 3: I found a forum post that I think explains my problem. Look at the final post on this page: http://www.pcreview.co.uk/forums/ie-going-very-slow-if-certificate-isnt-valid-t735059.html I used wireshark and once the request is issued, 3 DNS queries for www.download.windowsupdate.com are made. Once they fail (since the computer is not connected to the internet) the certificate validation callback is finally called and the request completes. If anyone can come up with a way to disable this behavior that would be amazing.

takteek
  • 7,020
  • 2
  • 39
  • 70
  • 2
    I have been looking this over and it all looks correct to me. From my investigation what you are doing looks correct as well. The only thing I would suggest is removing the line of code `req.Timeout = 5000;` to see if the setting of that is why you are getting the timeout instead of the security exception. – Scott Smith Jan 25 '12 at 03:57
  • Did you ever find a solution better than removing the timeout? I have the same issue. I want the timeout, but don't want the error on the first attempt. Super annoying. – TravisWhidden May 17 '18 at 19:08

4 Answers4

2

It is hard to tell what's wrong but some things to check:

  • set ServicePointManager.CheckCertificateRevocationList explicitly to false after you add your handler (it default to false but might somehow be true in your case)

  • check tha value of sslPolicyErrors in your callback, perhaps it gives you some clue on what is going on

  • check the properties of req.ServicePoint, it might help narrow down what is going on (esp. to see if your request is being redirected)

  • check your proxy settings, they might be part of the problem

  • is there lots of TCP/IP traffic going on ? (check with netstat, see whether you have several TIME_WAIT sockets)

  • what happens when try that URL from a browser ?

  • check the logs on the web server (IIS?) for anything regarding the http request

UPDATE - after EDIT from OP:

you could try to set ServicePointManager.DnsRefreshTimeout to a very high value and see if that helps BUT be aware that this might have other negative effects!

Yahia
  • 69,653
  • 9
  • 115
  • 144
  • Thanks for your help. While going through your steps and trying things I found a forum post that explains my problem. I edited my question to include some more information. – takteek Jan 26 '12 at 00:19
  • I'm going to accept this answer since you provided a lot of helpful suggestions. However, in the end, there doesn't appear to be a programmatic way of avoiding the problem. We don't have control over end-user group policy so Peresis's answer is out. We avoided the problem by signing the cert with our own root and then installing the root cert along with the application. – takteek Aug 07 '12 at 03:04
1

Answer for OP's Edit 3:
I was experiencing the same problem. The answer turned out to be disabling the Automatic Root Certificates Update component by editing the Group Policy settings in Windows. An explanation for how in Windows Server 2008 is here: http://technet.microsoft.com/en-us/library/cc734054%28v=ws.10%29.aspx

Update with summary of steps:

  1. Open Local Group Policy Editor (type gpedit.msc from command line)
  2. Navigate to: Administrative Templates -> System -> Internet Communication Management -> Internet Communication Settings
  3. Double click "Turn off Automatic Root Certificates Update"
  4. Click "enabled", click "ok".
Peresis
  • 11
  • 2
1
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

What makes this HTTPS WebRequest time out even though it works in the browser?

This solved my issue

Community
  • 1
  • 1
Kalel Wade
  • 7,742
  • 3
  • 39
  • 55
0

I had an issue with an application I wrote that ran within a WinPE 4.0 environment where we were using Two-way SSL.

It was taking a minute for the initial connection to go through. Sounds a lot like what you were saying is your problem in your Edit.

Because of the environment there is no group policy editor so I needed to track down the registry value that backed it so i could set it within the offline wim.

HKLM\Software\Policies\Microsoft\SystemCertificates\AuthRoot

DisableRootAutoUpdate DWORD Value 1

Source: http://www.group-policy.com/ref/policy/452/Turn_off_Automatic_Root_Certificates_Update

JoshHetland
  • 1,273
  • 1
  • 12
  • 22