How to identify a specific exception from CommunicationException class? - c#

I have a WCF Service that is running on a server using the protocol TLS 1.2. My application, which uses .NET Framework 4.0, communicates with this service. It can communicate through TLS 1.2, with the code below:
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072 | (SecurityProtocolType)768 | SecurityProtocolType.Tls | SecurityProtocolType.Ssl3;
The problem is that this code will only work if the customer machine have at least the .NET Framework 4.5 installed. Also, some clients have their own servers running this WCF Service, and those use TLS 1.0. I don't want these clients to forced upgrade the .NET Framework of their employees.
So, I want to handle the CommunicationException thrown by the WCF Service, when it cannot communicate through the default SecurityProtocol (TLS 1.0). This exception has the information below:
System.ServiceModel.CommunicationException: An error occurred while making the HTTP request to https://quellon.espaider.com.br/FacilcorpHomolog/DocSite/DSAddIn.svc. 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. ---> System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send. ---> System.IO.IOException: Authentication failed because the remote party has closed the transport stream exception.
When this specific exception is thrown, I'll use the code shown in the beginning and allow the communication between my application and the service.
I want to know if there is some property or method that I can use to identify when the CommunicationException is this one. The only thing that comes to my mind is using the Message property, which I think is not a good practice.

Related

I receive a CommunicationException on any port other than 443

I have a standard n-tier application (.Net 4.7.2) with a console server and a WinForms application both running on the same machine. The client and server communicate via WCF.
I get a CommunicationException on the client when I attempt to communicate with the server if I use any port other than 443 in my address binding. not specifying a port or explicitly specifying 443 works without an issue.
The error message is;
An error occurred while making the HTTP request to
https://localhost:44333/SecurityTokenService/issue/wstrust/mixed/anonymous.
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.
here is my client binding for reference
<endpoint
address="https://localhost:44333/SecurityTokenService/issue/wstrust/mixed/anonymous"
binding="customBinding"
bindingConfiguration="MySecurityTokenEndpointBinding"
contract="System.ServiceModel.Security.IWSTrustChannelContract"
name="SecretTokenAuthenticationEndPoint" />
UPDATE: I have continued to investigate the issue myself and enabled WCF tracing. I can see from the trace logs the warning 'The Security Protocol cannot secure the outgoing message'
Make sure to use the correct way to call the wcf service, such as adding service reference, channel factory, etc. After reading your question, I think it is very likely as the error message says: 'This could also be caused by a mismatch of the security binding between the client and the server.'
You can use the following code to specify the TLS version:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls13;
TLS1.3 is the latest TLS standard protocol, which is faster and has higher security.
Here is the reference: Transport Layer Security (TLS) best practices with the .NET Framework
The solution for me was to bind the SSL certificate to the IP Address and Port that my service was being exposed on. I used the following command from a command prompt;
netsh http add sslcert ipport={ipAddress}:{port} certhash={CertificateThumbprint} appid={appId}
Some points to note
If the above command fails; ensure you have the private key imported and not just the public certificate
I don't know if the appId is an arbitrary Guid; I used the Guid from my application shell project (a console application); It's the Guid that exposes your application to 'com'
Hopefully, this helps somebody in the future

Cannot consume SOAP endpoint with .NET WCF but testing endpoint with SoapUI works

I am currently developing a .NET client (with WCF) that must consume a third-party SOAP endpoint. This third-party endpoint requires HTTPS. When I test the endpoint with SoapUI, the endpoint responds correctly. However, when I try to consume the endpoint with the .NET client, I get the following exception:
System.ServiceModel.CommunicationException: An error occurred while making the HTTP request 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.
The inner exception was:
Unable to read data from the transport connection : An existing connection was forcibly closed by the remote host
The only solution I found was to use a newer version of TLS but this did not solve the issue.

WCF Service + Client (TLS1.2 Issue)

Our Server has had SSLv3, TLS1.0 and TLS1.1 disabled. Due to this, Visual Studio fails when trying to Add Service Reference when trying to retrieve the WSDL.
"The underlying connection was closed: An unexpected error occurred on a send.
Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
An existing connection was forcibly closed by the remote host
Metadata contains a reference that cannot be resolved:
An error occurred while making the HTTP request to https://mywebsite.com/Service/Service.svc?wsdl. 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.
The underlying connection was closed: An unexpected error occurred on a send.
Authentication failed because the remote party has closed the transport stream.
If the service is defined in the current solution, try building the solution and adding the service reference again."
The WSDL is accessible in the browser. The WSDL downloads okay when TLS 1.0/1.1 and SSLv3 are enabled. However, due to PCI requirements we have to disable SSLV3, TLS1.0 and TLS1.1.
I am aware of the following System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; but am not quite sure if this would go in the connecting Console Client or the WCF Service (or both).
Any advice would be appreciated
The line below line needs to be in the client, as that is what is making the connection.
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
As per this blog TLS 1.2 and .NET Support: How to Avoid Connection Errors, the above will work for .Net 4.5
For .Net 4.6 and above it will default to TLS 1.2 and you do not need to specify TLS 1.2
For .Net 4.0 you need the below instead.
System.Net.ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
NET 3.5 or below you need to install the appropriate Microsoft Patch for your OS (listed in the blog).

Issue with Xamarin App Connecting to WCF Service over https

I am developing an Xmarain.Forms app to initially work on Android along with a service it will be connecting to. The service is a WCF service and needs to use a secure transport to send messages so is set to use https.
I can correctly connect and use the service with both SoapUI and a console program built using the same client proxy library but when I try using the Xamarin App it fails. When run in the emulator the exception is a TimeoutException but when installed on an actual device the exception is WebException with message of "Error: SecureChannelFailure (The authentication or decryption has failed" with inner exception stack of:
IOException with message "The authentication or decryption has failed"
IOException with message "Error while sending TLS Alert (Fatal:InternalError)"
IOException with message "The authentication or decryption has failed.
IOException with message "Unable to read data from the transport connection: Connection reset by peer"
The full stack trace is included below as attachments. The full code is available at https://github.com/staircase27/WcfXamarinHttpBugExample along with the instructions of how to set it up and use it. The example code has connections using both http and https to show the difference and to show that one works and the other doesn't. I have also checked while testing that the devices can access the service using their web browsers so it's not a firewall or routing issue.
I have also wiresharked the connection to see where exactly the connection is failing and it's failing at the TLS v1.0 level. The app (on both devices I've tested) is sending a Client Hello and the service is responding with a TCP RST packet rather than a Server Hello. I have also performed a connection from the testing device using a web browser that succeeded and the main differences are in the types of encryption supported specifically the app only offers to use
TLS_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_3DES_EDE_CBC_SHA
TLS_RSA_WITH_RC4_128_SHA
TLS_RSA_WITH_RC4_128_MD5
TLS_RSA_WITH_DES_CBC_SHA
where as the working connections both used
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
A filtered wireshark with two connections is at https://github.com/staircase27/WcfXamarinHttpBugExample/raw/master/Mobile%20WCF%20https%20Capture%20-%20Filtered.pcapng. The first connection is from the app and fails with a tcp rst. The second is the start of the connection from the android web browser.
I have enabled all versions of TLS and all cypher suites but it hasn't changed the wireshark trace or exception in the app.
I have also checked the SChannel Event Logs as recommended by #tomasr and found the following event:
An SSL client handshake completed successfully. The negotiated cryptographic parameters are as follows. Protocol: TLS 1.0. CipherSuite: 0xc014. Exchange strength: 256
(Before enabling all version of TLS the events were:
An TLS 1.0 connection request was received from a remote client application, but none of the cipher suites supported by the client application are supported by the server. The SSL connection request has failed.
The following fatal alert was generated: 40. The internal error state is 1205.
)
Sadly as none of the suggestions in the comments worked I have had to work around this and am now using a RESTful WCF API and have implemented the client manually using HttpClient.

How to make windows store app work with TLS 1.2?

There is a windows store app 8.1 connected to a web service via WCF. Recently TLS 1.2 has been set at the server and as a result the app stopped working. Here is the exception
An error occurred while making the HTTP request to
https://services.companyname.com 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.
Even a simple web request
WebRequest request = WebRequest.Create(SERVER_URL_PROD);
WebResponse response = await request.GetResponseAsync();
returns the following
An exception of type 'System.Net.WebException' occurred in
mscorlib.dll but was not handled in user code
Additional information: The underlying connection was closed: An
unexpected error occurred on a send.
So how to make windows store app work with TLS 1.2 ?
Update
The code above works in a console app (.NET 4.5) if
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
But ServicePointManager is not available for Windows Store apps
Update 2
Moreover the code works in Windows Phone 8.1 where ServicePointManager is not available.
I've dealt with the TLS 1.2 issue for web applications, and as OP mentions, the simple solution for System.Net.ServicePointManager doesn't work in Windows Store apps.
The workaround is to use Windows.Web.Http instead of System.Net.Http as described in this MSDN forum posting.

Categories

Resources