diff --git a/Build/MQTTnet.AspNetCore.nuspec b/Build/MQTTnet.AspNetCore.nuspec
index f423f51d..53fb07ec 100644
--- a/Build/MQTTnet.AspNetCore.nuspec
+++ b/Build/MQTTnet.AspNetCore.nuspec
@@ -13,7 +13,7 @@
This is a support library to integrate MQTTnet into AspNetCore.
For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).
Copyright Christian Kratky 2016-2020
- MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin
+ MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin Blazor
diff --git a/Build/MQTTnet.Extensions.ManagedClient.nuspec b/Build/MQTTnet.Extensions.ManagedClient.nuspec
index d02464b7..d7de8f47 100644
--- a/Build/MQTTnet.Extensions.ManagedClient.nuspec
+++ b/Build/MQTTnet.Extensions.ManagedClient.nuspec
@@ -13,7 +13,7 @@
This is an extension library which provides a managed MQTT client with additional features using MQTTnet.
For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).
Copyright Christian Kratky 2016-2020
- MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin
+ MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin Blazor
diff --git a/Build/MQTTnet.Extensions.Rpc.nuspec b/Build/MQTTnet.Extensions.Rpc.nuspec
index a5eabc5c..109665af 100644
--- a/Build/MQTTnet.Extensions.Rpc.nuspec
+++ b/Build/MQTTnet.Extensions.Rpc.nuspec
@@ -13,7 +13,7 @@
This is an extension library which allows executing synchronous device calls including a response using MQTTnet.
For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).
Copyright Christian Kratky 2016-2020
- MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin
+ MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin Blazor
diff --git a/Build/MQTTnet.Extensions.WebSocket4Net.nuspec b/Build/MQTTnet.Extensions.WebSocket4Net.nuspec
index 6133179d..58a52295 100644
--- a/Build/MQTTnet.Extensions.WebSocket4Net.nuspec
+++ b/Build/MQTTnet.Extensions.WebSocket4Net.nuspec
@@ -13,7 +13,7 @@
This is an extension library which allows using _WebSocket4Net_ as transport for MQTTnet clients.
For release notes please go to MQTTnet release notes (https://www.nuget.org/packages/MQTTnet/).
Copyright Christian Kratky 2016-2020
- MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin
+ MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin Blazor
diff --git a/Build/MQTTnet.nuspec b/Build/MQTTnet.nuspec
index 8367ebb2..b329846d 100644
--- a/Build/MQTTnet.nuspec
+++ b/Build/MQTTnet.nuspec
@@ -16,9 +16,10 @@
* [AspNetCore] Adjusted some namespaces (BREAKING CHANGE!)
* [Server] Adjusted some namespaces (BREAKING CHANGE!)
* [Server] Added state checks (throw if not started etc.) for most server APIs.
+* [Server] Exposed real X509Certificate2 (instead byte array) to TLS options (thanks to @borigas).
Copyright Christian Kratky 2016-2020
- MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin
+ MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin Blazor
diff --git a/Source/MQTTnet/Certificates/BlobCertificateProvider.cs b/Source/MQTTnet/Certificates/BlobCertificateProvider.cs
new file mode 100644
index 00000000..f8daebb1
--- /dev/null
+++ b/Source/MQTTnet/Certificates/BlobCertificateProvider.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Security.Cryptography.X509Certificates;
+
+namespace MQTTnet.Certificates
+{
+ public class BlobCertificateProvider : ICertificateProvider
+ {
+ public BlobCertificateProvider(byte[] blob)
+ {
+ Blob = blob ?? throw new ArgumentNullException(nameof(blob));
+ }
+
+ public byte[] Blob { get; }
+
+ public string Password { get; set; }
+
+ public X509Certificate2 GetCertificate()
+ {
+ if (string.IsNullOrEmpty(Password))
+ {
+ // Use a different overload when no password is specified. Otherwise the constructor will fail.
+ return new X509Certificate2(Blob);
+ }
+
+ return new X509Certificate2(Blob, Password);
+ }
+ }
+}
diff --git a/Source/MQTTnet/Certificates/ICertificateProvider.cs b/Source/MQTTnet/Certificates/ICertificateProvider.cs
new file mode 100644
index 00000000..42113d49
--- /dev/null
+++ b/Source/MQTTnet/Certificates/ICertificateProvider.cs
@@ -0,0 +1,9 @@
+using System.Security.Cryptography.X509Certificates;
+
+namespace MQTTnet.Certificates
+{
+ public interface ICertificateProvider
+ {
+ X509Certificate2 GetCertificate();
+ }
+}
diff --git a/Source/MQTTnet/Certificates/X509CertificateProvider.cs b/Source/MQTTnet/Certificates/X509CertificateProvider.cs
new file mode 100644
index 00000000..4bbfa4d0
--- /dev/null
+++ b/Source/MQTTnet/Certificates/X509CertificateProvider.cs
@@ -0,0 +1,22 @@
+#if !WINDOWS_UWP
+using System;
+using System.Security.Cryptography.X509Certificates;
+
+namespace MQTTnet.Certificates
+{
+ public class X509CertificateProvider : ICertificateProvider
+ {
+ readonly X509Certificate2 _certificate;
+
+ public X509CertificateProvider(X509Certificate2 certificate)
+ {
+ _certificate = certificate ?? throw new ArgumentNullException(nameof(certificate));
+ }
+
+ public X509Certificate2 GetCertificate()
+ {
+ return _certificate;
+ }
+ }
+}
+#endif
\ No newline at end of file
diff --git a/Source/MQTTnet/Implementations/MqttTcpServerAdapter.cs b/Source/MQTTnet/Implementations/MqttTcpServerAdapter.cs
index 57a414ff..592a3b49 100644
--- a/Source/MQTTnet/Implementations/MqttTcpServerAdapter.cs
+++ b/Source/MQTTnet/Implementations/MqttTcpServerAdapter.cs
@@ -44,30 +44,12 @@ namespace MQTTnet.Implementations
if (options.TlsEndpointOptions?.IsEnabled == true)
{
- if (options.TlsEndpointOptions.Certificate == null && options.TlsEndpointOptions.X509Certificate == null)
+ if (options.TlsEndpointOptions.CertificateProvider == null)
{
throw new ArgumentException("TLS certificate is not set.");
}
- else if (options.TlsEndpointOptions.Certificate != null && options.TlsEndpointOptions.X509Certificate != null)
- {
- throw new ArgumentException($"{nameof(MqttServerTlsTcpEndpointOptions.Certificate)} and {nameof(MqttServerTlsTcpEndpointOptions.X509Certificate)} cannot both be set");
- }
-
- X509Certificate2 tlsCertificate;
- if (options.TlsEndpointOptions.X509Certificate != null)
- {
- tlsCertificate = options.TlsEndpointOptions.X509Certificate;
- }
- else if (string.IsNullOrEmpty(options.TlsEndpointOptions.CertificateCredentials?.Password))
- {
- // Use a different overload when no password is specified. Otherwise the constructor will fail.
- tlsCertificate = new X509Certificate2(options.TlsEndpointOptions.Certificate);
- }
- else
- {
- tlsCertificate = new X509Certificate2(options.TlsEndpointOptions.Certificate, options.TlsEndpointOptions.CertificateCredentials.Password);
- }
-
+
+ var tlsCertificate = options.TlsEndpointOptions.CertificateProvider.GetCertificate();
if (!tlsCertificate.HasPrivateKey)
{
throw new InvalidOperationException("The certificate for TLS encryption must contain the private key.");
@@ -76,13 +58,13 @@ namespace MQTTnet.Implementations
RegisterListeners(options.TlsEndpointOptions, tlsCertificate, _cancellationTokenSource.Token);
}
- return Task.FromResult(0);
+ return PlatformAbstractionLayer.CompletedTask;
}
public Task StopAsync()
{
Cleanup();
- return Task.FromResult(0);
+ return PlatformAbstractionLayer.CompletedTask;
}
protected override void Dispose(bool disposing)
diff --git a/Source/MQTTnet/Server/MqttServerOptionsBuilder.cs b/Source/MQTTnet/Server/MqttServerOptionsBuilder.cs
index 9821b648..b52215f7 100644
--- a/Source/MQTTnet/Server/MqttServerOptionsBuilder.cs
+++ b/Source/MQTTnet/Server/MqttServerOptionsBuilder.cs
@@ -2,6 +2,8 @@
using System.Net;
using System.Net.Security;
using System.Security.Authentication;
+using MQTTnet.Certificates;
+
#if !WINDOWS_UWP
using System.Security.Cryptography.X509Certificates;
#endif
@@ -10,7 +12,7 @@ namespace MQTTnet.Server
{
public class MqttServerOptionsBuilder
{
- private readonly MqttServerOptions _options = new MqttServerOptions();
+ readonly MqttServerOptions _options = new MqttServerOptions();
public MqttServerOptionsBuilder WithConnectionBacklog(int value)
{
@@ -85,17 +87,24 @@ namespace MQTTnet.Server
return this;
}
+#if !WINDOWS_UWP
public MqttServerOptionsBuilder WithEncryptionCertificate(byte[] value, IMqttServerCertificateCredentials credentials = null)
{
- _options.TlsEndpointOptions.Certificate = value;
- _options.TlsEndpointOptions.CertificateCredentials = credentials;
+ if (value == null) throw new ArgumentNullException(nameof(value));
+
+ _options.TlsEndpointOptions.CertificateProvider = new BlobCertificateProvider(value)
+ {
+ Password = credentials?.Password
+ };
+
return this;
}
-#if !WINDOWS_UWP
public MqttServerOptionsBuilder WithEncryptionCertificate(X509Certificate2 certificate)
{
- _options.TlsEndpointOptions.X509Certificate = certificate;
+ if (certificate == null) throw new ArgumentNullException(nameof(certificate));
+
+ _options.TlsEndpointOptions.CertificateProvider = new X509CertificateProvider(certificate);
return this;
}
#endif
diff --git a/Source/MQTTnet/Server/MqttServerTlsTcpEndpointOptions.cs b/Source/MQTTnet/Server/MqttServerTlsTcpEndpointOptions.cs
index 0c529b57..25f61bd3 100644
--- a/Source/MQTTnet/Server/MqttServerTlsTcpEndpointOptions.cs
+++ b/Source/MQTTnet/Server/MqttServerTlsTcpEndpointOptions.cs
@@ -1,33 +1,56 @@
-using System.Net.Security;
+using System;
using System.Security.Authentication;
-#if !WINDOWS_UWP
-using System.Security.Cryptography.X509Certificates;
-#endif
+using MQTTnet.Certificates;
namespace MQTTnet.Server
{
public class MqttServerTlsTcpEndpointOptions : MqttServerTcpEndpointBaseOptions
{
+ ICertificateProvider _certificateProvider;
+
public MqttServerTlsTcpEndpointOptions()
{
Port = 8883;
}
+ [Obsolete("Please use CertificateProvider with 'BlobCertificateProvider' instead.")]
public byte[] Certificate { get; set; }
-#if !WINDOWS_UWP
- public X509Certificate2 X509Certificate { get; set; }
-#endif
-
+ [Obsolete("Please use CertificateProvider with 'BlobCertificateProvider' including password property instead.")]
public IMqttServerCertificateCredentials CertificateCredentials { get; set; }
+#if !WINDOWS_UWP
+ public System.Net.Security.RemoteCertificateValidationCallback RemoteCertificateValidationCallback { get; set; }
+#endif
+ public ICertificateProvider CertificateProvider
+ {
+ get
+ {
+ // Backward compatibility only. Gets converted to auto property when
+ // obsolete properties are removed.
+ if (_certificateProvider != null)
+ {
+ return _certificateProvider;
+ }
+
+ if (Certificate == null)
+ {
+ return null;
+ }
+
+ return new BlobCertificateProvider(Certificate)
+ {
+ Password = CertificateCredentials?.Password
+ };
+ }
+
+ set => _certificateProvider = value;
+ }
+
public bool ClientCertificateRequired { get; set; }
public bool CheckCertificateRevocation { get; set; }
-#if !WINDOWS_UWP
- public RemoteCertificateValidationCallback RemoteCertificateValidationCallback { get; set; }
-#endif
public SslProtocols SslProtocol { get; set; } = SslProtocols.Tls12;
}
}