summaryrefslogtreecommitdiffstats
path: root/src/main.lib/Clients/IIS
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.lib/Clients/IIS')
-rw-r--r--src/main.lib/Clients/IIS/IISClient.cs117
-rw-r--r--src/main.lib/Clients/IIS/IISHelper.cs17
-rw-r--r--src/main.lib/Clients/IIS/IISHttpBindingUpdater.cs42
-rw-r--r--src/main.lib/Clients/IIS/IISSiteWrapper.cs2
4 files changed, 108 insertions, 70 deletions
diff --git a/src/main.lib/Clients/IIS/IISClient.cs b/src/main.lib/Clients/IIS/IISClient.cs
index 3ee4386..3171531 100644
--- a/src/main.lib/Clients/IIS/IISClient.cs
+++ b/src/main.lib/Clients/IIS/IISClient.cs
@@ -18,8 +18,10 @@ namespace PKISharp.WACS.Clients.IIS
public Version Version { get; set; }
[SuppressMessage("Code Quality", "IDE0069:Disposable fields should be disposed", Justification = "Actually is disposed")]
- private ServerManager? _ServerManager;
private readonly ILogService _log;
+ private ServerManager? _serverManager;
+ private List<IISSiteWrapper>? _webSites = null;
+ private List<IISSiteWrapper>? _ftpSites = null;
public IISClient(ILogService log)
{
@@ -34,14 +36,16 @@ namespace PKISharp.WACS.Clients.IIS
{
get
{
- if (_ServerManager == null)
+ if (_serverManager == null)
{
if (Version.Major > 0)
{
- _ServerManager = new ServerManager();
+ _serverManager = new ServerManager();
+ _webSites = null;
+ _ftpSites = null;
}
}
- return _ServerManager;
+ return _serverManager;
}
}
@@ -53,11 +57,11 @@ namespace PKISharp.WACS.Clients.IIS
/// </summary>
private void Commit()
{
- if (_ServerManager != null)
+ if (_serverManager != null)
{
try
{
- _ServerManager.CommitChanges();
+ _serverManager.CommitChanges();
}
catch
{
@@ -73,18 +77,29 @@ namespace PKISharp.WACS.Clients.IIS
public void Refresh()
{
- if (_ServerManager != null)
+ _webSites = null;
+ _ftpSites = null;
+ if (_serverManager != null)
{
- _ServerManager.Dispose();
- _ServerManager = null;
+ _serverManager.Dispose();
+ _serverManager = null;
}
}
#region _ Basic retrieval _
+ IEnumerable<IIISSite> IIISClient.WebSites => WebSites;
+
+ IEnumerable<IIISSite> IIISClient.FtpSites => FtpSites;
+
+ IIISSite IIISClient.GetWebSite(long id) => GetWebSite(id);
+
+ IIISSite IIISClient.GetFtpSite(long id) => GetFtpSite(id);
+
public bool HasWebSites => Version.Major > 0 && WebSites.Any();
- IEnumerable<IIISSite> IIISClient.WebSites => WebSites;
+ public bool HasFtpSites => Version >= new Version(7, 5) && FtpSites.Any();
+
public IEnumerable<IISSiteWrapper> WebSites
{
get
@@ -93,59 +108,65 @@ namespace PKISharp.WACS.Clients.IIS
{
return new List<IISSiteWrapper>();
}
- return ServerManager.Sites.AsEnumerable().
- Where(s => s.Bindings.Any(sb => sb.Protocol == "http" || sb.Protocol == "https")).
- Where(s =>
- {
- try
- {
- return s.State == ObjectState.Started;
- }
- catch
- {
- // Prevent COMExceptions such as misconfigured
- // application pools from crashing the whole
- _log.Warning("Unable to determine state for Site {id}", s.Id);
- return false;
- }
- }).
- OrderBy(s => s.Name).
- Select(x => new IISSiteWrapper(x));
+ if (_webSites == null)
+ {
+ _webSites = ServerManager.Sites.AsEnumerable().
+ Where(s => s.Bindings.Any(sb => sb.Protocol == "http" || sb.Protocol == "https")).
+ Where(s =>
+ {
+
+ try
+ {
+ return s.State == ObjectState.Started;
+ }
+ catch
+ {
+ // Prevent COMExceptions such as misconfigured
+ // application pools from crashing the whole
+ _log.Warning("Unable to determine state for Site {id}", s.Id);
+ return false;
+ }
+ }).
+ OrderBy(s => s.Name).
+ Select(x => new IISSiteWrapper(x)).
+ ToList();
+ }
+ return _webSites;
}
}
- IIISSite IIISClient.GetWebSite(long id) => GetWebSite(id);
- public IISSiteWrapper GetWebSite(long id)
+ public IEnumerable<IISSiteWrapper> FtpSites
{
- foreach (var site in WebSites)
+ get
{
- if (site.Site.Id == id)
+ if (ServerManager == null)
{
- return site;
+ return new List<IISSiteWrapper>();
+ }
+ if (_ftpSites == null)
+ {
+ _ftpSites = ServerManager.Sites.AsEnumerable().
+ Where(s => s.Bindings.Any(sb => sb.Protocol == "ftp")).
+ OrderBy(s => s.Name).
+ Select(x => new IISSiteWrapper(x)).
+ ToList();
}
+ return _ftpSites;
}
- throw new Exception($"Unable to find IIS SiteId #{id}");
}
- public bool HasFtpSites => Version >= new Version(7, 5) && FtpSites.Any();
-
- IEnumerable<IIISSite> IIISClient.FtpSites => FtpSites;
- public IEnumerable<IISSiteWrapper> FtpSites
+ public IISSiteWrapper GetWebSite(long id)
{
- get
+ foreach (var site in WebSites)
{
- if (ServerManager == null)
+ if (site.Site.Id == id)
{
- return new List<IISSiteWrapper>();
+ return site;
}
- return ServerManager.Sites.AsEnumerable().
- Where(s => s.Bindings.Any(sb => sb.Protocol == "ftp")).
- OrderBy(s => s.Name).
- Select(x => new IISSiteWrapper(x));
}
+ throw new Exception($"Unable to find IIS SiteId #{id}");
}
- IIISSite IIISClient.GetFtpSite(long id) => GetFtpSite(id);
public IISSiteWrapper GetFtpSite(long id)
{
foreach (var site in FtpSites)
@@ -316,9 +337,9 @@ namespace PKISharp.WACS.Clients.IIS
{
if (disposing)
{
- if (_ServerManager != null)
+ if (_serverManager != null)
{
- _ServerManager.Dispose();
+ _serverManager.Dispose();
}
}
disposedValue = true;
diff --git a/src/main.lib/Clients/IIS/IISHelper.cs b/src/main.lib/Clients/IIS/IISHelper.cs
index 63a8649..7f28176 100644
--- a/src/main.lib/Clients/IIS/IISHelper.cs
+++ b/src/main.lib/Clients/IIS/IISHelper.cs
@@ -79,12 +79,17 @@ namespace PKISharp.WACS.Clients.IIS
Where(sb => !string.IsNullOrWhiteSpace(sb.binding.Host)).
ToList();
+ static string lookupKey(IIISSite site, IIISBinding binding) =>
+ site.Id + "#" + binding.BindingInformation.ToLower();
+
// Option: hide http bindings when there are already https equivalents
- var https = siteBindings.Where(sb =>
- sb.binding.Protocol == "https" ||
- sb.site.Bindings.Any(other =>
- other.Protocol == "https" &&
- string.Equals(sb.binding.Host, other.Host, StringComparison.InvariantCultureIgnoreCase))).ToList();
+ var https = siteBindings
+ .Where(sb =>
+ sb.binding.Protocol == "https" ||
+ sb.site.Bindings.Any(other =>
+ other.Protocol == "https" &&
+ string.Equals(sb.binding.Host, other.Host, StringComparison.InvariantCultureIgnoreCase)))
+ .ToDictionary(sb => lookupKey(sb.site, sb.binding));
var targets = siteBindings.
Select(sb => new
@@ -92,7 +97,7 @@ namespace PKISharp.WACS.Clients.IIS
host = sb.binding.Host.ToLower(),
sb.site,
sb.binding,
- https = https.Contains(sb)
+ https = https.ContainsKey(lookupKey(sb.site, sb.binding))
}).
Select(sbi => new IISBindingOption(sbi.host, _idnMapping.GetAscii(sbi.host))
{
diff --git a/src/main.lib/Clients/IIS/IISHttpBindingUpdater.cs b/src/main.lib/Clients/IIS/IISHttpBindingUpdater.cs
index 9e8f3bf..43945c3 100644
--- a/src/main.lib/Clients/IIS/IISHttpBindingUpdater.cs
+++ b/src/main.lib/Clients/IIS/IISHttpBindingUpdater.cs
@@ -61,9 +61,11 @@ namespace PKISharp.WACS.Clients.IIS
{
try
{
- UpdateBinding(site, binding, bindingOptions);
found.Add(binding.Host);
- bindingsUpdated += 1;
+ if (UpdateBinding(site, binding, bindingOptions))
+ {
+ bindingsUpdated += 1;
+ }
}
catch (Exception ex)
{
@@ -91,7 +93,7 @@ namespace PKISharp.WACS.Clients.IIS
var current = todo.First();
try
{
- var binding = AddOrUpdateBindings(
+ var (hostFound, commitRequired) = AddOrUpdateBindings(
allBindings.Select(x => x.binding).ToArray(),
targetSite,
bindingOptions.WithHost(current));
@@ -99,7 +101,7 @@ namespace PKISharp.WACS.Clients.IIS
// Allow a single newly created binding to match with
// multiple hostnames on the todo list, e.g. the *.example.com binding
// matches with both a.example.com and b.example.com
- if (binding == null)
+ if (hostFound == null)
{
// We were unable to create the binding because it would
// lead to a duplicate. Pretend that we did add it to
@@ -108,8 +110,11 @@ namespace PKISharp.WACS.Clients.IIS
}
else
{
- found.Add(binding);
- bindingsUpdated += 1;
+ found.Add(hostFound);
+ if (commitRequired)
+ {
+ bindingsUpdated += 1;
+ }
}
}
catch (Exception ex)
@@ -143,13 +148,16 @@ namespace PKISharp.WACS.Clients.IIS
/// <param name="port"></param>
/// <param name="ipAddress"></param>
/// <param name="fuzzy"></param>
- private string? AddOrUpdateBindings(TBinding[] allBindings, TSite site, BindingOptions bindingOptions)
+ private (string?, bool) AddOrUpdateBindings(TBinding[] allBindings, TSite site, BindingOptions bindingOptions)
{
if (bindingOptions.Host == null)
{
throw new InvalidOperationException("bindingOptions.Host is null");
}
+ // Require IIS manager to commit
+ var commitRequired = false;
+
// Get all bindings which could map to the host
var matchingBindings = site.Bindings.
Select(x => new { binding = x, fit = Fits(x.Host, bindingOptions.Host, bindingOptions.Flags) }).
@@ -167,7 +175,7 @@ namespace PKISharp.WACS.Clients.IIS
// All existing https bindings
var existing = bestMatches.
Where(x => x.binding.Protocol == "https").
- Select(x => x.binding.BindingInformation).
+ Select(x => x.binding.BindingInformation.ToLower()).
ToList();
foreach (var match in bestMatches)
@@ -178,7 +186,7 @@ namespace PKISharp.WACS.Clients.IIS
if (UpdateExistingBindingFlags(bindingOptions.Flags, match.binding, allBindings, out var updateFlags))
{
var updateOptions = bindingOptions.WithFlags(updateFlags);
- UpdateBinding(site, match.binding, updateOptions);
+ commitRequired = UpdateBinding(site, match.binding, updateOptions);
}
}
else
@@ -194,14 +202,15 @@ namespace PKISharp.WACS.Clients.IIS
}
var binding = addOptions.Binding;
- if (!existing.Contains(binding) && AllowAdd(addOptions, allBindings))
+ if (!existing.Contains(binding.ToLower()) && AllowAdd(addOptions, allBindings))
{
AddBinding(site, addOptions);
existing.Add(binding);
+ commitRequired = true;
}
}
}
- return bestMatch.binding.Host;
+ return (bestMatch.binding.Host, commitRequired);
}
}
@@ -210,11 +219,12 @@ namespace PKISharp.WACS.Clients.IIS
if (AllowAdd(bindingOptions, allBindings))
{
AddBinding(site, bindingOptions);
- return bindingOptions.Host;
+ commitRequired = true;
+ return (bindingOptions.Host, commitRequired);
}
// We haven't been able to do anything
- return null;
+ return (null, commitRequired);
}
/// <summary>
@@ -243,7 +253,7 @@ namespace PKISharp.WACS.Clients.IIS
// In general we shouldn't create duplicate bindings
// because then only one of them will be usable at the
// same time.
- if (allBindings.Any(x => x.BindingInformation == bindingInfoFull))
+ if (allBindings.Any(x => string.Equals(x.BindingInformation, bindingInfoFull, StringComparison.InvariantCultureIgnoreCase)))
{
_log.Warning($"Prevent adding duplicate binding for {bindingInfoFull}");
return false;
@@ -365,7 +375,7 @@ namespace PKISharp.WACS.Clients.IIS
_client.AddBinding(site, options);
}
- private void UpdateBinding(TSite site, TBinding existingBinding, BindingOptions options)
+ private bool UpdateBinding(TSite site, TBinding existingBinding, BindingOptions options)
{
// Check flags
options = options.WithFlags(CheckFlags(false, existingBinding.Host, options.Flags));
@@ -377,6 +387,7 @@ namespace PKISharp.WACS.Clients.IIS
string.Equals(existingBinding.CertificateStoreName, options.Store, StringComparison.InvariantCultureIgnoreCase))))
{
_log.Verbose("No binding update needed");
+ return false;
}
else
{
@@ -401,6 +412,7 @@ namespace PKISharp.WACS.Clients.IIS
existingBinding.Port,
(int)options.Flags);
_client.UpdateBinding(site, existingBinding, options);
+ return true;
}
}
diff --git a/src/main.lib/Clients/IIS/IISSiteWrapper.cs b/src/main.lib/Clients/IIS/IISSiteWrapper.cs
index cb1ecd2..9bc204b 100644
--- a/src/main.lib/Clients/IIS/IISSiteWrapper.cs
+++ b/src/main.lib/Clients/IIS/IISSiteWrapper.cs
@@ -24,7 +24,7 @@ namespace PKISharp.WACS.Clients.IIS
{
Site = site;
- Bindings = site.Bindings.Select(x => new IISBindingWrapper(x));
+ Bindings = site.Bindings.Select(x => new IISBindingWrapper(x)).ToList();
}
}