Skip to content

Commit ad4f3d9

Browse files
author
Konstantina Chremmou
committed
Cmdlet refactoring:
- Moved certificate methods to the Connect-XenServer cmdlet and refactored them to avoid multiple loads of the global variable KnownServerCertificatesFilePath. - Fixed accessibility of CommonCmdletFunctions members. Signed-off-by: Konstantina Chremmou <[email protected]>
1 parent 769c863 commit ad4f3d9

File tree

2 files changed

+76
-80
lines changed

2 files changed

+76
-80
lines changed

ocaml/sdk-gen/powershell/autogen/src/CommonCmdletFunctions.cs

Lines changed: 5 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,11 @@
3939

4040
namespace Citrix.XenServer
4141
{
42-
class CommonCmdletFunctions
42+
internal class CommonCmdletFunctions
4343
{
4444
private const string SessionsVariable = "global:Citrix.XenServer.Sessions";
45-
4645
private const string DefaultSessionVariable = "global:XenServer_Default_Session";
4746

48-
private const string KnownServerCertificatesFilePathVariable = "global:KnownServerCertificatesFilePath";
49-
5047
static CommonCmdletFunctions()
5148
{
5249
Session.UserAgent = string.Format("XenServerPSModule/{0}", Assembly.GetExecutingAssembly().GetName().Version);
@@ -78,72 +75,12 @@ internal static void SetDefaultXenSession(PSCmdlet cmdlet, Session session)
7875
cmdlet.SessionState.PSVariable.Set(DefaultSessionVariable, session);
7976
}
8077

81-
internal static string GetKnownServerCertificatesFilePathVariable(PSCmdlet cmdlet)
82-
{
83-
var knownCertificatesFilePathObject = cmdlet.SessionState.PSVariable.GetValue(KnownServerCertificatesFilePathVariable);
84-
if (knownCertificatesFilePathObject is PSObject psObject)
85-
return psObject.BaseObject as string;
86-
return knownCertificatesFilePathObject?.ToString() ?? string.Empty;
87-
}
88-
8978
internal static string GetUrl(string hostname, int port)
9079
{
91-
return string.Format("{0}://{1}:{2}", port == 80 ? "http" : "https", hostname, port);
92-
}
93-
94-
public static Dictionary<string, string> LoadCertificates(PSCmdlet cmdlet)
95-
{
96-
Dictionary<string, string> certificates = new Dictionary<string, string>();
97-
var knownServerCertificatesFilePath = GetKnownServerCertificatesFilePathVariable(cmdlet);
98-
99-
if (File.Exists(knownServerCertificatesFilePath))
100-
{
101-
XmlDocument doc = new XmlDocument();
102-
doc.Load(knownServerCertificatesFilePath);
103-
104-
foreach (XmlNode node in doc.GetElementsByTagName("certificate"))
105-
{
106-
XmlAttribute hostAtt = node.Attributes?["hostname"];
107-
XmlAttribute fngprtAtt = node.Attributes?["fingerprint"];
108-
109-
if (hostAtt != null && fngprtAtt != null)
110-
certificates[hostAtt.Value] = fngprtAtt.Value;
111-
}
112-
}
113-
114-
return certificates;
115-
}
116-
117-
public static void SaveCertificates(PSCmdlet cmdlet, Dictionary<string, string> certificates)
118-
{
119-
var knownServerCertificatesFilePath = GetKnownServerCertificatesFilePathVariable(cmdlet);
120-
string dirName = Path.GetDirectoryName(knownServerCertificatesFilePath);
121-
122-
if (!Directory.Exists(dirName))
123-
Directory.CreateDirectory(dirName);
124-
125-
XmlDocument doc = new XmlDocument();
126-
XmlDeclaration decl = doc.CreateXmlDeclaration("1.0", "utf-8", null);
127-
doc.AppendChild(decl);
128-
XmlNode node = doc.CreateElement("certificates");
129-
130-
foreach (KeyValuePair<string, string> cert in certificates)
131-
{
132-
XmlNode certNode = doc.CreateElement("certificate");
133-
XmlAttribute hostname = doc.CreateAttribute("hostname");
134-
XmlAttribute fingerprint = doc.CreateAttribute("fingerprint");
135-
hostname.Value = cert.Key;
136-
fingerprint.Value = cert.Value;
137-
certNode.Attributes?.Append(hostname);
138-
certNode.Attributes?.Append(fingerprint);
139-
node.AppendChild(certNode);
140-
}
141-
142-
doc.AppendChild(node);
143-
doc.Save(knownServerCertificatesFilePath);
80+
return $"{(port == 80 ? "http" : "https")}://{hostname}:{port}";
14481
}
14582

146-
public static string FingerprintPrettyString(string fingerprint)
83+
internal static string FingerprintPrettyString(string fingerprint)
14784
{
14885
List<string> pairs = new List<string>();
14986
while (fingerprint.Length > 1)
@@ -157,7 +94,7 @@ public static string FingerprintPrettyString(string fingerprint)
15794
return string.Join(":", pairs.ToArray());
15895
}
15996

160-
public static Dictionary<T, S> ConvertHashTableToDictionary<T, S>(Hashtable tbl)
97+
internal static Dictionary<T, S> ConvertHashTableToDictionary<T, S>(Hashtable tbl)
16198
{
16299
if (tbl == null)
163100
return null;
@@ -169,7 +106,7 @@ public static Dictionary<T, S> ConvertHashTableToDictionary<T, S>(Hashtable tbl)
169106
return dict;
170107
}
171108

172-
public static Hashtable ConvertDictionaryToHashtable<T, S>(Dictionary<T, S> dict)
109+
internal static Hashtable ConvertDictionaryToHashtable<T, S>(Dictionary<T, S> dict)
173110
{
174111
if (dict == null)
175112
return null;

ocaml/sdk-gen/powershell/autogen/src/Connect-XenServer.cs

Lines changed: 71 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,24 @@
2929

3030
using System;
3131
using System.Collections.Generic;
32+
using System.IO;
3233
using System.Management.Automation;
3334
using System.Net;
3435
using System.Net.Security;
3536
using System.Runtime.InteropServices;
3637
using System.Security;
3738
using System.Security.Cryptography;
3839
using System.Security.Cryptography.X509Certificates;
40+
using System.Xml;
3941
using XenAPI;
4042

4143
namespace Citrix.XenServer.Commands
4244
{
4345
[Cmdlet("Connect", "XenServer")]
4446
public class ConnectXenServerCommand : PSCmdlet
4547
{
48+
private const string CertificatesPathVariable = "global:KnownServerCertificatesFilePath";
49+
4650
private readonly object _certificateValidationLock = new object();
4751

4852
public ConnectXenServerCommand()
@@ -214,7 +218,10 @@ protected override void ProcessRecord()
214218
{
215219
if (ShouldContinue(ex.Message, ex.Caption))
216220
{
217-
AddCertificate(ex.Hostname, ex.Fingerprint);
221+
var certPath = GetCertificatesPath();
222+
var certificates = LoadCertificates(certPath);
223+
certificates[ex.Hostname] = ex.Fingerprint;
224+
SaveCertificates(certPath, certificates);
218225
i--;
219226
continue;
220227
}
@@ -254,13 +261,6 @@ protected override void ProcessRecord()
254261
WriteObject(newSessions.Values, true);
255262
}
256263

257-
private void AddCertificate(string hostname, string fingerprint)
258-
{
259-
var certificates = CommonCmdletFunctions.LoadCertificates(this);
260-
certificates[hostname] = fingerprint;
261-
CommonCmdletFunctions.SaveCertificates(this, certificates);
262-
}
263-
264264
private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
265265
{
266266
if (sslPolicyErrors == SslPolicyErrors.None)
@@ -277,11 +277,11 @@ private bool ValidateServerCertificate(object sender, X509Certificate certificat
277277

278278
bool trusted = VerifyInAllStores(new X509Certificate2(certificate));
279279

280-
var certificates = CommonCmdletFunctions.LoadCertificates(this);
280+
var certPath = GetCertificatesPath();
281+
var certificates = LoadCertificates(certPath);
281282

282-
if (certificates.ContainsKey(hostname))
283+
if (certificates.TryGetValue(hostname, out var fingerprintOld))
283284
{
284-
string fingerprintOld = certificates[hostname];
285285
if (fingerprintOld == fingerprint)
286286
return true;
287287

@@ -295,7 +295,7 @@ private bool ValidateServerCertificate(object sender, X509Certificate certificat
295295
}
296296

297297
certificates[hostname] = fingerprint;
298-
CommonCmdletFunctions.SaveCertificates(this, certificates);
298+
SaveCertificates(certPath, certificates);
299299
return true;
300300
}
301301
}
@@ -312,6 +312,65 @@ private bool VerifyInAllStores(X509Certificate2 certificate2)
312312
return false;
313313
}
314314
}
315+
316+
private string GetCertificatesPath()
317+
{
318+
var certPathObject = SessionState.PSVariable.GetValue(CertificatesPathVariable);
319+
320+
return certPathObject is PSObject psObject
321+
? psObject.BaseObject as string
322+
: certPathObject?.ToString() ?? string.Empty;
323+
}
324+
325+
private Dictionary<string, string> LoadCertificates(string certPath)
326+
{
327+
var certificates = new Dictionary<string, string>();
328+
329+
if (File.Exists(certPath))
330+
{
331+
var doc = new XmlDocument();
332+
doc.Load(certPath);
333+
334+
foreach (XmlNode node in doc.GetElementsByTagName("certificate"))
335+
{
336+
var hostAtt = node.Attributes?["hostname"];
337+
var fngprtAtt = node.Attributes?["fingerprint"];
338+
339+
if (hostAtt != null && fngprtAtt != null)
340+
certificates[hostAtt.Value] = fngprtAtt.Value;
341+
}
342+
}
343+
344+
return certificates;
345+
}
346+
347+
private void SaveCertificates(string certPath, Dictionary<string, string> certificates)
348+
{
349+
string dirName = Path.GetDirectoryName(certPath);
350+
351+
if (!Directory.Exists(dirName))
352+
Directory.CreateDirectory(dirName);
353+
354+
XmlDocument doc = new XmlDocument();
355+
XmlDeclaration decl = doc.CreateXmlDeclaration("1.0", "utf-8", null);
356+
doc.AppendChild(decl);
357+
XmlNode node = doc.CreateElement("certificates");
358+
359+
foreach (KeyValuePair<string, string> cert in certificates)
360+
{
361+
XmlNode certNode = doc.CreateElement("certificate");
362+
XmlAttribute hostname = doc.CreateAttribute("hostname");
363+
XmlAttribute fingerprint = doc.CreateAttribute("fingerprint");
364+
hostname.Value = cert.Key;
365+
fingerprint.Value = cert.Value;
366+
certNode.Attributes?.Append(hostname);
367+
certNode.Attributes?.Append(fingerprint);
368+
node.AppendChild(certNode);
369+
}
370+
371+
doc.AppendChild(node);
372+
doc.Save(certPath);
373+
}
315374
}
316375

317376
internal abstract class CertificateValidationException : Exception

0 commit comments

Comments
 (0)