dotnet / dotnet/MQTTnet

client can connect using tls 1.2, but the client certificates from MqttServer_ValidatingConnectionAsync are always null on the server

Open
#1,669 3 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
C#
Stars
5.1k
Forks
1.2k
PR merge metrics
No merged PRs in 30d

Description

### Verification

Before opening a bug make sure that the following conditions are met.

1. Performance issues are also appearing in RELEASE mode of your application.
2. An increased memory consumption or high CPU load also happens when your application runs in RELEASE mode AND logging is DISABLED.
3. Client issues with not received messages, connection drops etc. can be reproduced via another client application like "MQTTnetApp" (https://github.com/chkr1011/MQTTnetApp) or similar.
4. The bug also appears in the VERY LATEST version of this library. There is no support for older version (due to limited resources) but pull requests for older versions are welcome.

### Describe the bug
Using the latest version of this lib on .net 4.8. The client can connect usingTls 1.2, but the server always shows the certificate as null. Consequently, I cannot verify the client cert on the server. All other aspects function correctly (subscriptions, publish, etc.) Moreover, both the client and the server are running on the same machine. I can use the client cert (pfx) to authenticate via https, and the cert is passed correctly.

### Which component is your bug related to?

- Client
- Server

### To Reproduce
Steps to reproduce the behavior:
1. Using this version of MQTTnet '...'.
2. Run this code '....'.
3. With these arguments '....'.
4. See error.

### Expected behavior
A clear and concise description of what you expected to happen.

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

### Additional context / logging
Add any other context about the problem here.
Include debugging or logging information here:

```batch
\\ Put your logging output here.
```
### Code example
Please provide full code examples below where possible to make it easier for the developers to check your issues.

**Ideally a Unit Test (which shows the error) is provided so that the behavior can be reproduced easily.**

private static async Task MqttClientConnect(string ipAddress, int port = 2883,
string userName=null, string userPassword=null, string clientId = null,
string pfxFilePath = "", string pfxFilePassword = "", string CaCertFilepath = "",
string connectTimespan="00:00:03", MqttProtocolVersion version = MqttProtocolVersion.V500, bool cleanSession = true,
string keepAliveTimespan = "01:00:00:00")
{

MqttFactory mqttFactory = null;
IMqttClient mqttClient = null;
TimeSpan klTimeSpan = new TimeSpan();
TimeSpan connTimeSpan = new TimeSpan();
CancellationTokenSource timerToken = null;

MqttClientOptions mqttClientOptions = null;

try
{
if(string.IsNullOrEmpty(ipAddress)) { return null; }

mqttFactory = new MqttFactory();
mqttClient = mqttFactory.CreateMqttClient();

if (!TimeSpan.TryParse(keepAliveTimespan, out klTimeSpan)) { klTimeSpan = new TimeSpan(1,0, 0, 0); }
if (!TimeSpan.TryParse(connectTimespan, out connTimeSpan)) { connTimeSpan = new TimeSpan(0, 0, 3); }

timerToken = new CancellationTokenSource(TimeSpan.FromSeconds(connTimeSpan.TotalSeconds));

if (!string.IsNullOrEmpty(pfxFilePath) && !string.IsNullOrEmpty(pfxFilePassword) &&
!string.IsNullOrEmpty(CaCertFilepath) )
{
var caCert = new X509Certificate2(@CaCertFilepath);
var clientCert = new X509Certificate2(@pfxFilePath, pfxFilePassword);
var tlsParas = new MqttClientOptionsBuilderTlsParameters();
tlsParas.UseTls = true;
tlsParas.SslProtocol = System.Security.Authentication.SslProtocols.Tls12;
tlsParas.Certificates = new List() { caCert,clientCert };
tlsParas.AllowUntrustedCertificates = false;
tlsParas.IgnoreCertificateChainErrors = false;
tlsParas.IgnoreCertificateRevocationErrors = false;

//tlsParas.CertificateValidationHandler = _ => true;

tlsParas.CertificateValidationHandler = (certCheck) =>
{
Console.WriteLine("======================================================================");
string certSubject = certCheck.Certificate.Subject;
Console.WriteLine("certSubject: " + certSubject);
string certExpirationDate = certCheck.Certificate.GetExpirationDateString();
Console.WriteLine("certExpirationDate: " + certExpirationDate);
var chainPolicy = certCheck.Chain.ChainPolicy.RevocationMode;
Console.WriteLine("chainPolicy: " + chainPolicy.ToString());
var chainStatus = certCheck.Chain.ChainStatus;
int chainStatusLength = chainStatus.Length;
Console.WriteLine("chainStatus: " + chainStatus.ToString());
Console.WriteLine("chainStatusLength: " + chainStatusLength.ToString());
var sslPolicyErrors = certCheck.SslPolicyErrors;

Console.WriteLine("sslPolicyErrors: " + sslPolicyErrors.ToString());
var cert = certCheck.Certificate;
Console.WriteLine("cert: " + cert.ToString());
var chain = certCheck.Chain;
Console.WriteLine("chain: " + chain.ToString());
string publicKey = certCheck.Certificate.GetPublicKeyString();
Console.WriteLine("publicKey: " + publicKey.ToString());

Console.WriteLine("======================================================================");

return true;
};

mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer(ipAddress, port)
.WithCredentials(userName, userPassword)
.WithTls(tlsParas)
.Build();

}
else
{
mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer(ipAddress, port)
.WithCredentials(userName, userPassword)
.Build();
}

mqttClientOptions.ProtocolVersion = version;
mqttClientOptions.ClientId = clientId;
mqttClientOptions.KeepAlivePeriod = klTimeSpan;
mqttClientOptions.Timeout = connTimeSpan;
mqttClientOptions.RequestResponseInformation = true;

// In MQTTv5 the response contains much more information.

var response = await mqttClient.ConnectAsync(mqttClientOptions, timerToken.Token);
Console.WriteLine("Broker Port: " + port + " ----> Result Code: " + response.ResultCode);
//if(response.ResultCode != MqttClientConnectResultCode.Success) { mqttClient = null; }

//response.DumpToConsole();
}
catch (Exception ex) { }
return mqttClient;

}

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with the client TLS setup in the supplied MqttClientConnect example and the server's MqttServer_ValidatingConnectionAsync callback. Reproduce on .NET Framework 4.8 using TLS 1.2 and the provided certificates, then verify that the server receives the client certificate and that a regression test covers the behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
backend, networking, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.