2

I have a download method in C#. The method sends request to the URL to be downloaded. But it gives error for some URL address. The last URL that has problem I faced is an exe file link.

My method:

    void DownloadProcedure()
    {

        #region Request-Response

        req = WebRequest.Create(url) as HttpWebRequest;
        req.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)";
        req.AllowAutoRedirect = true;
        req.MaximumAutomaticRedirections = 5;
        req.ServicePoint.ConnectionLimit += 2;
        req.ServicePoint.Expect100Continue = true;
        req.ProtocolVersion = HttpVersion.Version10;
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
            | SecurityProtocolType.Tls11
            | SecurityProtocolType.Tls12
            | SecurityProtocolType.Ssl3;
        // allows for validation of SSL conversations
        ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
        if (rangeAllowed)
            req.AddRange(from, to);
        resp = req.GetResponse() as HttpWebResponse;

        #endregion

        //...bla bla...
     }  

In this code at GetResponse() line it throws Could not create SSL/TSL secure channel. But it doesn't throw it always. Sometimes the file is downloaded successfully and sometimes it throws this exception. I don't know what is the right way to get through it.

So how can I fix this problem?A

Julian
  • 33,915
  • 22
  • 119
  • 174
Ali Tor
  • 2,772
  • 2
  • 27
  • 58
  • First, this line should be for debugging only. ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; Please do not put this code into production. – granadaCoder Nov 08 '16 at 22:30
  • 1
    Use this code to look at the cert in question. ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(( sender, cert, chain, ssl) => { Console.WriteLine("ServerCertificateValidationCallback for Cert.Subject : '{0}'", cert.Subject); System.Net.HttpWebRequest hwr = sender as System.Net.HttpWebRequest; if (null != hwr) { SecurityShower.ShowHttpWebRequest(hwr); } SecurityShower.ShowCertAndChain(cert, chain); return true; }); – granadaCoder Nov 08 '16 at 22:31
  • You can get the ShowCertAndChain code here: https://granadacoder.wordpress.com/2016/11/04/service-bus-and-custom-self-signed-certificates-with-a-high-availabilitymultiple-computing-nodes-in-the-farm/ – granadaCoder Nov 08 '16 at 22:32
  • @granadaCoder, I used it, But I can't understand the output. Because I have not enough knowledge about certificates and handshakings. How can I use it to solve the problem? – Ali Tor Nov 08 '16 at 23:02
  • Would be interesting to try the failing URL in a web browser. Try it. – Roman Polunin Nov 23 '16 at 01:43
  • Have you tried turning off SecurityProtocolType.Ssl3? Just ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; Also, tell us when do you set it? I would try to set ServicePointManager.SecurityProtocol only once at entry point in the application and don't change it later. That might be the problem. – piotrwest Nov 25 '16 at 08:06
  • Create a log for your application using http://ferozedaud.blogspot.com/2009/08/tracing-with-systemnet.html. Then the logfile should help you figure out the problem. – feroze Dec 12 '16 at 02:05

2 Answers2

0

If you are experiencing this problem for different urls: You are forcing Http 1.0. Curently, Http 1.0, 1.1 and 2. available. May you should not limit your self with Http 1.0. Also some servers still use old SSL versions so may you want to add support for them...

efaruk
  • 882
  • 9
  • 25
  • I'm not recommending to use "Heart Bleed Version", I have just mentioned, may failed url uses older versions. He is implementing client not a server... – efaruk Nov 26 '16 at 07:50
0

I'm not sure about diagnosing the specific problem from the code you have posted, but I think you can make a more general point about how specific your WebRequest is. There are no guarantees about what certificates, protocols or cipher suites are enabled on any particular remote server nor are there any guarantees about what is enabled or restricted on the computer that is running your code.

In particular I have seen similar errors when registry settings on your own server prevent the connection.

SSL3 is broken and unless you have a good reason (ie a specific site you need to access) then I would question why you explicitly want to support it. This interesting blog from 2 years ago suggests that 98.7% of websites support TLS1.0.

Unless you have good reasons not outlined in the orginal post why not just do something like:

Uri uri = new Uri(url);
if (uri.Scheme != "https")
    throw new ArgumentException("must use https");

WebRequest webRequest = WebRequest.Create(uri);
WebResponse webResponse = webRequest.GetResponse();

Then it is proof against future changes, like the day (hopefully a long time from now) when TLS is broken and deprecated. Also any changes such as requiring TLS1.2 or entirely removing SSLv3 sites can be accomplished by changing the settings on the host machine, not redeploying the code.

ste-fu
  • 6,879
  • 3
  • 27
  • 46