1

We have created a certificate in IIS6 and applied it to a site using SSL. Now the same program we have used before will not work. As I understand it c# supports HTTPS transparently so I believe it must be with the "untrusted" cert. After turning the proxy setting off (was getting 403 forbidden error) , I receive "Could not establish trust relationship for the SSL"

I have tried a few work arounds like swapping the default cert policy with validation hack but it was very old and I still get the same error.

Below is my post method.

 try
    {
        HttpRequestCachePolicy policy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);
        HttpWebRequest.DefaultCachePolicy = policy;


        byte[] buffer = Encoding.UTF8.GetBytes(postData);
        //Initialisation
        HttpWebRequest WebReq = (HttpWebRequest)WebRequest.Create(url);
        WebReq.Timeout = 10000;
        //method is post

        if (useproxy == "ON")
        {
            WebProxy myProxy = new WebProxy();
            // Create a new Uri object.
            Uri newUri = new Uri(proxy);

            // Associate the new Uri object to the myProxy object.
            myProxy.Address = newUri;
            WebReq.Proxy = myProxy;
        }


        WebReq.KeepAlive = false;
        WebReq.Method = "POST";
        WebReq.ContentType = "application/x-www-form-urlencoded";


        //The length of the buffer 
        WebReq.ContentLength = buffer.Length;
        Stream PostData = WebReq.GetRequestStream();
        //write, and close. 
        PostData.Write(buffer, 0, buffer.Length);
        PostData.Close();

        //Get the response handle
        HttpWebResponse WebResp = (HttpWebResponse)WebReq.GetResponse();

        Console.WriteLine(WebResp.StatusCode);
        Console.WriteLine(WebResp.Server);

        //Do not worry about response!. 
        //read the response (the string), and output it.
        Stream Answer = WebResp.GetResponseStream();
        StreamReader _Answer = new StreamReader(Answer);
        vystup = _Answer.ReadToEnd();


        if (vystup != "OK")
        {

        }
    }
    catch (WebException ex)
    {

        Console.WriteLine(ex);
    }

Is there any workaround for the certificate or my app or in IIS that would resolve this? Presumably its C# not trusting the certificate but this is my first go at Https.

Any info at all is welcome.

Michael Edenfield
  • 28,070
  • 4
  • 86
  • 117
user685590
  • 2,464
  • 5
  • 30
  • 42
  • Hm. Did you consider obtaining a valid certificate? – Lakis Jun 01 '12 at 12:21
  • 1
    Note that all X.509 certificates are signed, but perhaps not by a signature that you can verify. (Yours isn't "unsigned".) – Bruno Jun 01 '12 at 12:26
  • 1
    Slight correction there Bruno. ALL certs ARE signed. However, you can "self-sign" a certificate. In that case you are not signing it with the credentials from a trusted 3rd party. – Julian Knight Jun 01 '12 at 12:45
  • @JulianKnight, yes, that's what I said, in some cases, you can't verify it's signed by a party you trust. – Bruno Jun 02 '12 at 12:40

2 Answers2

3

By default, the .NET certificate policy will reject any unverified or untrusted server certificates, since 99% of the time that's what you want. (The only "bad" certificates that get through by default are expired, but otherwise valid ones.)

You have a few options, depending on the scale of the deployment you're talking about.

  1. Install the server's certificate on the client as a trusted root certificate. For testing, this is hands down the easiest option, and I do it all the time with my dev machine's IIS and IIS Express certificates. Horrible idea for production though.

  2. Use an internal CA to generate certificate; if you work for a company that has an Active Directory setup, the AD servers can act as a CA, and you can use group policy to push the AD server's CA root out to clients automatically. If you're deploying something internally, this is a good way to go because it's pretty cheap :)

  3. Implement a ServerCertificateValidationCallback on the ServicePointManager class that ignores any SSL errors. The only real pitfall here is that this is a global setting, so every use of the WebRequest classes will use your custom validation callback.

Michael Edenfield
  • 28,070
  • 4
  • 86
  • 117
  • Thanks for the tips. I exported the cert , gave it a pass , ran it on the dev machine and placed it in trusted root. It still throws the same error!. I will have someone look at the AD solution . I will try implementing the callback on the ServicePointManager then. – user685590 Jun 01 '12 at 13:47
  • if you're exporting a cert to install on a client, you should export just the public key half, and with no password, but it should still have worked. There may be something wrong server-side, I'd check your IIS logs to make sure it could load the certificate. – Michael Edenfield Jun 01 '12 at 13:52
  • Because of our infrastructure , its easier for me to try the callback set to true. It is not going to be used outside our network anyway and its function is pretty simple. I tried ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; to no avail is that right?. – user685590 Jun 01 '12 at 14:55
  • Yes, that should work, but the fact that it doesn't, combined with the fact that even making the cert a local root cert isn't working, makes me thing the problem is something else. I'm just not sure what. – Michael Edenfield Jun 01 '12 at 15:16
  • If you consider option 1 horrible in production, option 3 is even worse. Why bother using SSL/TLS if you don't verify the certificate? – Bruno Jun 02 '12 at 12:41
  • option three lets you choose to allow your program to ignore certificate errors as needed; option one makes *every* program thing the self-signed certificate is valid without a hint that it may not be. – Michael Edenfield Jun 02 '12 at 19:22
0

I don't think this is working because you haven't requested that the WebRequest happen over SSL.

According to Microsoft, you need to add something like WebReq.EnableSsl = true;

Julian Knight
  • 4,716
  • 2
  • 29
  • 42
  • 1
    The EnableSsl Function is for FTP, Http & Https will work depending on the url. "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." – user685590 Jun 01 '12 at 13:25