Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open SSL Bad cert on linux: Interop+Crypto+OpenSslCryptographicException: error:14094412:SSL routines:ssl3_read_bytes:sslv3 alert bad certificate #922

Closed
Jonesie opened this issue May 11, 2020 · 1 comment
Labels
question It is a question regarding the project

Comments

@Jonesie
Copy link

Jonesie commented May 11, 2020

Describe your question

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()

@Jonesie Jonesie added the question It is a question regarding the project label May 11, 2020
@Jonesie
Copy link
Author

Jonesie commented May 14, 2020

Switched to using M2MQTT. Problem resolved.

@Jonesie Jonesie closed this as completed May 14, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question It is a question regarding the project
Projects
None yet
Development

No branches or pull requests

1 participant