views:

2209

answers:

2

Using VS2k5 - c#2.0, System.Net.WebClient.UploadData(Uri address, byte[] data) Windows Server 2k3

So here's a stripped down version of the code:

static string SO_method(String fullRequestString)
    {
        string theUriStringToUse = @"https://10.10.10.10:443"; // populated with real endpoint IP:port
        string proxyAddressAndPort = @"http://10.10.10.10:80/"; // populated with a real proxy IP:port
        Byte[] utf8EncodedResponse; // for the return data in utf8
        string responseString; // for the return data in utf16

        WebClient myWebClient = new WebClient(); // instantiate a web client
        WebProxy proxyObject = new WebProxy(proxyAddressAndPort, true);// instantiate & popuylate a web proxy
        myWebClient.Proxy = proxyObject; // add the proxy to the client
        myWebClient.Headers.Add("Content-Type", "application/x-www-form-urlencoded"); // stick some stuff in the header

        UTF8Encoding utf8Encoding = new UTF8Encoding(false);// create a utf8 encoding
        Byte[] utf8EncodedRequest = HttpUtility.UrlEncodeToBytes(fullRequestString, utf8Encoding); // convert the request data to a utf8 byte array

        try
        {
            utf8EncodedResponse = myWebClient.UploadData(theUriStringToUse, "POST", utf8EncodedRequest); // pass the utf8-encoded byte array
            responseString = utf8Encoding.GetString(utf8EncodedResponse); // get a useable string out of the response
        }
        catch (Exception e)
        {
            // some other error handling
            responseString = "<CommError><![CDATA[" + e.ToString() + "]]></CommError>";// show the basics of the problem
        }
        return responseString;// return whatever ya got
    }

This is the error I get: "The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel."

I don't have much control to see what's happening when the request goes out. I'm told that it's reaching the correct destination and there's a "certificate error". This is supposedly because there's a literal mismatch between the IP address in my request and the URL it resolves to. I have more than one IP I'm supposed to round-robin to so specifying the URL won't work. I'm not attaching a certificate - nor am I supposed to according to the endpoint owners. Per "them" the certificate error is 'normal and I am supposed to ignore it.

The cert in question is supposedly one of the many verisign certs that is "just there" on our server. The examples I've seen for ignoring cert errors all seem to imply that the requestor is attaching a specific x509 certificate (which I'm not).

I looked over http://stackoverflow.com/questions/721472/net-webservice-bypass-ssl-validation which kinda-sorta describes my problem - except it also kinda-sorta doesn't because I don't know which certificate (if any) I should reference.

Is there a way for me to ignore the error without actually knowing/caring what certificate is causing the problem?

  • and please - kid gloves, small words, and "for dummies" code as I'm not exactly a heavy hitter.

  • This traffic is over a private line - so my understanding is that ignoring the cert error is not as big a deal as if it were open internet traffic.

+3  A: 

The SSL certificate is for a machine to establish a trust relationship. If you type in one IP address, and end up talking to another, that sounds the same as a DNS hijack security fault, the kind of thing SSL is intending to help you avoid - and perhaps something you don't want to put up with from "them".

If you may end up talking to more than machine (ideally they would make it appear as one for you), you will need a certificate for each of the possible machines to initiate trust.

To ignore trust (I've only ever had to do this temporarily in development scenarios) the following snippet may work for you, but I strongly recommend you consider the impact of ignoring trust before using it:

    public static void InitiateSSLTrust()
    {
        try
        {
            //Change SSL checks so that all checks pass
            ServicePointManager.ServerCertificateValidationCallback =
                new RemoteCertificateValidationCallback(
                    delegate
                    { return true; }
                );
        }
        catch (Exception ex)
        {
            ActivityLog.InsertSyncActivity(ex);
        }
    }
MattH
Thanks, MattH. I'm executing the code you have in the TRY block jut prior to invoking the System.Net.WebClient.UploadData(Uri address, byte[] data) method. To say that I'm not sure what it's doing would be an understatement. I don't see the tie-in to my WebClient. However, it "appears" to be working as we seem to be getting further in our communication per the network team on my side. I found A very similar suggestion on MSDN but the words just want to bounce off my eyeballs. http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager%28VS.80%29.aspx
JohnTheBarber
In a nutshell the above code trusts anybody, and bypasses all SSL verification, and is therefore not secure.
MattH
Right - that much I got - but is this tied to my specific instance of a WebClient, my running process, or to ANY cert related "goings on" on the server once this executes? My guess is it's limited to my process but...
JohnTheBarber
Oh - yeah - This traffic is over a private line -- just added a bullet indicating as much in the question. But then I'm thinking - I know there's not a physical private cable from our site to the other party. All them wires in the middle must be sharing other traffic...
JohnTheBarber
+1  A: 

This code is much broader than you might expect. It is process-wide. The process might be the exe, IIS on this machine, or even DLLHost.exe. After calling it, have a finally block that restores things to normal by removing the delegate that always returns true.

thomas
This is a good suggestion, post it?
Mo Flanagan