MQTTnet icon indicating copy to clipboard operation
MQTTnet copied to clipboard

Regression: Certificate validation does no longer work on linux machines when upgrading from 3.0.6 to 3.0.7 or 3.0.8

Open dpsenner opened this issue 5 years ago • 4 comments

I used to build an instance of IMqttClientOptions as follows:

private IMqttClientOptions GetConnectOptions()
{
    var builder = new MqttClientOptionsBuilder()
        .WithCleanSession()
        .WithTcpServer(Configuration.Host, Configuration.Port)
        .WithProtocolVersion(MqttProtocolVersion.V311);

    if (Configuration.Auth.Enable)
    {
        builder.WithCredentials(Configuration.Auth.Username, Configuration.Auth.Password);
    }

    if (Configuration.Ssl.Enable)
    {
        builder.WithTls(parameters =>
        {
            parameters.UseTls = true;
            parameters.AllowUntrustedCertificates = Configuration.Ssl.AllowUntrustedCertificates;
        });
    }
            
    return builder.Build();
}

This used to work fine, also for ssl connections with letsencrypt certificates and AllowUntrustedCertificates=false. By bumping the version to 3.0.7 or newer it still works on windows. It doesn't on a linux (ubuntu bionic) machine where it fails with the error message The remote certificate is invalid according to the validation procedure..

dpsenner avatar Dec 12 '19 21:12 dpsenner

This is the full stacktrace of the exception:

MQTTnet.Exceptions.MqttCommunicationException: The remote certificate is invalid according to the validation procedure. ---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.
   at System.Net.Security.SslState.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, ExceptionDispatchInfo exception)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.PartialFrameCallback(AsyncProtocolRequest asyncRequest)
--- End of stack trace from previous location where exception was thrown ---
   at System.Net.Security.SslState.ThrowIfExceptional()
   at System.Net.Security.SslState.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)
   at System.Net.Security.SslState.EndProcessAuthentication(IAsyncResult result)
   at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult)
   at System.Net.Security.SslStream.<>c.<AuthenticateAsClientAsync>b__46_2(IAsyncResult iar)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
   at MQTTnet.Implementations.MqttTcpChannel.ConnectAsync(CancellationToken cancellationToken)
   at MQTTnet.Internal.MqttTaskTimeout.WaitAsync(Func`2 action, TimeSpan timeout, CancellationToken cancellationToken)
   at MQTTnet.Adapter.MqttChannelAdapter.ConnectAsync(TimeSpan timeout, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at MQTTnet.Adapter.MqttChannelAdapter.WrapException(Exception exception)
   at MQTTnet.Adapter.MqttChannelAdapter.ConnectAsync(TimeSpan timeout, CancellationToken cancellationToken)
   at MQTTnet.Client.MqttClient.ConnectAsync(IMqttClientOptions options, CancellationToken cancellationToken)
   at MQTTnet.Client.MqttClient.ConnectAsync(IMqttClientOptions options, CancellationToken cancellationToken)
   at Infrastructure.Mqtt.Internals.MqttConnectionWatchdog.ConnectAsync(CancellationToken cancellationToken)

dpsenner avatar Dec 12 '19 21:12 dpsenner

Bumping the application from netcoreapp2.2 to netcoreapp3.1 resolves the problem.

dpsenner avatar Dec 13 '19 20:12 dpsenner

For the case it helps: I got a similar error message after upgrading to 3.0.7/3.0.8 a few weeks ago ("the remote certificate is invalid according to the validation procedure"). The reason was that with this version the checking for revoked SSL certificates is turned on by default due to a bug fix (it seemed to be enabled before, but was not).

In my case the application was running on a windows machine with no possibility to communicate on port 80 due to firewall restrictions so the certificate revocation check could not be performed. I "solved" it by disabling the certificate revocation check in MqttClientOptionsBuilder on that machine. Maybe your issue is related to that and has been somehow solved by upgrading to .net core 3.1. My app was running on .net core 3.0 IIRC.

stedaho avatar Dec 20 '19 10:12 stedaho

@stedaho I observed that it worked fine on windows while it did fail on linux with ssl enabled, mqttnet >= 3.0.7 and netcoreapp2.2. This is in my opinion a hint to the cause of this issue. Can you confirm this with your usecase?

dpsenner avatar Dec 22 '19 09:12 dpsenner

I assume this issue is solved with the upgrade to netcoreapp3.1.

chkr1011 avatar Dec 05 '22 18:12 chkr1011