Expose more TLS options (#1737)

This commit is contained in:
Christian
2023-05-13 12:08:52 +02:00
committed by GitHub
parent 449624fd72
commit 0bb4c6ef09
13 changed files with 49 additions and 60 deletions
+4
View File
@@ -1,4 +1,8 @@
* [Core] Add validation of maximum string lengths (#1718). * [Core] Add validation of maximum string lengths (#1718).
* [Core] Added .NET 4.8 builds (#1729).
* [Core] Exposed more details of DISCONNECT packet in log (#1729).
* [Client] Added overloads for setting packet payload and will payload (#1720). * [Client] Added overloads for setting packet payload and will payload (#1720).
* [Client] The proper connect result is now exposed in the _Disconnected_ event when authentication fails (#1139). * [Client] The proper connect result is now exposed in the _Disconnected_ event when authentication fails (#1139).
* [Client] Exposed more TLS options (#1729).
* [Client] Fixed wrong return code conversion (#1729).
* [Server] Improved performance by changing internal locking strategy for subscriptions (#1716, thanks to @zeheng). * [Server] Improved performance by changing internal locking strategy for subscriptions (#1716, thanks to @zeheng).
@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net7.0</TargetFrameworks> <TargetFrameworks>netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net7.0</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net452;net461</TargetFrameworks> <TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net452;net461;net48</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' AND '$(MSBuildRuntimeType)' != 'Core' ">$(TargetFrameworks);uap10.0</TargetFrameworks> <TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' AND '$(MSBuildRuntimeType)' != 'Core' ">$(TargetFrameworks);uap10.0</TargetFrameworks>
<AssemblyName>MQTTnet.Extensions.ManagedClient</AssemblyName> <AssemblyName>MQTTnet.Extensions.ManagedClient</AssemblyName>
@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net7.0</TargetFrameworks> <TargetFrameworks>netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net7.0</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net452;net461</TargetFrameworks> <TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net452;net461;net48</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' AND '$(MSBuildRuntimeType)' != 'Core' ">$(TargetFrameworks);uap10.0</TargetFrameworks> <TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' AND '$(MSBuildRuntimeType)' != 'Core' ">$(TargetFrameworks);uap10.0</TargetFrameworks>
<AssemblyName>MQTTnet.Extensions.Rpc</AssemblyName> <AssemblyName>MQTTnet.Extensions.Rpc</AssemblyName>
@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net7.0</TargetFrameworks> <TargetFrameworks>netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net7.0</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net452;net461</TargetFrameworks> <TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net452;net461;net48</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' AND '$(MSBuildRuntimeType)' != 'Core' ">$(TargetFrameworks);uap10.0</TargetFrameworks> <TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' AND '$(MSBuildRuntimeType)' != 'Core' ">$(TargetFrameworks);uap10.0</TargetFrameworks>
<AssemblyName>MQTTnet.Extensions.WebSocket4Net</AssemblyName> <AssemblyName>MQTTnet.Extensions.WebSocket4Net</AssemblyName>
@@ -78,7 +78,7 @@ namespace MQTTnet.Tests.Formatter
Assert.IsNull(deserialized.UserProperties); // Not supported in v3.1.1 Assert.IsNull(deserialized.UserProperties); // Not supported in v3.1.1
} }
[TestMethod] [TestMethod]
public void Serialize_Full_MqttConnAckPacket_V310() public void Serialize_Full_MqttConnAckPacket_V310()
{ {
var connAckPacket = new MqttConnAckPacket var connAckPacket = new MqttConnAckPacket
@@ -4,6 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net.Security;
using System.Security.Authentication; using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
@@ -30,11 +31,21 @@ namespace MQTTnet.Client
#endif #endif
#if NETCOREAPP3_1_OR_GREATER #if NETCOREAPP3_1_OR_GREATER
public List<System.Net.Security.SslApplicationProtocol> ApplicationProtocols { get; set; } public List<SslApplicationProtocol> ApplicationProtocols { get; set; }
public System.Net.Security.CipherSuitesPolicy CipherSuitesPolicy { get; set; } public CipherSuitesPolicy CipherSuitesPolicy { get; set; }
public EncryptionPolicy EncryptionPolicy { get; set; } = EncryptionPolicy.RequireEncryption;
public bool AllowRenegotiation { get; set; } = true;
#endif #endif
/// <summary>
/// Gets or sets the target host.
/// If the value is null or empty the same host as the TCP socket host will be used.
/// </summary>
public string TargetHost { get; set; }
#if NET48 || NETCOREAPP3_1_OR_GREATER #if NET48 || NETCOREAPP3_1_OR_GREATER
public SslProtocols SslProtocol { get; set; } = SslProtocols.Tls12 | SslProtocols.Tls13; public SslProtocols SslProtocol { get; set; } = SslProtocols.Tls12 | SslProtocols.Tls13;
#else #else
@@ -16,6 +16,8 @@ namespace MQTTnet.Diagnostics
return "net461"; return "net461";
#elif NET472 #elif NET472
return "net472"; return "net472";
#elif NET48
return "net48";
#elif NETSTANDARD1_3 #elif NETSTANDARD1_3
return "netstandard1.3"; return "netstandard1.3";
#elif NETSTANDARD2_0 #elif NETSTANDARD2_0
@@ -2,54 +2,12 @@
// The .NET Foundation licenses this file to you under the MIT license. // The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using MQTTnet.Exceptions;
using MQTTnet.Protocol; using MQTTnet.Protocol;
namespace MQTTnet.Formatter namespace MQTTnet.Formatter
{ {
public static class MqttConnectReasonCodeConverter public static class MqttConnectReasonCodeConverter
{ {
public static MqttConnectReasonCode ToConnectReasonCode(MqttConnectReturnCode returnCode)
{
switch (returnCode)
{
case MqttConnectReturnCode.ConnectionAccepted:
{
return MqttConnectReasonCode.Success;
}
case MqttConnectReturnCode.ConnectionRefusedUnacceptableProtocolVersion:
{
return MqttConnectReasonCode.UnsupportedProtocolVersion;
}
case MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword:
{
return MqttConnectReasonCode.BadUserNameOrPassword;
}
case MqttConnectReturnCode.ConnectionRefusedIdentifierRejected:
{
return MqttConnectReasonCode.ClientIdentifierNotValid;
}
case MqttConnectReturnCode.ConnectionRefusedServerUnavailable:
{
return MqttConnectReasonCode.ServerUnavailable;
}
case MqttConnectReturnCode.ConnectionRefusedNotAuthorized:
{
return MqttConnectReasonCode.NotAuthorized;
}
default:
{
throw new MqttProtocolViolationException("Unable to convert connect reason code (MQTTv5) to return code (MQTTv3).");
}
}
}
public static MqttConnectReturnCode ToConnectReturnCode(MqttConnectReasonCode reasonCode) public static MqttConnectReturnCode ToConnectReturnCode(MqttConnectReasonCode reasonCode)
{ {
switch (reasonCode) switch (reasonCode)
@@ -59,11 +17,13 @@ namespace MQTTnet.Formatter
return MqttConnectReturnCode.ConnectionAccepted; return MqttConnectReturnCode.ConnectionAccepted;
} }
case MqttConnectReasonCode.Banned:
case MqttConnectReasonCode.NotAuthorized: case MqttConnectReasonCode.NotAuthorized:
{ {
return MqttConnectReturnCode.ConnectionRefusedNotAuthorized; return MqttConnectReturnCode.ConnectionRefusedNotAuthorized;
} }
case MqttConnectReasonCode.BadAuthenticationMethod:
case MqttConnectReasonCode.BadUserNameOrPassword: case MqttConnectReasonCode.BadUserNameOrPassword:
{ {
return MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword; return MqttConnectReturnCode.ConnectionRefusedBadUsernameOrPassword;
@@ -79,6 +39,7 @@ namespace MQTTnet.Formatter
return MqttConnectReturnCode.ConnectionRefusedUnacceptableProtocolVersion; return MqttConnectReturnCode.ConnectionRefusedUnacceptableProtocolVersion;
} }
case MqttConnectReasonCode.UseAnotherServer:
case MqttConnectReasonCode.ServerUnavailable: case MqttConnectReasonCode.ServerUnavailable:
case MqttConnectReasonCode.ServerBusy: case MqttConnectReasonCode.ServerBusy:
case MqttConnectReasonCode.ServerMoved: case MqttConnectReasonCode.ServerMoved:
@@ -87,9 +48,7 @@ namespace MQTTnet.Formatter
} }
default: default:
{ return MqttConnectReturnCode.ConnectionRefusedUnacceptableProtocolVersion;
throw new MqttProtocolViolationException("Unable to convert connect reason code (MQTTv5) to return code (MQTTv3).");
}
} }
} }
} }
@@ -130,6 +130,9 @@ namespace MQTTnet.Formatter.V5
MaximumQoS = MqttQualityOfServiceLevel.ExactlyOnce MaximumQoS = MqttQualityOfServiceLevel.ExactlyOnce
}; };
// Also set the return code of MQTT 3.1.1 for backward compatibility and debugging purposes.
packet.ReturnCode = MqttConnectReasonCodeConverter.ToConnectReturnCode(packet.ReasonCode);
var propertiesReader = new MqttV5PropertiesReader(_bufferReader); var propertiesReader = new MqttV5PropertiesReader(_bufferReader);
while (propertiesReader.MoveNext()) while (propertiesReader.MoveNext())
{ {
@@ -100,6 +100,12 @@ namespace MQTTnet.Implementations
if (_tcpOptions.TlsOptions?.UseTls == true) if (_tcpOptions.TlsOptions?.UseTls == true)
{ {
var targetHost = _tcpOptions.TlsOptions.TargetHost;
if (string.IsNullOrEmpty(targetHost))
{
targetHost = _tcpOptions.Server;
}
var sslStream = new SslStream(networkStream, false, InternalUserCertificateValidationCallback); var sslStream = new SslStream(networkStream, false, InternalUserCertificateValidationCallback);
try try
{ {
@@ -111,14 +117,16 @@ namespace MQTTnet.Implementations
EnabledSslProtocols = _tcpOptions.TlsOptions.SslProtocol, EnabledSslProtocols = _tcpOptions.TlsOptions.SslProtocol,
CertificateRevocationCheckMode = CertificateRevocationCheckMode =
_tcpOptions.TlsOptions.IgnoreCertificateRevocationErrors ? X509RevocationMode.NoCheck : _tcpOptions.TlsOptions.RevocationMode, _tcpOptions.TlsOptions.IgnoreCertificateRevocationErrors ? X509RevocationMode.NoCheck : _tcpOptions.TlsOptions.RevocationMode,
TargetHost = _tcpOptions.Server, TargetHost = targetHost,
CipherSuitesPolicy = _tcpOptions.TlsOptions.CipherSuitesPolicy CipherSuitesPolicy = _tcpOptions.TlsOptions.CipherSuitesPolicy,
EncryptionPolicy = _tcpOptions.TlsOptions.EncryptionPolicy,
AllowRenegotiation = _tcpOptions.TlsOptions.AllowRenegotiation
}; };
await sslStream.AuthenticateAsClientAsync(sslOptions, cancellationToken).ConfigureAwait(false); await sslStream.AuthenticateAsClientAsync(sslOptions, cancellationToken).ConfigureAwait(false);
#else #else
await sslStream.AuthenticateAsClientAsync( await sslStream.AuthenticateAsClientAsync(
_tcpOptions.Server, targetHost,
LoadCertificates(), LoadCertificates(),
_tcpOptions.TlsOptions.SslProtocol, _tcpOptions.TlsOptions.SslProtocol,
!_tcpOptions.TlsOptions.IgnoreCertificateRevocationErrors) !_tcpOptions.TlsOptions.IgnoreCertificateRevocationErrors)
@@ -290,12 +298,12 @@ namespace MQTTnet.Implementations
X509CertificateCollection LoadCertificates() X509CertificateCollection LoadCertificates()
{ {
var certificates = new X509CertificateCollection();
if (_tcpOptions.TlsOptions.Certificates == null) if (_tcpOptions.TlsOptions.Certificates == null)
{ {
return certificates; return null;
} }
var certificates = new X509CertificateCollection();
foreach (var certificate in _tcpOptions.TlsOptions.Certificates) foreach (var certificate in _tcpOptions.TlsOptions.Certificates)
{ {
certificates.Add(certificate); certificates.Add(certificate);
@@ -220,6 +220,8 @@ namespace MQTTnet.Implementations
throw new NotSupportedException("Remote certificate validation callback is not supported when using 'net452'."); throw new NotSupportedException("Remote certificate validation callback is not supported when using 'net452'.");
#elif NET461 #elif NET461
throw new NotSupportedException("Remote certificate validation callback is not supported when using 'net461'."); throw new NotSupportedException("Remote certificate validation callback is not supported when using 'net461'.");
#elif NET48
throw new NotSupportedException("Remote certificate validation callback is not supported when using 'net48'.");
#else #else
clientWebSocket.Options.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => clientWebSocket.Options.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
{ {
+1 -1
View File
@@ -11,7 +11,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net7.0</TargetFrameworks> <TargetFrameworks>netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net7.0</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net452;net461</TargetFrameworks> <TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);net452;net461;net48</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' AND '$(MSBuildRuntimeType)' != 'Core' ">$(TargetFrameworks);uap10.0</TargetFrameworks> <TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' AND '$(MSBuildRuntimeType)' != 'Core' ">$(TargetFrameworks);uap10.0</TargetFrameworks>
<LangVersion>7.3</LangVersion> <LangVersion>7.3</LangVersion>
<AssemblyName>MQTTnet</AssemblyName> <AssemblyName>MQTTnet</AssemblyName>
@@ -36,7 +36,7 @@ namespace MQTTnet.Packets
public override string ToString() public override string ToString()
{ {
return $"Disconnect: [ReasonCode={ReasonCode}]"; return $"Disconnect: [ReasonCode={ReasonCode}] [ReasonString={ReasonString}] [ServerReference={ServerReference}] [SessionExpiryInterval={SessionExpiryInterval}]";
} }
} }
} }