CP-31587 implements confirmation check before updating client

Signed-off-by: Christophe25 <christopher.lancaste1@citrix.com>
This commit is contained in:
Christophe25 2022-01-18 13:33:21 +00:00 committed by Konstantina Chremmou
parent 75f9b402ec
commit 755411a970
4 changed files with 106 additions and 44 deletions

View File

@ -276,6 +276,7 @@ namespace XenAdmin
this.aboutXenSourceAdminToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.aboutXenSourceAdminToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.MainMenuBar = new XenAdmin.Controls.MenuStripEx(); this.MainMenuBar = new XenAdmin.Controls.MenuStripEx();
this.updateClientToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.updateClientToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.skipToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.securityGroupsToolStripMenuItem = new XenAdmin.Commands.CommandToolStripMenuItem(); this.securityGroupsToolStripMenuItem = new XenAdmin.Commands.CommandToolStripMenuItem();
this.MenuPanel = new System.Windows.Forms.Panel(); this.MenuPanel = new System.Windows.Forms.Panel();
this.StatusStrip = new System.Windows.Forms.StatusStrip(); this.StatusStrip = new System.Windows.Forms.StatusStrip();
@ -284,6 +285,7 @@ namespace XenAdmin
this.statusLabelErrors = new System.Windows.Forms.ToolStripStatusLabel(); this.statusLabelErrors = new System.Windows.Forms.ToolStripStatusLabel();
this.statusLabelUpdates = new System.Windows.Forms.ToolStripStatusLabel(); this.statusLabelUpdates = new System.Windows.Forms.ToolStripStatusLabel();
this.statusLabelAlerts = 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(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
this.splitContainer1.Panel1.SuspendLayout(); this.splitContainer1.Panel1.SuspendLayout();
this.splitContainer1.Panel2.SuspendLayout(); this.splitContainer1.Panel2.SuspendLayout();
@ -1931,11 +1933,19 @@ namespace XenAdmin
// //
this.updateClientToolStripMenuItem.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right; this.updateClientToolStripMenuItem.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;
this.updateClientToolStripMenuItem.BackColor = System.Drawing.SystemColors.Window; 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"); resources.ApplyResources(this.updateClientToolStripMenuItem, "updateClientToolStripMenuItem");
this.updateClientToolStripMenuItem.Image = global::XenAdmin.Properties.Resources._075_WarningRound_h32bit_16; 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.Margin = new System.Windows.Forms.Padding(0, 0, 5, 0);
this.updateClientToolStripMenuItem.Name = "updateClientToolStripMenuItem"; 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 // securityGroupsToolStripMenuItem
// //
@ -2011,6 +2021,12 @@ namespace XenAdmin
this.statusLabelAlerts.VisitedLinkColor = System.Drawing.SystemColors.ControlDarkDark; this.statusLabelAlerts.VisitedLinkColor = System.Drawing.SystemColors.ControlDarkDark;
this.statusLabelAlerts.Click += new System.EventHandler(this.statusLabelAlerts_Click); 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 // MainWindow
// //
resources.ApplyResources(this, "$this"); resources.ApplyResources(this, "$this");
@ -2294,6 +2310,8 @@ namespace XenAdmin
private XenAdmin.Commands.CommandToolStripMenuItem toolStripMenuItemCertificate; private XenAdmin.Commands.CommandToolStripMenuItem toolStripMenuItemCertificate;
private XenAdmin.Commands.CommandToolStripMenuItem toolStripMenuItemResetCertificate; private XenAdmin.Commands.CommandToolStripMenuItem toolStripMenuItemResetCertificate;
private System.Windows.Forms.ToolStripMenuItem updateClientToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem updateClientToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem skipToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem downloadInstallToolStripMenuItem;
} }
} }

View File

@ -2655,7 +2655,7 @@ namespace XenAdmin
statusLabelUpdates.Text = string.Format(Messages.NOTIFICATIONS_SUBMODE_UPDATES_STATUS, updatesCount); statusLabelUpdates.Text = string.Format(Messages.NOTIFICATIONS_SUBMODE_UPDATES_STATUS, updatesCount);
statusLabelUpdates.Visible = updatesCount > 0; statusLabelUpdates.Visible = updatesCount > 0;
updateAlert = Updates.UpdateAlerts.FirstOrDefault(update => update is ClientUpdateAlert) as ClientUpdateAlert;
if (updatesPage.Visible) if (updatesPage.Visible)
{ {
TitleLabel.Text = NotificationsSubModeItem.GetText(NotificationsSubMode.Updates, updatesCount); TitleLabel.Text = NotificationsSubModeItem.GetText(NotificationsSubMode.Updates, updatesCount);
@ -2669,7 +2669,7 @@ namespace XenAdmin
Program.Invoke(this, () => { Program.Invoke(this, () => {
updateAlert = Updates.UpdateAlerts.FirstOrDefault(update => update is ClientUpdateAlert) as ClientUpdateAlert; 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); 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); 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)) 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);
dlg.ShowDialog(Parent); // 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);
}
}
} }
} }
} }

View File

@ -2784,14 +2784,26 @@
<data name="MainMenuBar.Font" type="System.Drawing.Font, System.Drawing"> <data name="MainMenuBar.Font" type="System.Drawing.Font, System.Drawing">
<value>Microsoft Sans Serif, 8.25pt</value> <value>Microsoft Sans Serif, 8.25pt</value>
</data> </data>
<data name="downloadInstallToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
<value>180, 22</value>
</data>
<data name="downloadInstallToolStripMenuItem.Text" xml:space="preserve">
<value>Download and Install</value>
</data>
<data name="skipToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
<value>180, 22</value>
</data>
<data name="skipToolStripMenuItem.Text" xml:space="preserve">
<value>Skip</value>
</data>
<data name="updateClientToolStripMenuItem.Enabled" type="System.Boolean, mscorlib"> <data name="updateClientToolStripMenuItem.Enabled" type="System.Boolean, mscorlib">
<value>False</value> <value>False</value>
</data> </data>
<data name="updateClientToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing"> <data name="updateClientToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
<value>99, 20</value> <value>70, 20</value>
</data> </data>
<data name="updateClientToolStripMenuItem.Text" xml:space="preserve"> <data name="updateClientToolStripMenuItem.Text" xml:space="preserve">
<value>Update Client</value> <value>Update</value>
</data> </data>
<data name="MainMenuBar.Location" type="System.Drawing.Point, System.Drawing"> <data name="MainMenuBar.Location" type="System.Drawing.Point, System.Drawing">
<value>0, 0</value> <value>0, 0</value>
@ -4074,6 +4086,12 @@
<data name="&gt;&gt;updateClientToolStripMenuItem.Type" xml:space="preserve"> <data name="&gt;&gt;updateClientToolStripMenuItem.Type" xml:space="preserve">
<value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data> </data>
<data name="&gt;&gt;skipToolStripMenuItem.Name" xml:space="preserve">
<value>skipToolStripMenuItem</value>
</data>
<data name="&gt;&gt;skipToolStripMenuItem.Type" xml:space="preserve">
<value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;securityGroupsToolStripMenuItem.Name" xml:space="preserve"> <data name="&gt;&gt;securityGroupsToolStripMenuItem.Name" xml:space="preserve">
<value>securityGroupsToolStripMenuItem</value> <value>securityGroupsToolStripMenuItem</value>
</data> </data>
@ -4110,6 +4128,12 @@
<data name="&gt;&gt;statusLabelAlerts.Type" xml:space="preserve"> <data name="&gt;&gt;statusLabelAlerts.Type" xml:space="preserve">
<value>System.Windows.Forms.ToolStripStatusLabel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Windows.Forms.ToolStripStatusLabel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data> </data>
<data name="&gt;&gt;downloadInstallToolStripMenuItem.Name" xml:space="preserve">
<value>downloadInstallToolStripMenuItem</value>
</data>
<data name="&gt;&gt;downloadInstallToolStripMenuItem.Type" xml:space="preserve">
<value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;$this.Name" xml:space="preserve"> <data name="&gt;&gt;$this.Name" xml:space="preserve">
<value>MainWindow</value> <value>MainWindow</value>
</data> </data>

View File

@ -40,6 +40,7 @@ using System.Diagnostics;
using System.Security.Cryptography; using System.Security.Cryptography;
using XenCenterLib; using XenCenterLib;
using System.Text; using System.Text;
using System.Security.Cryptography.X509Certificates;
namespace XenAdmin.Actions namespace XenAdmin.Actions
{ {
@ -192,67 +193,72 @@ namespace XenAdmin.Actions
if (Cancelling) if (Cancelling)
throw new CancelledException(); throw new CancelledException();
} }
if (ValidMsi())
ValidateMsi();
// Install the msi
try
{ {
// Install the downloaded msi if (File.Exists(outputPathAndFileName))
try
{ {
// Start the install process and end current // Start the install process, it will handle closing of application.
if (File.Exists(outputPathAndFileName)) Process.Start(outputPathAndFileName);
{ log.DebugFormat("Update {0} found and install started", updateName);
// Launch downloaded msi
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);
{
File.Delete(outputPathAndFileName);
}
log.Error("Exception occurred when installing CHC.", e);
throw;
} }
log.Error("Exception occurred when installing CHC.", e);
throw;
} }
Description = Messages.COMPLETED; Description = Messages.COMPLETED;
MarkCompleted(); MarkCompleted();
} }
private bool ValidMsi() private void ValidateMsi()
{ {
using (FileStream stream = new FileStream(outputPathAndFileName, FileMode.Open, FileAccess.Read)) using (FileStream stream = new FileStream(outputPathAndFileName, FileMode.Open, FileAccess.Read))
{ {
var hash = StreamUtilities.ComputeHash(stream, out var hashAlgorithm); var hash = StreamUtilities.ComputeHash(stream, out var hashAlgorithm);
//Convert to Hex string //Convert to Hex string
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
foreach (var b in hash) foreach (var b in hash)
{
sb.Append(b.ToString("x2")); sb.Append(b.ToString("x2"));
}
var calculatedChecksum = sb.ToString(); var calculatedChecksum = sb.ToString();
// Check if calculatedChecksum matches what is in chcupdates.xml // Check if calculatedChecksum matches what is in chcupdates.xml
if (checksum != calculatedChecksum) 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; if (!valid)
throw new Exception("Invalid digital signature on msi.");
// 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();
} }
void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)