dotnet / dotnet/wcf

WebSocket custom SSL validation only works when using client certificates

Open
#5,729 4 comments 0 reactions 2 assignees Claimed by @imcarolwang View on GitHub
feature request triaged
Dominant language
C#
Stars
1.8k
Forks
576
Avg merge
6d 9h
Merged PRs (30d)
2

Description

**Describe the bug**
It's possible to disable (or provide custom) SSL validation by setting `SslCertificateAuthentication` like in this example:

```c#

serviceCertificate.SslCertificateAuthentication = new X509ServiceCertificateAuthentication()
{
CertificateValidationMode = X509CertificateValidationMode.None,
RevocationMode = X509RevocationMode.NoCheck,
};

```

However, this only works when using client certificate authentication.
Looking at: https://github.com/dotnet/wcf/blob/f789e63e3254b9e57eee3b38c42d83d410973e7e/src/System.ServiceModel.Http/src/System/ServiceModel/Channels/ClientWebSocketTransportDuplexSessionChannel.cs#L155

It seems like the WebSocket RemoteCertificateValidationCallback is only ever set if RequireClientCertificate is true, which will only be the case when using client certificates.

It should be possible to disable or customize server SSL certificate validation regardless of the auth type being used.

**To Reproduce**
1. Create a binding where WebSockets are always enabled, without setting any client certificate auth.
```c#
var binding = new NetHttpBinding(BasicHttpSecurityMode.Transport)
{
MaxReceivedMessageSize = int.MaxValue,
WebSocketSettings = { TransportUsage = WebSocketTransportUsage.Always },
};
```

2. Disable SSL validation with:
```c#
serviceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.Custom;
serviceCertificate.Authentication.CustomCertificateValidator = new DisableCertificateValidation();
serviceCertificate.SslCertificateAuthentication = new X509ServiceCertificateAuthentication()
{
CertificateValidationMode = X509CertificateValidationMode.None,
RevocationMode = X509RevocationMode.NoCheck
};
```

3. Try to call a service that uses a self-signed SSL certificate, or one that doesn't match the domain.

**Expected behavior**
The call should succeed.

**Actual behavior**
Call fails with an error similar to this one:
```
Exception info dump:
System.ServiceModel.CommunicationException: Unable to connect to the remote server
---> System.Net.WebSockets.WebSocketException (0x80004005): Unable to connect to the remote server
---> System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure: RemoteCertificateNameMismatch
````

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Additional context**
Add any other context about the problem here.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.