Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Worker">

<PropertyGroup>
<TargetFramework>net6.0-windows10.0.19041.0</TargetFramework>
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
Expand Down
2 changes: 1 addition & 1 deletion src/HASS.Agent/HASS.Agent.Shared/HASS.Agent.Shared.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0-windows10.0.19041.0</TargetFramework>
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
<Platforms>x64;x86</Platforms>
<AssemblyName>HASS.Agent.Shared</AssemblyName>
<PackageId>HASS.Agent.Shared</PackageId>
Expand Down
10 changes: 5 additions & 5 deletions src/HASS.Agent/HASS.Agent/Functions/HelperFunctions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ internal static async Task ShutdownAsync(TimeSpan waitBeforeClosing)
Variables.MainForm?.HideTrayIcon();

// stop hotkey
Variables.MainForm?.Invoke(new MethodInvoker(delegate
Variables.MainForm?.Invoke(new System.Windows.Forms.MethodInvoker(delegate
{
Variables.HotKeyListener?.RemoveAll();
Variables.HotKeyListener?.Dispose();
Expand Down Expand Up @@ -412,7 +412,7 @@ internal static void LaunchWebView(WebViewInfo webViewInfo, string url = "")
if (!string.IsNullOrEmpty(url)) webViewInfo.Url = url;

// show it from within the UI thread
Variables.MainForm.Invoke(new MethodInvoker(delegate
Variables.MainForm.Invoke(new System.Windows.Forms.MethodInvoker(delegate
{
var webView = new WebView(webViewInfo);
webView.Opacity = 0;
Expand Down Expand Up @@ -446,7 +446,7 @@ internal static void PrepareTrayIconWebView()
webViewInfo.IsTrayIconWebView = true;

// prepare the webview
Variables.MainForm.Invoke(new MethodInvoker(delegate
Variables.MainForm.Invoke(new System.Windows.Forms.MethodInvoker(delegate
{
// optionally close an existing one
Variables.TrayIconWebView?.ForceClose();
Expand Down Expand Up @@ -506,7 +506,7 @@ internal static void LaunchTrayIconWebView(WebViewInfo webViewInfo)

private static void LaunchTrayIconBackgroundLoadedWebView()
{
Variables.MainForm.Invoke(new MethodInvoker(delegate
Variables.MainForm.Invoke(new System.Windows.Forms.MethodInvoker(delegate
{
// make sure it's ready
if (Variables.TrayIconWebView == null || Variables.TrayIconWebView.IsDisposed)
Expand All @@ -519,7 +519,7 @@ private static void LaunchTrayIconBackgroundLoadedWebView()

private static void LaunchTrayIconCustomWebView(WebViewInfo webViewInfo)
{
Variables.MainForm.Invoke(new MethodInvoker(delegate
Variables.MainForm.Invoke(new System.Windows.Forms.MethodInvoker(delegate
{
var x = Screen.PrimaryScreen.WorkingArea.Width - webViewInfo.Width;
var y = Screen.PrimaryScreen.WorkingArea.Height - webViewInfo.Height;
Expand Down
4 changes: 2 additions & 2 deletions src/HASS.Agent/HASS.Agent/HASS.Agent.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows10.0.19041.0</TargetFramework>
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
<Nullable>disable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<UseWPF>true</UseWPF>
Expand All @@ -26,7 +26,7 @@
<FileVersion>2.1.1</FileVersion>
<RootNamespace>HASS.Agent</RootNamespace>
<WindowsPackageType>None</WindowsPackageType>
<RuntimeIdentifiers>win10-x64;win10-x86</RuntimeIdentifiers>
<RuntimeIdentifiers>win-x64</RuntimeIdentifiers>
<EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization>
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
<EnableCoreMrtTooling Condition=" '$(BuildingInsideVisualStudio)' != 'true' ">false</EnableCoreMrtTooling>
Expand Down
45 changes: 36 additions & 9 deletions src/HASS.Agent/HASS.Agent/MQTT/MqttManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -720,21 +720,23 @@ private static ManagedMqttClientOptions GetOptions()
if (!string.IsNullOrEmpty(Variables.AppSettings.MqttUsername))
clientOptionsBuilder.WithCredentials(Variables.AppSettings.MqttUsername, Variables.AppSettings.MqttPassword);

var certificates = new List<X509Certificate>();
// Load CA cert for server validation
X509Certificate2? caCert = null;
if (!string.IsNullOrEmpty(Variables.AppSettings.MqttRootCertificate))
{
if (!File.Exists(Variables.AppSettings.MqttRootCertificate))
Log.Error("[MQTT] Provided root certificate not found: {cert}", Variables.AppSettings.MqttRootCertificate);
else
certificates.Add(new X509Certificate2(Variables.AppSettings.MqttRootCertificate));
caCert = new X509Certificate2(Variables.AppSettings.MqttRootCertificate);
}

var certificates = new List<X509Certificate>();
if (!string.IsNullOrEmpty(Variables.AppSettings.MqttClientCertificate))
{
if (!File.Exists(Variables.AppSettings.MqttClientCertificate))
Log.Error("[MQTT] Provided client certificate not found: {cert}", Variables.AppSettings.MqttClientCertificate);
else
certificates.Add(new X509Certificate2(Variables.AppSettings.MqttClientCertificate));
certificates.Add(new X509Certificate2(Variables.AppSettings.MqttClientCertificate, "")); // P12, empty password
}

var clientTlsOptions = new MqttClientTlsOptions()
Expand All @@ -745,25 +747,50 @@ private static ManagedMqttClientOptions GetOptions()
};

//TODO(Amadeo): add more granular control to the UI
if (Variables.AppSettings.MqttAllowUntrustedCertificates)
if (caCert != null)
{
clientTlsOptions.IgnoreCertificateChainErrors = Variables.AppSettings.MqttAllowUntrustedCertificates;
clientTlsOptions.IgnoreCertificateRevocationErrors = Variables.AppSettings.MqttAllowUntrustedCertificates;
clientTlsOptions.CertificateValidationHandler = delegate (MqttClientCertificateValidationEventArgs _)
clientTlsOptions.CertificateValidationHandler = ctx =>
{
var chain = new X509Chain();
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;

chain.ChainPolicy.TrustMode = X509ChainTrustMode.System;
chain.ChainPolicy.ExtraStore.Add(caCert);

chain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;

var serverCert = new X509Certificate2(ctx.Certificate);
var valid = chain.Build(serverCert);

if (!valid)
{
Log.Error("[MQTT] Server certificate validation failed. Chain errors: {errors}",
string.Join(", ", chain.ChainStatus
.Where(s => s.Status != X509ChainStatusFlags.NoError)
.Select(s => $"{s.Status}: {s.StatusInformation}")));
return false;
}
return true;
};
}
else if (Variables.AppSettings.MqttAllowUntrustedCertificates)
{
clientTlsOptions.CertificateValidationHandler = ctx => true;
}
else
{
clientTlsOptions.CertificateValidationHandler = MqttClientDefaultCertificateValidationHandler.Handle;
}

if (certificates.Count > 0)
clientTlsOptions.ClientCertificatesProvider = new DefaultMqttCertificatesProvider(certificates);

clientOptionsBuilder.WithTlsOptions(clientTlsOptions);
clientOptionsBuilder.Build();

return new ManagedMqttClientOptionsBuilder()
.WithAutoReconnectDelay(TimeSpan.FromSeconds(5))
.WithClientOptions(clientOptionsBuilder).Build();
.WithClientOptions(clientOptionsBuilder.Build())
.Build();
}

/// <summary>
Expand Down