C#: How to accept an invalid SSL certificate programmatically

May 1, 2008 · Posted in Tech 

In the project I’m working on at the moment, we have a requirement to call some REST services using .NET#’s built-in System.Net.HttpWebRequest class. The calls will eventually be over SSL using a properly issued certificate when we go live, but for testing we’ve been using a self-signed certificate.

When you navigate to an HTTP URL with a dodgy certificate in a browser, you get a warning that gives you the option to ignore the problems. In code, this just results in an exception being thrown. The exception is a System.Security.Authentication.AuthenticationException (wrapped in a System.Net.WebException), with an error message of “The remote certificate is invalid according to the validation procedure.”

So, for testing, we needed to find a way to bypass the certificate validation. It turns out that you need to provide a RemoteCertificateValidationCallback delegate and attach it to ServicePointManager.ServerCertificateValidationCallback. What’s not clear is what happens if two threads are competing to set this property to different values, since it’s a static property. Reflector suggests that the property set method doesn’t do anything fancy, so you could easily get into a race condition.

Anyway, here’s s snippet that shows how to do this. Hopefully someone will find it useful, because it took me a while to find.

 // callback used to validate the certificate in an SSL conversation
private static bool ValidateRemoteCertificate(
object sender,
	X509Certificate certificate,
	X509Chain chain,
	SslPolicyErrors policyErrors
)
{
	if (Convert.ToBoolean(ConfigurationManager.AppSettings["IgnoreSslErrors"]))
	{
		// allow any old dodgy certificate...
		return true;
	}
	else
	{
		return policyErrors == SslPolicyErrors.None;
	}
}

private static string MakeRequest(string uri, string method, WebProxy proxy)
{
	HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
	webRequest.AllowAutoRedirect = true;
	webRequest.Method = method;

	// allows for validation of SSL conversations
	ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(
		ValidateRemoteCertificate
	);

	if (proxy != null)
	{
		webRequest.Proxy = proxy;
	}

	HttpWebResponse response = null;
	try
	{
		response = (HttpWebResponse)webRequest.GetResponse();

		using (Stream s = response.GetResponseStream())
		{
			using (StreamReader sr = new StreamReader(s))
			{
				return sr.ReadToEnd();
			}
		}
	}
	finally
	{
		if (response != null)
			response.Close();
	}
}

Comments

27 Responses to “C#: How to accept an invalid SSL certificate programmatically”

  1. Pawan on June 5th, 2008 15:41

    Hi, Very thanks for the code.

    I am using this code to validate SSL certificate of the web site on which I need to post vital data.

    I want to know, if I found that SSL certificate got expired or anything wrong with the certificate then how can I stop the request. Please do respond. Thanks

  2. Darshan Thacker on August 12th, 2008 07:28

    hi,

    its nice to read this article.
    i want to do same validation for one url. can u please tell me what i have to do for the same.in method and proxy what argument i have to pass as i m new in this SSL side i dont have any idea.
    can you please help me.

    thanks

  3. Mark Miller on September 26th, 2008 19:59

    James,

    Thank you. You saved me a lot of R&D work.

    Best,

    Mark

  4. Mario & Salvo on October 17th, 2008 14:25

    This is great snippet. Thank you very much!

  5. sam on November 21st, 2008 11:05

    Thanks a bunch..nice help!!

  6. Doug on January 7th, 2009 04:15

    You are legend!!!! saved my ass

    i also had another problem that was solved by specifying the security protocol as found at:
    http://blogs.msdn.com/mariya/archive/2006/06/19/637162.aspx

    p.s this works for web requests/responses as well

  7. Codru on May 6th, 2009 11:46

    Saved my ass, too, especially that I had 15 minutes to solve it :D

  8. jetty on May 12th, 2009 08:50

    Any one has vb version? i cant convert the following:
    ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(
    ValidateRemoteCertificate
    );

    any help will be appreciated! Thanks

  9. higgis on May 12th, 2009 09:04

    It’ll be something like:

    AddHandler ServicePointManager.ServerCertificateValidationCallback, AddressOf Me.ValidateRemoteCertificate
  10. jetty on May 13th, 2009 08:49

    Thanks for the reply. Now the problem i face is how do i use them? I pasted them in my MasterPage which will through the certificate. Should i call the MakeRequest in my page_load? Any hints please?

  11. higgis on May 13th, 2009 14:49

    I’m confused. Are you trying to download some resource from the web in your Master Page? That sounds like a very bad idea to me. You’ll definitely want to spin off a separate thread to do that I would have thought. Without understanding about what you’re trying to achieve and what your specific problem is I’m probably not going to be able to help.

    If you’re trying to force your own certificate to be accepted by the user’s browser when the certificate is invalid, this approach isn’t going to work. Clearly that would be a great way to con old ladies out of money and is the precise reason that SSL exists in the first place: it’s up to the browser to verify the certificate with a trusted third party, not up to you to say “I know this looks invalid, but trust me it isn’t”.

  12. jetty on May 14th, 2009 02:39

    Ok. Yes i was thinking to force the client browser to accept the certificate but this wasn’t in the production server. I was using that for my staging server, therefore i was hoping that all the developers doesn’t need to accept the invalid certificate everytime they are doing testing. Thanks for the advice.

  13. higgis on May 14th, 2009 09:13

    It’s easy enough to achieve. You just need to add an exclusion for the certificate in your browser. How you do that varies depending on the browser you’re using.

  14. hamish on July 29th, 2009 11:59

    You rule!

  15. Ravi Vooda on August 11th, 2009 06:33

    Though i have a valid certificate , i am getting the below exception. Please help
    System.Net.WebException: The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel

    I have pasted the code below

    X509Certificate2 x509 = new X509Certificate2();
    X509Store store = new X509Store(StoreLocation.LocalMachine);
    byte[] certRawData;

    try
    {
    certRawData = File.ReadAllBytes(ConfigurationManager.AppSettings["CERT_PATH"].ToString());
    x509.Import(certRawData);

    store.Open(OpenFlags.ReadWrite);

    store.Add(x509);

    ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

    //MPG Http Post
    HttpWebRequest webReq;
    webReq = (HttpWebRequest)WebRequest.Create(strURL);
    webReq.Method = “GET”;
    webReq.ClientCertificates.Add(x509);

    HttpWebResponse webRes;
    StreamReader srResponse;
    webRes = (HttpWebResponse)webReq.GetResponse();
    srResponse = new StreamReader(webRes.GetResponseStream(), Encoding.ASCII);
    String strResponseText = srResponse.ReadToEnd();
    srResponse.Close();

    Console.WriteLine(”RESPONSE: ” + strResponseText);

    //End of Http Post

    store.Close();

    }
    catch (Exception certException)
    {
    Console.WriteLine(certException.ToString());
    }

  16. Lawyno on August 27th, 2009 15:09

    Yay! That’s what I needed!

    Thank you very much!

  17. zTech on October 21st, 2009 18:11

    Sweet! Solved my problem with talking to a dev server without a valid certificate. Thanks!

  18. Chris on October 26th, 2009 13:01

    Yay! Thanks a lot! I was having problem with a web service from a company that was a PHP shop. I’ve had nothing but trouble trying to get their service set up. The latest error I got was my system rejecting their SSL cert. They said I had to get my program to ignore SSL errors…and your code did the trick!

  19. Chris on October 26th, 2009 13:02

    FYI: Don’t forget the following usings:

    using System.Web;
    using System.Web.Security;

  20. Ami Schreiber on October 27th, 2009 16:29

    @zTech,

    You say that you solved your problem but you don’t say how. Could you please elaborate?

    @Ravi Vooda,

    Did you ever get this code to work?

  21. higgis on October 27th, 2009 16:33

    @Ami

    Are you having trouble getting it to work? If so, what’s the problem? Let me know and I’ll see if I can help.

  22. Bülent ÇOBAN on December 14th, 2009 08:42

    Thank you ,
    This information solved my testing problems.

  23. Jónas on June 1st, 2010 04:05

    Exactly what I needed. Thanks a lot!

  24. Dietmar on June 10th, 2010 14:53

    Thanks a lot!! That’s what I needed!

  25. Rytis ?salis on June 17th, 2010 14:25

    Thanks a lot :) You solved my problem :)

  26. Rytis Usalis on June 17th, 2010 14:25

    Thanks a lot :) You solved my problem :)

  27. Secret Agent on July 7th, 2010 19:24

    Just remember to unregister the callback after you’re done, otherwise your callback will be called for every registration:

    finally
    {
    ServicePointManager.ServerCertificateValidationCallback -= ValidateRemoteCertificate;
    if (response != null) response.Close();
    }

Leave a Reply