From 562a5304f6efc74307417454c7f849c5cef04197 Mon Sep 17 00:00:00 2001 From: Christian Kratky Date: Sun, 10 Mar 2019 19:52:55 +0100 Subject: [PATCH] Add flag for secure connections. --- Build/MQTTnet.nuspec | 2 ++ Source/MQTTnet.AspnetCore/MqttConnectionContext.cs | 1 + Source/MQTTnet.AspnetCore/MqttWebSocketServerAdapter.cs | 7 ++++--- Source/MQTTnet.Server/Mqtt/MqttConnectionValidator.cs | 1 + Source/MQTTnet/Adapter/IMqttChannelAdapter.cs | 2 ++ Source/MQTTnet/Adapter/MqttChannelAdapter.cs | 2 ++ Source/MQTTnet/Channel/IMqttChannel.cs | 1 + .../MQTTnet/Implementations/MqttClientAdapterFactory.cs | 1 - Source/MQTTnet/Implementations/MqttTcpChannel.Uwp.cs | 4 ++++ Source/MQTTnet/Implementations/MqttTcpChannel.cs | 6 ++++++ Source/MQTTnet/Implementations/MqttWebSocketChannel.cs | 9 ++++++++- Source/MQTTnet/Internal/TestMqttChannel.cs | 2 ++ Source/MQTTnet/Server/MqttClientSessionsManager.cs | 3 ++- Source/MQTTnet/Server/MqttConnectionValidatorContext.cs | 5 ++++- Tests/MQTTnet.Benchmarks/SerializerBenchmark.cs | 4 +++- .../Mockups/TestMqttCommunicationAdapter.cs | 4 +++- 16 files changed, 45 insertions(+), 9 deletions(-) diff --git a/Build/MQTTnet.nuspec b/Build/MQTTnet.nuspec index 2f12dd05..f5137d18 100644 --- a/Build/MQTTnet.nuspec +++ b/Build/MQTTnet.nuspec @@ -25,6 +25,8 @@ * [Server] Added support for MQTTv5 clients. The server will still return _success_ for all cases at the moment even if more granular codes are available. * [Server] Fixed issues in QoS 2 handling which leads to message loss. * [Server] Replaced all events with proper async compatible handlers (BREAKING CHANGE!). +* [Server] The used logger instance is now propagated to the WebSocket server adapter. +* [Server] Added the flag "IsSecureConnection" which is set to true when the connection is encrypted. * [MQTTnet Server] Added as first Alpha version. * [Note] Due to MQTTv5 a lot of new classes were introduced. This required adding new namespaces as well. Most classes are backward compatible but new namespaces must be added. diff --git a/Source/MQTTnet.AspnetCore/MqttConnectionContext.cs b/Source/MQTTnet.AspnetCore/MqttConnectionContext.cs index 999b340c..4a9eb91d 100644 --- a/Source/MQTTnet.AspnetCore/MqttConnectionContext.cs +++ b/Source/MQTTnet.AspnetCore/MqttConnectionContext.cs @@ -20,6 +20,7 @@ namespace MQTTnet.AspNetCore } public string Endpoint => Connection.ConnectionId; + public bool IsSecureConnection => false; // TODO: Fix detection. public ConnectionContext Connection { get; } public MqttPacketFormatterAdapter PacketFormatterAdapter { get; } public event EventHandler ReadingPacketStarted; diff --git a/Source/MQTTnet.AspnetCore/MqttWebSocketServerAdapter.cs b/Source/MQTTnet.AspnetCore/MqttWebSocketServerAdapter.cs index e5720e7a..959d25a4 100644 --- a/Source/MQTTnet.AspnetCore/MqttWebSocketServerAdapter.cs +++ b/Source/MQTTnet.AspnetCore/MqttWebSocketServerAdapter.cs @@ -38,13 +38,14 @@ namespace MQTTnet.AspNetCore if (webSocket == null) throw new ArgumentNullException(nameof(webSocket)); var endpoint = $"{httpContext.Connection.RemoteIpAddress}:{httpContext.Connection.RemotePort}"; - var channel = new MqttWebSocketChannel(webSocket, endpoint); - var clientAdapter = new MqttChannelAdapter(channel, new MqttPacketFormatterAdapter(), _logger.CreateChildLogger(nameof(MqttWebSocketServerAdapter))); - + var clientCertificate = await httpContext.Connection.GetClientCertificateAsync().ConfigureAwait(false); var isSecureConnection = clientCertificate != null; clientCertificate?.Dispose(); + var channel = new MqttWebSocketChannel(webSocket, endpoint, isSecureConnection); + var clientAdapter = new MqttChannelAdapter(channel, new MqttPacketFormatterAdapter(), _logger.CreateChildLogger(nameof(MqttWebSocketServerAdapter))); + var eventArgs = new MqttServerAdapterClientAcceptedEventArgs(clientAdapter); ClientAcceptedHandler?.Invoke(eventArgs); diff --git a/Source/MQTTnet.Server/Mqtt/MqttConnectionValidator.cs b/Source/MQTTnet.Server/Mqtt/MqttConnectionValidator.cs index d0852303..83f66039 100644 --- a/Source/MQTTnet.Server/Mqtt/MqttConnectionValidator.cs +++ b/Source/MQTTnet.Server/Mqtt/MqttConnectionValidator.cs @@ -26,6 +26,7 @@ namespace MQTTnet.Server.Mqtt { { "client_id", context.ClientId }, { "endpoint", context.Endpoint }, + { "is_secure_connection", context.IsSecureConnection }, { "username", context.Username }, { "password", context.Password }, { "result", PythonConvert.Pythonfy(context.ReturnCode) } diff --git a/Source/MQTTnet/Adapter/IMqttChannelAdapter.cs b/Source/MQTTnet/Adapter/IMqttChannelAdapter.cs index f4993224..e759221f 100644 --- a/Source/MQTTnet/Adapter/IMqttChannelAdapter.cs +++ b/Source/MQTTnet/Adapter/IMqttChannelAdapter.cs @@ -10,6 +10,8 @@ namespace MQTTnet.Adapter { string Endpoint { get; } + bool IsSecureConnection { get; } + MqttPacketFormatterAdapter PacketFormatterAdapter { get; } event EventHandler ReadingPacketStarted; diff --git a/Source/MQTTnet/Adapter/MqttChannelAdapter.cs b/Source/MQTTnet/Adapter/MqttChannelAdapter.cs index 1bfcff02..eba18f7d 100644 --- a/Source/MQTTnet/Adapter/MqttChannelAdapter.cs +++ b/Source/MQTTnet/Adapter/MqttChannelAdapter.cs @@ -42,6 +42,8 @@ namespace MQTTnet.Adapter public string Endpoint => _channel.Endpoint; + public bool IsSecureConnection => _channel.IsSecureConnection; + public MqttPacketFormatterAdapter PacketFormatterAdapter { get; } public event EventHandler ReadingPacketStarted; diff --git a/Source/MQTTnet/Channel/IMqttChannel.cs b/Source/MQTTnet/Channel/IMqttChannel.cs index 4dcb6684..4848b46d 100644 --- a/Source/MQTTnet/Channel/IMqttChannel.cs +++ b/Source/MQTTnet/Channel/IMqttChannel.cs @@ -7,6 +7,7 @@ namespace MQTTnet.Channel public interface IMqttChannel : IDisposable { string Endpoint { get; } + bool IsSecureConnection { get; } Task ConnectAsync(CancellationToken cancellationToken); Task DisconnectAsync(CancellationToken cancellationToken); diff --git a/Source/MQTTnet/Implementations/MqttClientAdapterFactory.cs b/Source/MQTTnet/Implementations/MqttClientAdapterFactory.cs index 0f5df6f5..2377cde7 100644 --- a/Source/MQTTnet/Implementations/MqttClientAdapterFactory.cs +++ b/Source/MQTTnet/Implementations/MqttClientAdapterFactory.cs @@ -1,6 +1,5 @@ using System; using MQTTnet.Adapter; -using MQTTnet.Client; using MQTTnet.Client.Options; using MQTTnet.Diagnostics; using MQTTnet.Formatter; diff --git a/Source/MQTTnet/Implementations/MqttTcpChannel.Uwp.cs b/Source/MQTTnet/Implementations/MqttTcpChannel.Uwp.cs index ea5d6ccf..092b7030 100644 --- a/Source/MQTTnet/Implementations/MqttTcpChannel.Uwp.cs +++ b/Source/MQTTnet/Implementations/MqttTcpChannel.Uwp.cs @@ -36,6 +36,8 @@ namespace MQTTnet.Implementations _bufferSize = serverOptions.DefaultEndpointOptions.BufferSize; CreateStreams(); + + IsSecureConnection = socket.Information.ProtectionLevel >= SocketProtectionLevel.Tls12; } public static Func> CustomIgnorableServerCertificateErrorsResolver { get; set; } @@ -53,6 +55,8 @@ namespace MQTTnet.Implementations } } + public bool IsSecureConnection { get; } + public async Task ConnectAsync(CancellationToken cancellationToken) { if (_socket == null) diff --git a/Source/MQTTnet/Implementations/MqttTcpChannel.cs b/Source/MQTTnet/Implementations/MqttTcpChannel.cs index 4a178855..e6b7debc 100644 --- a/Source/MQTTnet/Implementations/MqttTcpChannel.cs +++ b/Source/MQTTnet/Implementations/MqttTcpChannel.cs @@ -27,6 +27,8 @@ namespace MQTTnet.Implementations { _clientOptions = clientOptions ?? throw new ArgumentNullException(nameof(clientOptions)); _options = (MqttClientTcpOptions)clientOptions.ChannelOptions; + + IsSecureConnection = clientOptions.ChannelOptions?.TlsOptions?.UseTls == true; } /// @@ -37,6 +39,8 @@ namespace MQTTnet.Implementations { _socket = socket ?? throw new ArgumentNullException(nameof(socket)); + IsSecureConnection = sslStream != null; + CreateStream(sslStream); } @@ -45,6 +49,8 @@ namespace MQTTnet.Implementations public string Endpoint => _socket?.RemoteEndPoint?.ToString(); + public bool IsSecureConnection { get; } + public async Task ConnectAsync(CancellationToken cancellationToken) { if (_socket == null) diff --git a/Source/MQTTnet/Implementations/MqttWebSocketChannel.cs b/Source/MQTTnet/Implementations/MqttWebSocketChannel.cs index 6240f25f..59329a5a 100644 --- a/Source/MQTTnet/Implementations/MqttWebSocketChannel.cs +++ b/Source/MQTTnet/Implementations/MqttWebSocketChannel.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Net; using System.Net.WebSockets; using System.Security.Cryptography.X509Certificates; @@ -21,14 +22,18 @@ namespace MQTTnet.Implementations _options = options ?? throw new ArgumentNullException(nameof(options)); } - public MqttWebSocketChannel(WebSocket webSocket, string endpoint) + public MqttWebSocketChannel(WebSocket webSocket, string endpoint, bool isSecureConnection) { _webSocket = webSocket ?? throw new ArgumentNullException(nameof(webSocket)); + Endpoint = endpoint; + IsSecureConnection = isSecureConnection; } public string Endpoint { get; } + public bool IsSecureConnection { get; private set; } + public async Task ConnectAsync(CancellationToken cancellationToken) { var uri = _options.Uri; @@ -83,6 +88,8 @@ namespace MQTTnet.Implementations await clientWebSocket.ConnectAsync(new Uri(uri), cancellationToken).ConfigureAwait(false); _webSocket = clientWebSocket; + + IsSecureConnection = uri.StartsWith("wss://", StringComparison.OrdinalIgnoreCase); } public async Task DisconnectAsync(CancellationToken cancellationToken) diff --git a/Source/MQTTnet/Internal/TestMqttChannel.cs b/Source/MQTTnet/Internal/TestMqttChannel.cs index 03f23b14..1ef8e5a5 100644 --- a/Source/MQTTnet/Internal/TestMqttChannel.cs +++ b/Source/MQTTnet/Internal/TestMqttChannel.cs @@ -16,6 +16,8 @@ namespace MQTTnet.Internal public string Endpoint { get; } = ""; + public bool IsSecureConnection { get; } = false; + public Task ConnectAsync(CancellationToken cancellationToken) { return Task.FromResult(0); diff --git a/Source/MQTTnet/Server/MqttClientSessionsManager.cs b/Source/MQTTnet/Server/MqttClientSessionsManager.cs index 34393130..07640d94 100644 --- a/Source/MQTTnet/Server/MqttClientSessionsManager.cs +++ b/Source/MQTTnet/Server/MqttClientSessionsManager.cs @@ -298,7 +298,8 @@ namespace MQTTnet.Server connectPacket.Username, connectPacket.Password, connectPacket.WillMessage, - clientAdapter.Endpoint); + clientAdapter.Endpoint, + clientAdapter.IsSecureConnection); var connectionValidator = _options.ConnectionValidator; diff --git a/Source/MQTTnet/Server/MqttConnectionValidatorContext.cs b/Source/MQTTnet/Server/MqttConnectionValidatorContext.cs index 5857862b..b06eb844 100644 --- a/Source/MQTTnet/Server/MqttConnectionValidatorContext.cs +++ b/Source/MQTTnet/Server/MqttConnectionValidatorContext.cs @@ -4,13 +4,14 @@ namespace MQTTnet.Server { public class MqttConnectionValidatorContext { - public MqttConnectionValidatorContext(string clientId, string username, string password, MqttApplicationMessage willMessage, string endpoint) + public MqttConnectionValidatorContext(string clientId, string username, string password, MqttApplicationMessage willMessage, string endpoint, bool isSecureConnection) { ClientId = clientId; Username = username; Password = password; WillMessage = willMessage; Endpoint = endpoint; + IsSecureConnection = isSecureConnection; } public string ClientId { get; } @@ -23,6 +24,8 @@ namespace MQTTnet.Server public string Endpoint { get; } + public bool IsSecureConnection { get; } + public MqttConnectReturnCode ReturnCode { get; set; } = MqttConnectReturnCode.ConnectionAccepted; } } diff --git a/Tests/MQTTnet.Benchmarks/SerializerBenchmark.cs b/Tests/MQTTnet.Benchmarks/SerializerBenchmark.cs index d713dfca..35a001d0 100644 --- a/Tests/MQTTnet.Benchmarks/SerializerBenchmark.cs +++ b/Tests/MQTTnet.Benchmarks/SerializerBenchmark.cs @@ -73,7 +73,9 @@ namespace MQTTnet.Benchmarks _position = _buffer.Offset; } - public string Endpoint { get; } + public string Endpoint { get; } = string.Empty; + + public bool IsSecureConnection { get; } = false; public void Reset() { diff --git a/Tests/MQTTnet.Core.Tests/Mockups/TestMqttCommunicationAdapter.cs b/Tests/MQTTnet.Core.Tests/Mockups/TestMqttCommunicationAdapter.cs index 73676ddd..54441ef9 100644 --- a/Tests/MQTTnet.Core.Tests/Mockups/TestMqttCommunicationAdapter.cs +++ b/Tests/MQTTnet.Core.Tests/Mockups/TestMqttCommunicationAdapter.cs @@ -14,7 +14,9 @@ namespace MQTTnet.Tests.Mockups public TestMqttCommunicationAdapter Partner { get; set; } - public string Endpoint { get; } + public string Endpoint { get; } = string.Empty; + + public bool IsSecureConnection { get; } = false; public MqttPacketFormatterAdapter PacketFormatterAdapter { get; } = new MqttPacketFormatterAdapter(MqttProtocolVersion.V311); -- GitLab