From d5e69db1b431643520e97ff8afc6a5f0822172cc Mon Sep 17 00:00:00 2001 From: Ylian Saint-Hilaire Date: Tue, 3 Nov 2020 21:29:12 -0800 Subject: [PATCH] Update. --- MainForm.cs | 6 +++--- MeshCentralServer.cs | 8 ++++++-- UpdateForm.cs | 30 ++++++++++++++++++++++++++++-- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/MainForm.cs b/MainForm.cs index c0576f4..65ae917 100644 --- a/MainForm.cs +++ b/MainForm.cs @@ -498,10 +498,10 @@ namespace MeshCentralRouter } } - private void Meshcentral_onToolUpdate(string url, string hash, int size) + private void Meshcentral_onToolUpdate(string url, string hash, int size, string serverhash) { - if (this.InvokeRequired) { this.Invoke(new MeshCentralServer.toolUpdateHandler(Meshcentral_onToolUpdate), url, hash, size); return; } - UpdateForm f = new UpdateForm(url, hash, size, args); + if (this.InvokeRequired) { this.Invoke(new MeshCentralServer.toolUpdateHandler(Meshcentral_onToolUpdate), url, hash, size, serverhash); return; } + UpdateForm f = new UpdateForm(url, hash, size, args, serverhash); if (f.ShowDialog(this) == DialogResult.OK) { } } diff --git a/MeshCentralServer.cs b/MeshCentralServer.cs index e7644d4..e6e8475 100644 --- a/MeshCentralServer.cs +++ b/MeshCentralServer.cs @@ -601,8 +601,12 @@ namespace MeshCentralRouter string loginkey = getValueFromQueryString(wsurl.Query, "key"); if (loginkey != null) { url += ("&key=" + loginkey); } + // Server TLS certificate hash + string serverhash = null; + if (jsonAction.ContainsKey("serverhash")) { serverhash = jsonAction["serverhash"].ToString(); } + // If the hashes don't match, event the tool update with URL - if (selfExecutableHashHex != hash) { onToolUpdate((string)url, (string)jsonAction["hash"], (int)jsonAction["size"]); } + if (selfExecutableHashHex != hash) { onToolUpdate((string)url, (string)jsonAction["hash"], (int)jsonAction["size"], serverhash); } } break; } @@ -637,7 +641,7 @@ namespace MeshCentralRouter public event onClipboardDataHandler onClipboardData; public delegate void twoFactorCookieHandler(string cookie); public event twoFactorCookieHandler onTwoFactorCookie; - public delegate void toolUpdateHandler(string url, string hash, int size); + public delegate void toolUpdateHandler(string url, string hash, int size, string serverhash); public event toolUpdateHandler onToolUpdate; public class xwebclient : IDisposable diff --git a/UpdateForm.cs b/UpdateForm.cs index 60e9f47..ca0979c 100644 --- a/UpdateForm.cs +++ b/UpdateForm.cs @@ -6,6 +6,7 @@ using System.Net.Security; using System.Windows.Forms; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; +using System.Text; namespace MeshCentralRouter { @@ -15,14 +16,16 @@ namespace MeshCentralRouter private string hash = null; private int size = 0; private string[] args = null; + private string serverTlsCertHash = null; - public UpdateForm(string url, string hash, int size, string[] args) + public UpdateForm(string url, string hash, int size, string[] args, string serverhash) { InitializeComponent(); this.url = url; this.hash = hash; this.size = size; this.args = args; + this.serverTlsCertHash = serverhash; } private void okButton_Click(object sender, EventArgs e) @@ -46,8 +49,10 @@ namespace MeshCentralRouter updateProgressBar.Visible = true; } - public static bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) + public bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { + // Check MeshCentral server's TLS certificate. This is our first security layer. + if ((serverTlsCertHash != null) && (serverTlsCertHash != certificate.GetCertHashString().ToLower()) && (serverTlsCertHash != GetMeshKeyHash(certificate).ToLower()) && (serverTlsCertHash != GetMeshCertHash(certificate).ToLower())) return false; return true; } @@ -112,5 +117,26 @@ namespace MeshCentralRouter catch (Exception ex) { updateMessage("Error: " + ex.ToString(), 2); } } + + // Return a modified base64 SHA384 hash string of the certificate public key + public static string GetMeshKeyHash(X509Certificate cert) + { + return ByteArrayToHexString(new SHA384Managed().ComputeHash(cert.GetPublicKey())); + } + + // Return a modified base64 SHA384 hash string of the certificate + public static string GetMeshCertHash(X509Certificate cert) + { + return ByteArrayToHexString(new SHA384Managed().ComputeHash(cert.GetRawCertData())); + } + + public static string ByteArrayToHexString(byte[] Bytes) + { + StringBuilder Result = new StringBuilder(Bytes.Length * 2); + string HexAlphabet = "0123456789ABCDEF"; + foreach (byte B in Bytes) { Result.Append(HexAlphabet[(int)(B >> 4)]); Result.Append(HexAlphabet[(int)(B & 0xF)]); } + return Result.ToString(); + } + } }