mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-18 10:26:11 +08:00
Add custom certificate validation handler
This commit is contained in:
@@ -46,6 +46,8 @@ namespace MQTTnet.Implementations
|
||||
public Stream ReceiveStream { get; private set; }
|
||||
public Stream RawReceiveStream { get; private set; }
|
||||
|
||||
public static Func<X509Certificate, X509Chain, SslPolicyErrors, MqttClientTcpOptions, bool> CustomCertificateValidationCallback { get; set; }
|
||||
|
||||
public async Task ConnectAsync()
|
||||
{
|
||||
if (_socket == null)
|
||||
@@ -57,7 +59,7 @@ namespace MQTTnet.Implementations
|
||||
|
||||
if (_options.TlsOptions.UseTls)
|
||||
{
|
||||
_sslStream = new SslStream(new NetworkStream(_socket, true), false, UserCertificateValidationCallback);
|
||||
_sslStream = new SslStream(new NetworkStream(_socket, true), false, InternalUserCertificateValidationCallback);
|
||||
await _sslStream.AuthenticateAsClientAsync(_options.Server, LoadCertificates(_options), SslProtocols.Tls12, _options.TlsOptions.IgnoreCertificateRevocationErrors).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -98,8 +100,13 @@ namespace MQTTnet.Implementations
|
||||
ReceiveStream = new BufferedStream(RawReceiveStream, BufferSize);
|
||||
}
|
||||
|
||||
private bool UserCertificateValidationCallback(object sender, X509Certificate x509Certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
|
||||
private bool InternalUserCertificateValidationCallback(object sender, X509Certificate x509Certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
|
||||
{
|
||||
if (CustomCertificateValidationCallback != null)
|
||||
{
|
||||
return CustomCertificateValidationCallback(x509Certificate, chain, sslPolicyErrors, _options);
|
||||
}
|
||||
|
||||
if (sslPolicyErrors == SslPolicyErrors.None)
|
||||
{
|
||||
return true;
|
||||
|
||||
@@ -40,7 +40,9 @@ namespace MQTTnet.Implementations
|
||||
public Stream SendStream => ReceiveStream;
|
||||
public Stream ReceiveStream { get; private set; }
|
||||
public Stream RawReceiveStream => ReceiveStream;
|
||||
|
||||
|
||||
public static Func<X509Certificate, X509Chain, SslPolicyErrors, MqttClientTcpOptions, bool> CustomCertificateValidationCallback { get; set; }
|
||||
|
||||
public async Task ConnectAsync()
|
||||
{
|
||||
if (_socket == null)
|
||||
@@ -52,7 +54,7 @@ namespace MQTTnet.Implementations
|
||||
|
||||
if (_options.TlsOptions.UseTls)
|
||||
{
|
||||
_sslStream = new SslStream(new NetworkStream(_socket, true), false, UserCertificateValidationCallback);
|
||||
_sslStream = new SslStream(new NetworkStream(_socket, true), false, InternalUserCertificateValidationCallback);
|
||||
ReceiveStream = _sslStream;
|
||||
await _sslStream.AuthenticateAsClientAsync(_options.Server, LoadCertificates(_options), SslProtocols.Tls12, _options.TlsOptions.IgnoreCertificateRevocationErrors).ConfigureAwait(false);
|
||||
}
|
||||
@@ -77,8 +79,13 @@ namespace MQTTnet.Implementations
|
||||
_sslStream = null;
|
||||
}
|
||||
|
||||
private bool UserCertificateValidationCallback(object sender, X509Certificate x509Certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
|
||||
private bool InternalUserCertificateValidationCallback(object sender, X509Certificate x509Certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
|
||||
{
|
||||
if (CustomCertificateValidationCallback != null)
|
||||
{
|
||||
return CustomCertificateValidationCallback(x509Certificate, chain, sslPolicyErrors, _options);
|
||||
}
|
||||
|
||||
if (sslPolicyErrors == SslPolicyErrors.None)
|
||||
{
|
||||
return true;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
@@ -32,6 +33,8 @@ namespace MQTTnet.Implementations
|
||||
public Stream ReceiveStream { get; private set; }
|
||||
public Stream RawReceiveStream { get; private set; }
|
||||
|
||||
public Func<MqttClientTcpOptions, IEnumerable<ChainValidationResult>> CustomIgnorableServerCertificateErrorsResolver { get; set; }
|
||||
|
||||
public async Task ConnectAsync()
|
||||
{
|
||||
if (_socket == null)
|
||||
@@ -47,23 +50,11 @@ namespace MQTTnet.Implementations
|
||||
{
|
||||
_socket.Control.ClientCertificate = LoadCertificate(_options);
|
||||
|
||||
if (_options.TlsOptions.IgnoreCertificateRevocationErrors)
|
||||
foreach (var ignorableChainValidationResult in ResolveIgnorableServerCertificateErrors())
|
||||
{
|
||||
_socket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.RevocationInformationMissing);
|
||||
//_socket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.Revoked); Not supported.
|
||||
_socket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.RevocationFailure);
|
||||
_socket.Control.IgnorableServerCertificateErrors.Add(ignorableChainValidationResult);
|
||||
}
|
||||
|
||||
if (_options.TlsOptions.IgnoreCertificateChainErrors)
|
||||
{
|
||||
_socket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.IncompleteChain);
|
||||
}
|
||||
|
||||
if (_options.TlsOptions.AllowUntrustedCertificates)
|
||||
{
|
||||
_socket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted);
|
||||
}
|
||||
|
||||
await _socket.ConnectAsync(new HostName(_options.Server), _options.GetPort().ToString(), SocketProtectionLevel.Tls12);
|
||||
}
|
||||
|
||||
@@ -112,5 +103,34 @@ namespace MQTTnet.Implementations
|
||||
|
||||
return new Certificate(options.TlsOptions.Certificates.First().AsBuffer());
|
||||
}
|
||||
|
||||
private IEnumerable<ChainValidationResult> ResolveIgnorableServerCertificateErrors()
|
||||
{
|
||||
if (CustomIgnorableServerCertificateErrorsResolver != null)
|
||||
{
|
||||
return CustomIgnorableServerCertificateErrorsResolver(_options);
|
||||
}
|
||||
|
||||
var result = new List<ChainValidationResult>();
|
||||
|
||||
if (_options.TlsOptions.IgnoreCertificateRevocationErrors)
|
||||
{
|
||||
result.Add(ChainValidationResult.RevocationInformationMissing);
|
||||
//_socket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.Revoked); Not supported.
|
||||
result.Add(ChainValidationResult.RevocationFailure);
|
||||
}
|
||||
|
||||
if (_options.TlsOptions.IgnoreCertificateChainErrors)
|
||||
{
|
||||
result.Add(ChainValidationResult.IncompleteChain);
|
||||
}
|
||||
|
||||
if (_options.TlsOptions.AllowUntrustedCertificates)
|
||||
{
|
||||
result.Add(ChainValidationResult.Untrusted);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user