MQTTnet is a high performance .NET library for MQTT based communication. It provides a MQTT client and a MQTT server (broker). The implementation is based on the documentation from http://mqtt.org/.
MIT License
4.51k
stars
1.07k
forks
source link
Open SSL Bad cert on linux: Interop+Crypto+OpenSslCryptographicException: error:14094412:SSL routines:ssl3_read_bytes:sslv3 alert bad certificate #922
Everything works fine on Windows but when I publish from our test or prod platform I get this error from OpenSSL:
Interop+Crypto+OpenSslCryptographicException: error:14094412:SSL routines:ssl3_read_bytes:sslv3 alert bad certificate.
The error occurs when publishing a message from our API. We use AWS IoT Core over HTTPS with TLS.
The API is running in a Fargate container (docker) on Amazon Linux. I have checked that the certs are in the container and are as expected.
I add the certs to the store - because, well, why not - and on the 2nd pass it tells me the certs are in the store, but I just use the version from file.
Ive tried with and without passwords - null or empty string. Every combo I can think of.
Ive been churning on this for days. Im hoping someone here and spot my stupid mistake (95% normal for me).
Thanks
` public async Task Send(Agent agent, IQueueMessage msg)
{
var json = JsonConvert.SerializeObject(msg);
var bytes = System.Text.Encoding.UTF8.GetBytes(json);
var topic = agent.IoTTopic + "/" + msg.Type;
var mqmsg = new MqttApplicationMessageBuilder()
.WithTopic(topic)
.WithPayload(bytes)
.WithQualityOfServiceLevel(MQTTnet.Protocol.MqttQualityOfServiceLevel.AtMostOnce)
.Build();
CheckConnected();
await _connection.PublishAsync(mqmsg);
}
private void CheckConnected()
{
if (_factory == null)
{
_factory = new MqttFactory();
}
if (_connection == null || !_connection.IsConnected)
{
var tlsOptions = new MqttClientOptionsBuilderTlsParameters
{
UseTls = true,
AllowUntrustedCertificates = true,
SslProtocol = SslProtocols.Tls12,
Certificates = GetCertsList(),
CertificateValidationCallback = (X509Certificate x, X509Chain y, SslPolicyErrors z, IMqttClientOptions o) =>
{
return true;
}
};
_connection = _factory.CreateManagedMqttClient(new MQTTLogger(_logger));
var options = new ManagedMqttClientOptionsBuilder()
.WithAutoReconnectDelay(TimeSpan.FromSeconds(5))
.WithClientOptions(new MqttClientOptionsBuilder()
.WithClientId(_settings.Value.IoTClientID)
.WithCommunicationTimeout(TimeSpan.FromSeconds(10))
.WithTcpServer(_settings.Value.IoTEndpoint, _settings.Value.IoTPort)
.WithTls(tlsOptions).Build())
.Build();
_connection.ConnectedHandler = new MqttClientConnectedHandlerDelegate(async e =>
{
_logger.LogInformation("MQTT connected");
});
_connection.ConnectingFailedHandler = new ConnectingFailedHandlerDelegate(e =>
{
_logger.LogError(e.Exception, "MQTT connection failed");
});
_connection.ApplicationMessageProcessedHandler = new ApplicationMessageProcessedHandlerDelegate(e =>
{
if (e.HasSucceeded)
{
_logger.LogDebug($"MQTT {e.ApplicationMessage.Id} Message published");
}
else if (e.HasFailed)
{
if (e.Exception != null)
{
_logger.LogError(e.Exception, "MQTT Publish failed");
}
else
{
_logger.LogError("MQTT Publish failed for unknown reason");
}
}
});
_connection.StartAsync(options).Wait();
}
}
private List<X509Certificate2> GetCertsList()
{
return new List<X509Certificate2>
{
GetCert(_settings.Value.CARootCertificateFile, null),
GetCert(_settings.Value.IoTCertificateFile, "mybigsecret")
};
}
private X509Certificate2 GetCert(string certFileName, string password = "")
{
try
{
var cert = new X509Certificate2(GetCertBytes(certFileName), password, X509KeyStorageFlags.PersistKeySet);
//if (cert.Verify())
//{
// _logger.LogInformation($"Loaded cert {certFileName} and verifide ok");
//}
//else
//{
// _logger.LogError($"Loaded cert {certFileName} and NOT verifide ok");
//}
using (X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser, OpenFlags.ReadWrite))
{
if (store.Certificates.Find(X509FindType.FindByThumbprint, cert.Thumbprint, false) == null)
{
_logger.LogInformation($"Writing certificate {cert.Thumbprint} to store");
store.Add(cert);
}
else
{
_logger.LogInformation($"Certificate {cert.Thumbprint} already in store");
}
}
return cert;
}
catch (Exception ex)
{
_logger.LogError(ex, $"Invalid certificate {certFileName}");
throw;
}
}
private byte[] GetCertBytes(string certFileName)
{
if (certFileName.StartsWith("~"))
{
var basePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
certFileName = certFileName.Replace("~", basePath);
}
if (!File.Exists(certFileName))
{
throw new Exception($"Certfile {certFileName} missing.");
}
return File.ReadAllBytes(certFileName);
}
`
There are no exceptions raised from my checks - cert file exists etc.
Full stace below.
Which project is your question related to?
ManagedClient
Nuget version: 3.0.9
.Net Core v 3.1 Web API project
Stack Trace:
MQTTnet.Exceptions.MqttCommunicationException: Authentication failed, see inner exception.
---> System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception.
---> Interop+OpenSsl+SslException: SSL Handshake failed with OpenSSL error - SSL_ERROR_SSL.
---> Interop+Crypto+OpenSslCryptographicException: error:14094412:SSL routines:ssl3_read_bytes:sslv3 alert bad certificate
--- End of inner exception stack trace ---
at Interop.OpenSsl.DoSslHandshake(SafeSslHandle context, Byte[] recvBuf, Int32 recvOffset, Int32 recvCount, Byte[]& sendBuf, Int32& sendCount)
at System.Net.Security.SslStreamPal.HandshakeInternal(SafeFreeCredentials credential, SafeDeleteContext& context, ArraySegment1 inputBuffer, Byte[]& outputBuffer, SslAuthenticationOptions sslAuthenticationOptions) --- End of inner exception stack trace --- at System.Net.Security.SslStream.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, ExceptionDispatchInfo exception) at System.Net.Security.SslStream.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslStream.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslStream.PartialFrameCallback(AsyncProtocolRequest asyncRequest) --- End of stack trace from previous location where exception was thrown --- at System.Net.Security.SslStream.InternalEndProcessAuthentication(LazyAsyncResult lazyResult) at System.Net.Security.SslStream.EndProcessAuthentication(IAsyncResult result) at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult) at System.Net.Security.SslStream.<>c.<AuthenticateAsClientAsync>b__64_2(IAsyncResult iar) at System.Threading.Tasks.TaskFactory1.FromAsyncCoreLogic(IAsyncResult iar, Func2 endFunction, Action1 endAction, Task1 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(Func2 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 MQTTnet.Extensions.ManagedClient.ManagedMqttClient.ReconnectIfRequiredAsync()
Describe your question
Everything works fine on Windows but when I publish from our test or prod platform I get this error from OpenSSL:
The error occurs when publishing a message from our API. We use AWS IoT Core over HTTPS with TLS.
The API is running in a Fargate container (docker) on Amazon Linux. I have checked that the certs are in the container and are as expected.
I add the certs to the store - because, well, why not - and on the 2nd pass it tells me the certs are in the store, but I just use the version from file.
Ive tried with and without passwords - null or empty string. Every combo I can think of.
Ive been churning on this for days. Im hoping someone here and spot my stupid mistake (95% normal for me).
Thanks
` public async Task Send(Agent agent, IQueueMessage msg) { var json = JsonConvert.SerializeObject(msg); var bytes = System.Text.Encoding.UTF8.GetBytes(json);
` There are no exceptions raised from my checks - cert file exists etc.
Full stace below.
Which project is your question related to?
Nuget version: 3.0.9 .Net Core v 3.1 Web API project
Stack Trace:
MQTTnet.Exceptions.MqttCommunicationException: Authentication failed, see inner exception. ---> System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception. ---> Interop+OpenSsl+SslException: SSL Handshake failed with OpenSSL error - SSL_ERROR_SSL. ---> Interop+Crypto+OpenSslCryptographicException: error:14094412:SSL routines:ssl3_read_bytes:sslv3 alert bad certificate --- End of inner exception stack trace --- at Interop.OpenSsl.DoSslHandshake(SafeSslHandle context, Byte[] recvBuf, Int32 recvOffset, Int32 recvCount, Byte[]& sendBuf, Int32& sendCount) at System.Net.Security.SslStreamPal.HandshakeInternal(SafeFreeCredentials credential, SafeDeleteContext& context, ArraySegment
1 inputBuffer, Byte[]& outputBuffer, SslAuthenticationOptions sslAuthenticationOptions) --- End of inner exception stack trace --- at System.Net.Security.SslStream.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, ExceptionDispatchInfo exception) at System.Net.Security.SslStream.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslStream.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslStream.PartialFrameCallback(AsyncProtocolRequest asyncRequest) --- End of stack trace from previous location where exception was thrown --- at System.Net.Security.SslStream.InternalEndProcessAuthentication(LazyAsyncResult lazyResult) at System.Net.Security.SslStream.EndProcessAuthentication(IAsyncResult result) at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult) at System.Net.Security.SslStream.<>c.<AuthenticateAsClientAsync>b__64_2(IAsyncResult iar) at System.Threading.Tasks.TaskFactory
1.FromAsyncCoreLogic(IAsyncResult iar, Func2 endFunction, Action
1 endAction, Task1 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 MQTTnet.Extensions.ManagedClient.ManagedMqttClient.ReconnectIfRequiredAsync()