0

I have a WCF service app and client app that I have written. I have been using BasicHTTPBinding on both ends.

To be clear: This is NOT a web application. The service is self-hosted in a PC application (NOT IIS). All configuration of the endpoints on both the client and server are done in code, not in app.config. In fact, to make sure, I have commented out the entire System.Servicemodel sections of app.config for both the client and server applications, and everything works great. This is all using BasicHTTPBinding.

Now, I want to change everything to use HTTPS instead of HTTP, for security reasons. I have changed what I thought I needed to change in my code, but it's not working.

Original Code (This works fine!)

Server:

BasicHttpBinding _binding;            
Service1 _generalService;
ServiceHost _generalHost;

_binding = new BasicHttpBinding();
_binding.MaxReceivedMessageSize = 1000000;
_generalService = new Service1(_dbConnParams, _imagePath, _registrationProvider, LicenseCount);
_generalHost = new ServiceHost(_generalService, new Uri("http://localhost:8000"));
_generalHost.AddServiceEndpoint(typeof(IService1), _binding, "Service1");
_generalHost.Open();

Client:

internal static ToOrson.IService1 SetupService(string ServerAddress, TimeSpan? timeout = null)
{
    var myBinding = new BasicHttpBinding();
    myBinding.MaxReceivedMessageSize = 1000000;

    if (timeout != null)
        myBinding.SendTimeout = (TimeSpan)timeout;

    string fullAddress = string.Format("http://{0}:8000/Service1", ServerAddress);
    var myEndpoint = new EndpointAddress(fullAddress);
    var myChannelFactory = new ChannelFactory<ToOrson.IService1>(myBinding, myEndpoint);

    return myChannelFactory.CreateChannel();
}

private async void TestButton_Click(object sender, RoutedEventArgs e)
{
    var TestService = MainWindow.SetupService(ServerBox.Text);

    try
    {
        await TestService.TestConnectionAsync();
    }
    catch (Exception connException)
    {
        MessageBox.Show("Connection failed: " + connException.Message, "Error");
        return;
    }

    MessageBox.Show("Connection succeeded!", "Success");
}

Code modified for HTTPS (This does NOT work)

Server:

BasicHttpsBinding _binding;            
Service1 _generalService;
ServiceHost _generalHost;

_binding = new BasicHttpsBinding();
_binding.MaxReceivedMessageSize = 1000000;
_generalService = new Service1(_dbConnParams, _imagePath, _registrationProvider, LicenseCount);
_generalHost = new ServiceHost(_generalService, new Uri("https://localhost:8000"));
_generalHost.AddServiceEndpoint(typeof(IService1), _binding, "Service1");
_generalHost.Open();

Client:

internal static ToOrson.IService1 SetupService(string ServerAddress, TimeSpan? timeout = null)
{
    var myBinding = new BasicHttpsBinding();
    myBinding.MaxReceivedMessageSize = 1000000;

    if (timeout != null)
        myBinding.SendTimeout = (TimeSpan)timeout;

    string fullAddress = string.Format("https://{0}:8000/Service1", ServerAddress);
    var myEndpoint = new EndpointAddress(fullAddress);
    var myChannelFactory = new ChannelFactory<ToOrson.IService1>(myBinding, myEndpoint);

    return myChannelFactory.CreateChannel();
}

private async void TestButton_Click(object sender, RoutedEventArgs e)
{
    var TestService = MainWindow.SetupService(ServerBox.Text);

    try
    {
        await TestService.TestConnectionAsync();
    }
    catch (Exception connException)
    {
        MessageBox.Show("Connection failed: " + connException.Message, "Error");
        return;
    }

    MessageBox.Show("Connection succeeded!", "Success");
}

Basically, I just changed BasicHTTPBinding to BasicHTTPSBinding and HTTP:// to HTTPS:// in all places in the code.

Here is the exception that I'm getting:

System.ServiceModel.CommunicationException "An error occurred while
making the HTTP request to https://localhost:8000/Service1. This could
be due to the fact that the server certificate is not configured
properly with HTTP.SYS in the HTTPS case. This could also be caused by
a mismatch of the security binding between the client and the server."

This exception is occurring on the client, on the call to TestService.TestConnectionAsync() (which is one of my OperationContracts).

Here are the inner exceptions:

System.Net.WebException "The underlying connection was closed: An unexpected error occurred on a send."

System.IO.IOException "Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host."

System.Net.Sockets.SocketException "An existing connection was forcibly closed by the remote host"

Yes, I updated my service reference after these changes. Yes, I am targeting the .NET 4.5 framework. I don't think it's a firewall issue, as I'm using the same port (8000) in both cases, and I already have that port open.

What am I doing wrong?

JoeMjr2
  • 3,804
  • 4
  • 34
  • 62
  • 1
    Off the top of my head, I'd say that your client & server machines don't share a common trusted certificate for SSL and can't create a common encrypted channel. Although [this MSDN article](http://msdn.microsoft.com/en-us/library/ms729700(v=vs.110).aspx) is for `wsHttpBinding`, the SSL configuration aspects also apply to `basicHttpBinding`. – Sixto Saez Feb 02 '14 at 17:03
  • Ugh! For some reason, I was under the impression that certificates were only required when a web server and/or web browser was involved. I didn't think that it was required for a self-hosted service, accessed by a dedicated client app. It sounds like I may be wrong. I am trying to make my server application's installation/configuration very easy for the end user, so I don't want them to be having to deal with certificates. Is there any other simple way to ensure a secure connection between client and server? – JoeMjr2 Feb 02 '14 at 18:13
  • 1
    @JoeMjr2 yes certificates are required for SSL and are the mechanism used for passing the client/server keys and other data needed to securely encrypt the data between the client and server. See this for more info on SSL: http://security.stackexchange.com/questions/20803/how-does-ssl-work Off the top of my head, I don't know of another simple way to secure the client/server connection. In most cases in .NET there is a way to disable or write your own certification validation, so that the client will accept the SSL connection regardless of if the cert if installed on the client. – BateTech Feb 02 '14 at 18:28
  • Check out the section "An alternative solution is to provide custom logic to validate the X.509 certificate" in this answer. http://stackoverflow.com/questions/338385/how-do-i-tell-wcf-to-skip-verification-of-the-certificate – BateTech Feb 02 '14 at 18:41
  • You can try [following SO](https://stackoverflow.com/questions/10274207/https-from-a-console-application/10373991#10373991) but it also requires certificates. – Petar Vučetin Feb 03 '14 at 05:03
  • Possible duplicate of [WCF Error "This could be due to the fact that the server certificate is not configured properly with HTTP.SYS in the HTTPS case"](https://stackoverflow.com/questions/2013880/wcf-error-this-could-be-due-to-the-fact-that-the-server-certificate-is-not-conf) – kenorb Oct 02 '18 at 16:33

0 Answers0