124

I'm writing a program that reads content from a user provided URL. My problem is in the code that goes something like this:

Uri uri = new Uri(url);
WebRequest webRequest = WebRequest.Create(uri);
WebResponse webResponse = webRequest.GetResponse();
ReadFrom(webResponse.GetResponseStream());

And this is breaking if the provided url is an https:// URL. Can anyone help me with changing this code so that it will work with SSL encrypted content. Thanks.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
Alfred B. Thordarson
  • 4,460
  • 8
  • 39
  • 37

4 Answers4

184

You're doing it the correct way but users may be providing urls to sites that have invalid SSL certs installed. You can ignore those cert problems if you put this line in before you make the actual web request:

ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(AcceptAllCertifications);

where AcceptAllCertifications is defined as

public bool AcceptAllCertifications(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certification, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
    return true;
}
Amirhossein Mehrvarzi
  • 18,024
  • 7
  • 45
  • 70
LukeDuff
  • 2,379
  • 1
  • 14
  • 4
  • 46
    Thanks for this answer! To avoid some useless code I used it like this: ServicePointManager.ServerCertificateValidationCallback = (s, cert, chain, ssl) => true; – Charles Ouellet Oct 26 '11 at 21:17
  • 4
    Thanks, you helped me sir. F# makes this so easier: ``ServicePointManager.ServerCertificateValidationCallback <- Security.RemoteCertificateValidationCallback (fun _ _ _ _ -> true)`` – David Grenier Jan 10 '12 at 21:25
  • 25
    I prefer `+= delegate { return true; }` – user10101 Aug 24 '12 at 10:32
  • 2
    Be aware of the potential risks associated with this approach. See https://stackoverflow.com/a/6613434/2969615 for more information. – Joe Coyle Oct 24 '18 at 17:15
21

This one worked for me:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Nani
  • 1,148
  • 3
  • 20
  • 35
  • 1
    The default value is "Ssl2 | Tls". I had only had enabled Tls 1.1 and 1.2 on my server. This indeed fixed the problem! For LetsEncrypt with nginX on linux, the protocols are defined here: /etc/letsencrypt/options-ssl-nginx.conf – Jerther Oct 03 '17 at 13:18
  • 1
    I believe this is dealing with a different issue. It's not about invalid Certs but a higher TLS versions. – wp78de Dec 21 '17 at 05:20
18

This link will be of interest to you: http://msdn.microsoft.com/en-us/library/ds8bxk2a.aspx

For http connections, the WebRequest and WebResponse classes use SSL to communicate with web hosts that support SSL. The decision to use SSL is made by the WebRequest class, based on the URI it is given. If the URI begins with "https:", SSL is used; if the URI begins with "http:", an unencrypted connection is used.

GurdeepS
  • 65,107
  • 109
  • 251
  • 387
0

As the most voted answer by @LukeDuff correctly says, it is probable that the server uses an invalid or untrusted (or self-signed, what is technically also untrusted) certificate. But the answer blindly accepts any certificate. And what's worse, even any certificate for any site, even for sites, where you expect trusted and valid certificate. That's a security flaw.

When implementing ServicePointManager.ServerCertificateValidation callback one should validate the certificate. E.g. by checking certificate's hash against a known value:

using System.Net;
using System.Net.Security;
using System.Security.Cryptography;
ServicePointManager.ServerCertificateValidationCallback +=
    (sender, certificate, chain, errors) =>
    {
        return
            (errors == SslPolicyErrors.None) ||
            certificate.GetCertHashString(HashAlgorithmName.SHA256).Equals(
                "EB8E0B28AE064ED58CBED9DAEB46CFEB3BD7ECA677...");
    };

For the X509Certificate.GetCertHashString overload that takes HashAlgorithmName.SHA256, you need .NET 4.8. On older versions use the parameter-less overload that returns an SHA-1 hash.


Based on Is it safe to test the X509Certificate.Thumbprint property when you know an invalid certificate is safe?

For VB.NET version of the code, see Accept self-signed TLS/SSL certificate in VB.NET.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992