From 755411a970ca239721c5f64d24d26070031a7ae1 Mon Sep 17 00:00:00 2001 From: Christophe25 Date: Tue, 18 Jan 2022 13:33:21 +0000 Subject: [PATCH] CP-31587 implements confirmation check before updating client Signed-off-by: Christophe25 --- XenAdmin/MainWindow.Designer.cs | 20 ++++- XenAdmin/MainWindow.cs | 26 +++++-- XenAdmin/MainWindow.resx | 28 ++++++- .../Updates/DownloadAndUpdateClientAction.cs | 76 ++++++++++--------- 4 files changed, 106 insertions(+), 44 deletions(-) diff --git a/XenAdmin/MainWindow.Designer.cs b/XenAdmin/MainWindow.Designer.cs index a11282845..20681cec2 100644 --- a/XenAdmin/MainWindow.Designer.cs +++ b/XenAdmin/MainWindow.Designer.cs @@ -276,6 +276,7 @@ namespace XenAdmin this.aboutXenSourceAdminToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.MainMenuBar = new XenAdmin.Controls.MenuStripEx(); this.updateClientToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.skipToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.securityGroupsToolStripMenuItem = new XenAdmin.Commands.CommandToolStripMenuItem(); this.MenuPanel = new System.Windows.Forms.Panel(); this.StatusStrip = new System.Windows.Forms.StatusStrip(); @@ -284,6 +285,7 @@ namespace XenAdmin this.statusLabelErrors = new System.Windows.Forms.ToolStripStatusLabel(); this.statusLabelUpdates = new System.Windows.Forms.ToolStripStatusLabel(); this.statusLabelAlerts = new System.Windows.Forms.ToolStripStatusLabel(); + this.downloadInstallToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); this.splitContainer1.Panel1.SuspendLayout(); this.splitContainer1.Panel2.SuspendLayout(); @@ -1931,11 +1933,19 @@ namespace XenAdmin // this.updateClientToolStripMenuItem.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right; this.updateClientToolStripMenuItem.BackColor = System.Drawing.SystemColors.Window; + this.updateClientToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.downloadInstallToolStripMenuItem, + this.skipToolStripMenuItem}); resources.ApplyResources(this.updateClientToolStripMenuItem, "updateClientToolStripMenuItem"); this.updateClientToolStripMenuItem.Image = global::XenAdmin.Properties.Resources._075_WarningRound_h32bit_16; this.updateClientToolStripMenuItem.Margin = new System.Windows.Forms.Padding(0, 0, 5, 0); this.updateClientToolStripMenuItem.Name = "updateClientToolStripMenuItem"; - this.updateClientToolStripMenuItem.Click += new System.EventHandler(this.updateToolStripMenuItem_Click); + // + // skipToolStripMenuItem + // + this.skipToolStripMenuItem.Name = "skipToolStripMenuItem"; + resources.ApplyResources(this.skipToolStripMenuItem, "skipToolStripMenuItem"); + this.skipToolStripMenuItem.Click += new System.EventHandler(this.skipToolStripMenuItem_Click); // // securityGroupsToolStripMenuItem // @@ -2011,6 +2021,12 @@ namespace XenAdmin this.statusLabelAlerts.VisitedLinkColor = System.Drawing.SystemColors.ControlDarkDark; this.statusLabelAlerts.Click += new System.EventHandler(this.statusLabelAlerts_Click); // + // downloadInstallToolStripMenuItem + // + this.downloadInstallToolStripMenuItem.Name = "downloadInstallToolStripMenuItem"; + resources.ApplyResources(this.downloadInstallToolStripMenuItem, "downloadInstallToolStripMenuItem"); + this.downloadInstallToolStripMenuItem.Click += new System.EventHandler(this.downloadInstallToolStripMenuItem_Click); + // // MainWindow // resources.ApplyResources(this, "$this"); @@ -2294,6 +2310,8 @@ namespace XenAdmin private XenAdmin.Commands.CommandToolStripMenuItem toolStripMenuItemCertificate; private XenAdmin.Commands.CommandToolStripMenuItem toolStripMenuItemResetCertificate; private System.Windows.Forms.ToolStripMenuItem updateClientToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem skipToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem downloadInstallToolStripMenuItem; } } diff --git a/XenAdmin/MainWindow.cs b/XenAdmin/MainWindow.cs index 09dcd5013..c94abf3ff 100755 --- a/XenAdmin/MainWindow.cs +++ b/XenAdmin/MainWindow.cs @@ -2655,7 +2655,7 @@ namespace XenAdmin statusLabelUpdates.Text = string.Format(Messages.NOTIFICATIONS_SUBMODE_UPDATES_STATUS, updatesCount); statusLabelUpdates.Visible = updatesCount > 0; - + updateAlert = Updates.UpdateAlerts.FirstOrDefault(update => update is ClientUpdateAlert) as ClientUpdateAlert; if (updatesPage.Visible) { TitleLabel.Text = NotificationsSubModeItem.GetText(NotificationsSubMode.Updates, updatesCount); @@ -2669,7 +2669,7 @@ namespace XenAdmin Program.Invoke(this, () => { updateAlert = Updates.UpdateAlerts.FirstOrDefault(update => update is ClientUpdateAlert) as ClientUpdateAlert; - updateClientToolStripMenuItem.Enabled = true;//updateAlert != null; + updateClientToolStripMenuItem.Enabled = updateAlert != null; }); } @@ -3330,12 +3330,26 @@ namespace XenAdmin navigationPane.SwitchToNotificationsView(NotificationsSubMode.Events); } - private void updateToolStripMenuItem_Click(object sender, EventArgs e) - { + private void skipToolStripMenuItem_Click(object sender, EventArgs e) + { + updateAlert.Dismiss(); + Program.Invoke(this, () => { updateClientToolStripMenuItem.Enabled = false; }); + } + + private void downloadInstallToolStripMenuItem_Click(object sender, EventArgs e) + { var downloadAndInstallClientAction = new DownloadAndUpdateClientAction(updateAlert.Name, new Uri(updateAlert.NewVersion.Url), Path.Combine(Path.GetTempPath(), $"{updateAlert.Name}.msi"), true, updateAlert.Checksum); - using (var dlg = new ActionProgressDialog(downloadAndInstallClientAction, ProgressBarStyle.Marquee)) - dlg.ShowDialog(Parent); + DialogResult dialogResult = MessageBox.Show("In order to update your client will be closed. Is all your work done and saved?.", "Are you ready to update?", MessageBoxButtons.YesNo); + // Only start if user says yes. + if (dialogResult == DialogResult.Yes) + { + // Start the download and show progress + using (var dlg = new ActionProgressDialog(downloadAndInstallClientAction, ProgressBarStyle.Marquee)) + { + dlg.ShowDialog(Parent); + } + } } } } diff --git a/XenAdmin/MainWindow.resx b/XenAdmin/MainWindow.resx index 0bc377f24..c9e9697ff 100644 --- a/XenAdmin/MainWindow.resx +++ b/XenAdmin/MainWindow.resx @@ -2784,14 +2784,26 @@ Microsoft Sans Serif, 8.25pt + + 180, 22 + + + Download and Install + + + 180, 22 + + + Skip + False - 99, 20 + 70, 20 - Update Client + Update 0, 0 @@ -4074,6 +4086,12 @@ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + skipToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + securityGroupsToolStripMenuItem @@ -4110,6 +4128,12 @@ System.Windows.Forms.ToolStripStatusLabel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + downloadInstallToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + MainWindow diff --git a/XenModel/Actions/Updates/DownloadAndUpdateClientAction.cs b/XenModel/Actions/Updates/DownloadAndUpdateClientAction.cs index 2079028f5..97bf258ce 100644 --- a/XenModel/Actions/Updates/DownloadAndUpdateClientAction.cs +++ b/XenModel/Actions/Updates/DownloadAndUpdateClientAction.cs @@ -40,6 +40,7 @@ using System.Diagnostics; using System.Security.Cryptography; using XenCenterLib; using System.Text; +using System.Security.Cryptography.X509Certificates; namespace XenAdmin.Actions { @@ -192,67 +193,72 @@ namespace XenAdmin.Actions if (Cancelling) throw new CancelledException(); } - if (ValidMsi()) + + ValidateMsi(); + + // Install the msi + try { - // Install the downloaded msi - try + if (File.Exists(outputPathAndFileName)) { - // Start the install process and end current - if (File.Exists(outputPathAndFileName)) - { - // Launch downloaded msi - Process.Start(outputPathAndFileName); - log.DebugFormat("Update {0} found and install started", updateName); - } + // Start the install process, it will handle closing of application. + Process.Start(outputPathAndFileName); + log.DebugFormat("Update {0} found and install started", updateName); } - catch (Exception e) + } + catch (Exception e) + { + if (File.Exists(outputPathAndFileName)) { - if (File.Exists(outputPathAndFileName)) - { - File.Delete(outputPathAndFileName); - } - log.Error("Exception occurred when installing CHC.", e); - throw; + File.Delete(outputPathAndFileName); } + log.Error("Exception occurred when installing CHC.", e); + throw; } Description = Messages.COMPLETED; MarkCompleted(); } - private bool ValidMsi() + private void ValidateMsi() { + using (FileStream stream = new FileStream(outputPathAndFileName, FileMode.Open, FileAccess.Read)) { var hash = StreamUtilities.ComputeHash(stream, out var hashAlgorithm); + //Convert to Hex string StringBuilder sb = new StringBuilder(); foreach (var b in hash) - { sb.Append(b.ToString("x2")); - } + var calculatedChecksum = sb.ToString(); + // Check if calculatedChecksum matches what is in chcupdates.xml if (checksum != calculatedChecksum) + throw new Exception("The checksum of the downloaded MSI does not match what is expected. This indicates it has been tampered with."); + } + + var valid = false; + // Check digital signature of .msi + using (var basicSigner = X509Certificate.CreateFromSignedFile(outputPathAndFileName)) + { + using (var cert = new X509Certificate2(basicSigner)) { - return false; + try + { + valid = cert.Verify(); + valid = false; + } + catch (Exception e) + { + throw new Exception("Unable to validate digital signature on msi.", e); + } } } - return true; - - // TODO: Check digital signature of .msi - - } - // Display the byte array in a readable format. - public static void PrintByteArray(byte[] array) - { - for (int i = 0; i < array.Length; i++) - { - Console.Write($"{array[i]:X2}"); - if ((i % 4) == 3) Console.Write(" "); - } - Console.WriteLine(); + if (!valid) + throw new Exception("Invalid digital signature on msi."); } void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)