Describe the bug
MqttClientDefaultCertificateValidationHandler does not seem to be used by default when using tls with the MqttClient, instead a method called InternalUserCertificateValidationCallback in MqttTcpChannel is handling the certificate.
This causes several settings to be ignored that MqttClientDefaultCertificateValidationHandler handles correctly:
- IgnoreCertificateRevocationErrors
- AllowUntrustedCertificates
Which component is your bug related to?
- Client
- ManagedClient (unsure)
To Reproduce
Steps to reproduce the behavior:
- Using this version of MQTTnet 5.1.0.1559.
- Run this code:
var mqttClientOptions = new MqttClientOptionsBuilder()
.WithTcpServer("untrusted cert server", untrustercertserverport)
.WithTlsOptions(b =>
{
b.UseTls(true);
// this setting is ignored by default
b.WithAllowUntrustedCertificates(true);
// this will make the sample work as expected:
//b.WithCertificateValidationHandler(MqttClientDefaultCertificateValidationHandler.Handle);
})
.Build();
await client.ConnectAsync(mqttClientOptions, token);
- See error:
System.Security.Authentication.AuthenticationException: 'The remote certificate was rejected by the provided RemoteCertificateValidationCallback.'
Expected behavior
WithAllowUntrustedCertificates should work by default without setting the MqttClientDefaultCertificateValidationHandler
Screenshots
N/A
Additional context / logging
Source of MqttClientDefaultCertificateValidationHandler:
public static bool Handle(MqttClientCertificateValidationEventArgs eventArgs)
{
if (eventArgs.SslPolicyErrors == SslPolicyErrors.None)
{
return true;
}
if (eventArgs.Chain.ChainStatus.Any(
c => c.Status is X509ChainStatusFlags.RevocationStatusUnknown or X509ChainStatusFlags.Revoked or X509ChainStatusFlags.OfflineRevocation))
{
if (eventArgs.ClientOptions?.TlsOptions?.IgnoreCertificateRevocationErrors != true)
{
return false;
}
}
if (eventArgs.Chain.ChainStatus.Any(c => c.Status == X509ChainStatusFlags.PartialChain))
{
if (eventArgs.ClientOptions?.TlsOptions?.IgnoreCertificateChainErrors != true)
{
return false;
}
}
return eventArgs.ClientOptions?.TlsOptions?.AllowUntrustedCertificates == true;
}
Source of InternalUserCertificateValidationCallback:
bool InternalUserCertificateValidationCallback(object sender, X509Certificate x509Certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
var certificateValidationHandler = _tcpOptions?.TlsOptions?.CertificateValidationHandler;
if (certificateValidationHandler != null)
{
var eventArgs = new MqttClientCertificateValidationEventArgs(x509Certificate, chain, sslPolicyErrors, _tcpOptions);
return certificateValidationHandler(eventArgs);
}
if (_tcpOptions?.TlsOptions?.IgnoreCertificateChainErrors ?? false)
{
sslPolicyErrors &= ~SslPolicyErrors.RemoteCertificateChainErrors;
}
return sslPolicyErrors == SslPolicyErrors.None;
}
Code example
Provided above.
Describe the bug
MqttClientDefaultCertificateValidationHandler does not seem to be used by default when using tls with the MqttClient, instead a method called InternalUserCertificateValidationCallback in MqttTcpChannel is handling the certificate.
This causes several settings to be ignored that MqttClientDefaultCertificateValidationHandler handles correctly:
Which component is your bug related to?
To Reproduce
Steps to reproduce the behavior:
System.Security.Authentication.AuthenticationException: 'The remote certificate was rejected by the provided RemoteCertificateValidationCallback.'
Expected behavior
WithAllowUntrustedCertificates should work by default without setting the MqttClientDefaultCertificateValidationHandler
Screenshots
N/A
Additional context / logging
Source of MqttClientDefaultCertificateValidationHandler:
Source of InternalUserCertificateValidationCallback:
Code example
Provided above.