Jumping Through Hoops James Higgs’s Blog

Posted
1 May 2008 @ 5pm

Tagged
.NET, C#

C#: How to accept an invalid SSL certificate programmatically

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();
	}
}

2 Comments

Posted by
Pawan
5 June 2008 @ 3pm

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


Posted by
Darshan Thacker
12 August 2008 @ 7am

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


Leave a Comment

del.icio.us links for 2008-04-30 del.icio.us links for 2008-07-15