12

I am writing a utility that would allow me to monitor the health of our websites. This consists of a series of validation tasks that I can run against a web application. One of the tests is to anticipate the expiration of a particular SSL certificate.

I am looking for a way to pre-fetch the SSL certificate installed on a web site using .NET or a WINAPI so that I can validate the expiration date of the certificate associated with a particular website.

One way I could do this is to cache the certificates when they are validated in the ServicePointManager.ServerCertificateValidationCallback handler and then match them up with configured web sites, but this seems a bit hackish. Another would be to configure the application with the certificate for the website, but I'd rather avoid this if I can in order to minimize configuration.

What would be the easiest way for me to download an SSL certificate associated with a website using .NET so that I can inspect the information the certificate contains to validate it?

EDIT:

To extend on the answer below there is no need to manually create the ServicePoint prior to creating the request. It is generated on the request object as part of executing the request.

    private static string GetSSLExpiration(string url)
    {
        HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
        using (WebResponse response = request.GetResponse()) { }
        if (request.ServicePoint.Certificate != null)
        {
            return request.ServicePoint.Certificate.GetExpirationDateString();
        }
        else
        {
            return string.Empty;
        }
    }
Wil P
  • 3,341
  • 1
  • 20
  • 20

1 Answers1

17

I've just tried this, which "works on my machine (tm)".

It returns the text string representing the expiry date on the server's certificate, and requires an actual hit to be made on the web site.

private string GetSSLExpiryDate(string url)
{
    Uri u = new Uri(url);
    ServicePoint sp = ServicePointManager.FindServicePoint(u);

    string groupName = Guid.NewGuid().ToString();
    HttpWebRequest req = HttpWebRequest.Create(u) as HttpWebRequest;
    req.ConnectionGroupName = groupName;

    using (WebResponse resp = req.GetResponse())
    {
        // Ignore response, and close the response.
    }
    sp.CloseConnectionGroup(groupName);

    // Implement favourite null check pattern here on sp.Certificate
    string expiryDate = sp.Certificate.GetExpirationDateString();

    return expiryDate;
}

I'm afraid I don't know all the rights and wrongs of using ServicePoint, and any other hoops that you might need to jump through, but you do get an SSL expiry date for the actual web site you want to know about.

EDIT: ensure the "url" parameter use the https:// protocol.

e.g. string contosoExpiry = GetSSLExpiryData("https://www.contoso.com/");

Neil Moss
  • 6,598
  • 2
  • 26
  • 42
  • I used this to write certificate details when I hit exceptions. Works great. – GregB Apr 13 '11 at 18:54
  • When I read this my main question was 'what's this ServicePoint thing?' It seems it is a 'connection helper' object for connecting to a particular site, http or https, and shares information necessary for repeated connections to that site, like, in this case, the certificate. Handy. – Tim Lovell-Smith Feb 28 '12 at 05:13
  • Thanks for the great code. However, this does no include the private key with the certificate. Is there any way to get it? – Aditya Bokade Mar 19 '13 at 08:19
  • 1
    @Aditya Bokade - Absolutely not. If you were able to obtain the private key (in this way, or any way) then you would be able to decrypt any traffic sent to this web server. This would be bad. – Neil Moss Mar 19 '13 at 09:55
  • @NeilMoss Thansk for Reply, Neil. Actually I am developing a HTTPS proxy web server. Its working great for HTTP but not for HTTPS. And I am lost in the twisty maze of SSL and certificates. I am posting question in 15 min. Please help. I will drop you a link here. Till then have a look at my this question: http://stackoverflow.com/questions/14671112/sslstream-authenticateasserver-exception-the-server-mode-ssl-must-use-a-certif – Aditya Bokade Mar 19 '13 at 10:48
  • @NeilMoss Please check this:http://stackoverflow.com/questions/15498447/web-proxy-server-application-for-https-requests – Aditya Bokade Mar 19 '13 at 11:39
  • I was looking for the fingerprint instead of expiry date. So this was very helpful for me. Thank you. – Kul-Tigin Mar 18 '14 at 23:39