summaryrefslogtreecommitdiffstats
path: root/src/main.lib/Plugins/ValidationPlugins/Http
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.lib/Plugins/ValidationPlugins/Http')
-rw-r--r--src/main.lib/Plugins/ValidationPlugins/Http/FileSystem/FileSystem.cs18
-rw-r--r--src/main.lib/Plugins/ValidationPlugins/Http/FileSystem/FileSystemOptionsFactory.cs2
-rw-r--r--src/main.lib/Plugins/ValidationPlugins/Http/Ftp/Ftp.cs8
-rw-r--r--src/main.lib/Plugins/ValidationPlugins/Http/HttpValidation.cs206
-rw-r--r--src/main.lib/Plugins/ValidationPlugins/Http/HttpValidationOptionsFactory.cs4
-rw-r--r--src/main.lib/Plugins/ValidationPlugins/Http/HttpValidationParameters.cs8
-rw-r--r--src/main.lib/Plugins/ValidationPlugins/Http/SelfHosting/SelfHosting.cs84
-rw-r--r--src/main.lib/Plugins/ValidationPlugins/Http/SelfHosting/SelfHostingOptionsFactory.cs4
-rw-r--r--src/main.lib/Plugins/ValidationPlugins/Http/Sftp/Sftp.cs9
-rw-r--r--src/main.lib/Plugins/ValidationPlugins/Http/WebDav/WebDav.cs12
10 files changed, 194 insertions, 161 deletions
diff --git a/src/main.lib/Plugins/ValidationPlugins/Http/FileSystem/FileSystem.cs b/src/main.lib/Plugins/ValidationPlugins/Http/FileSystem/FileSystem.cs
index f8d5b0b..8dfccb4 100644
--- a/src/main.lib/Plugins/ValidationPlugins/Http/FileSystem/FileSystem.cs
+++ b/src/main.lib/Plugins/ValidationPlugins/Http/FileSystem/FileSystem.cs
@@ -1,7 +1,9 @@
using PKISharp.WACS.Clients.IIS;
+using PKISharp.WACS.DomainObjects;
using System;
using System.IO;
using System.Linq;
+using System.Threading.Tasks;
namespace PKISharp.WACS.Plugins.ValidationPlugins.Http
{
@@ -11,7 +13,7 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Http
public FileSystem(FileSystemOptions options, IIISClient iisClient, RunLevel runLevel, HttpValidationParameters pars) : base(options, runLevel, pars) => _iisClient = iisClient;
- protected override void DeleteFile(string path)
+ protected override Task DeleteFile(string path)
{
var fi = new FileInfo(path);
if (fi.Exists)
@@ -23,9 +25,10 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Http
{
_log.Warning("File {path} already deleted", path);
}
+ return Task.CompletedTask;
}
- protected override void DeleteFolder(string path)
+ protected override Task DeleteFolder(string path)
{
var di = new DirectoryInfo(path);
if (di.Exists)
@@ -37,11 +40,12 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Http
{
_log.Warning("Folder {path} already deleted", path);
}
+ return Task.CompletedTask;
}
- protected override bool IsEmpty(string path) => !new DirectoryInfo(path).EnumerateFileSystemInfos().Any();
+ protected override Task<bool> IsEmpty(string path) => Task.FromResult(!new DirectoryInfo(path).EnumerateFileSystemInfos().Any());
- protected override void WriteFile(string path, string content)
+ protected override async Task WriteFile(string path, string content)
{
var fi = new FileInfo(path);
if (!fi.Directory.Exists)
@@ -49,19 +53,19 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Http
fi.Directory.Create();
}
_log.Verbose("Writing file to {path}", path);
- File.WriteAllText(path, content);
+ await File.WriteAllTextAsync(path, content);
}
/// <summary>
/// Update webroot
/// </summary>
/// <param name="scheduled"></param>
- protected override void Refresh()
+ protected override void Refresh(TargetPart targetPart)
{
if (string.IsNullOrEmpty(_options.Path))
{
// Update web root path
- var siteId = _options.SiteId ?? _targetPart.SiteId;
+ var siteId = _options.SiteId ?? targetPart.SiteId;
if (siteId > 0)
{
_path = _iisClient.GetWebSite(siteId.Value).Path;
diff --git a/src/main.lib/Plugins/ValidationPlugins/Http/FileSystem/FileSystemOptionsFactory.cs b/src/main.lib/Plugins/ValidationPlugins/Http/FileSystem/FileSystemOptionsFactory.cs
index 19a8de3..9a4e748 100644
--- a/src/main.lib/Plugins/ValidationPlugins/Http/FileSystem/FileSystemOptionsFactory.cs
+++ b/src/main.lib/Plugins/ValidationPlugins/Http/FileSystem/FileSystemOptionsFactory.cs
@@ -32,7 +32,7 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Http
if (target.IIS && _iisClient.HasWebSites)
{
- if (args.ValidationSiteId != null)
+ if (args?.ValidationSiteId != null)
{
// Throws exception when not found
var site = _iisClient.GetWebSite(args.ValidationSiteId.Value);
diff --git a/src/main.lib/Plugins/ValidationPlugins/Http/Ftp/Ftp.cs b/src/main.lib/Plugins/ValidationPlugins/Http/Ftp/Ftp.cs
index 6dbde44..c9aa07e 100644
--- a/src/main.lib/Plugins/ValidationPlugins/Http/Ftp/Ftp.cs
+++ b/src/main.lib/Plugins/ValidationPlugins/Http/Ftp/Ftp.cs
@@ -12,12 +12,12 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Http
protected override char PathSeparator => '/';
- protected override void DeleteFile(string path) => _ftpClient.Delete(path, FtpClient.FileType.File);
+ protected override async Task DeleteFile(string path) => _ftpClient.Delete(path, FtpClient.FileType.File);
- protected override void DeleteFolder(string path) => _ftpClient.Delete(path, FtpClient.FileType.Directory);
+ protected override async Task DeleteFolder(string path) => _ftpClient.Delete(path, FtpClient.FileType.Directory);
- protected override bool IsEmpty(string path) => !_ftpClient.GetFiles(path).Any();
+ protected override async Task<bool> IsEmpty(string path) => !_ftpClient.GetFiles(path).Any();
- protected override void WriteFile(string path, string content) => _ftpClient.Upload(path, content);
+ protected override async Task WriteFile(string path, string content) => _ftpClient.Upload(path, content);
}
}
diff --git a/src/main.lib/Plugins/ValidationPlugins/Http/HttpValidation.cs b/src/main.lib/Plugins/ValidationPlugins/Http/HttpValidation.cs
index bc811fe..ee6a996 100644
--- a/src/main.lib/Plugins/ValidationPlugins/Http/HttpValidation.cs
+++ b/src/main.lib/Plugins/ValidationPlugins/Http/HttpValidation.cs
@@ -1,8 +1,10 @@
using ACMESharp.Authorizations;
+using PKISharp.WACS.Context;
using PKISharp.WACS.DomainObjects;
using PKISharp.WACS.Plugins.Interfaces;
using PKISharp.WACS.Services;
using System;
+using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
@@ -19,9 +21,7 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins
where TOptions : HttpValidationOptions<TPlugin>
where TPlugin : IValidationPlugin
{
-
- private bool _webConfigWritten = false;
- private bool _challengeWritten = false;
+ private readonly List<string> _filesWritten = new List<string>();
protected TOptions _options;
protected ILogService _log;
@@ -31,6 +31,11 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins
protected RunLevel _runLevel;
/// <summary>
+ /// Multiple http-01 validation challenges can be answered at the same time
+ /// </summary>
+ public override ParallelOperations Parallelism => ParallelOperations.Answer;
+
+ /// <summary>
/// Path used for the current renewal, may not be same as _options.Path
/// because of the "Split" function employed by IISSites target
/// </summary>
@@ -42,13 +47,6 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins
private readonly ProxyService _proxy;
/// <summary>
- /// Current TargetPart that we are working on. A TargetPart is mainly used by
- /// the IISSites TargetPlugin to indicate that we are working with different
- /// IIS sites
- /// </summary>
- protected TargetPart _targetPart;
-
- /// <summary>
/// Where to find the template for the web.config that's copied to the webroot
/// </summary>
protected string TemplateWebConfig => Path.Combine(Path.GetDirectoryName(_settings.ExePath), "web_config.xml");
@@ -79,25 +77,29 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins
_proxy = pars.ProxyService;
_settings = pars.Settings;
_renewal = pars.Renewal;
- _targetPart = pars.TargetPart;
}
/// <summary>
/// Handle http challenge
/// </summary>
- public async override Task PrepareChallenge()
+ public async override Task PrepareChallenge(ValidationContext context, Http01ChallengeValidationDetails challenge)
{
- Refresh();
- WriteAuthorizationFile();
- WriteWebConfig();
- _log.Information("Answer should now be browsable at {answerUri}", Challenge.HttpResourceUrl);
+ // Should always have a value, confirmed by RenewalExecutor
+ // check only to satifiy the compiler
+ if (context.TargetPart != null)
+ {
+ Refresh(context.TargetPart);
+ }
+ WriteAuthorizationFile(challenge);
+ WriteWebConfig(challenge);
+ _log.Information("Answer should now be browsable at {answerUri}", challenge.HttpResourceUrl);
if (_runLevel.HasFlag(RunLevel.Test) && _renewal.New)
{
if (await _input.PromptYesNo("[--test] Try in default browser?", false))
{
Process.Start(new ProcessStartInfo
{
- FileName = Challenge.HttpResourceUrl,
+ FileName = challenge.HttpResourceUrl,
UseShellExecute = true
});
await _input.Wait();
@@ -107,8 +109,8 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins
string? foundValue = null;
try
{
- var value = await WarmupSite();
- if (Equals(value, Challenge.HttpResourceValue))
+ var value = await WarmupSite(challenge);
+ if (Equals(value, challenge.HttpResourceValue))
{
_log.Information("Preliminary validation looks good, but the ACME server will be more thorough");
}
@@ -116,7 +118,7 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins
{
_log.Warning("Preliminary validation failed, the server answered '{value}' instead of '{expected}'. The ACME server might have a different perspective",
foundValue ?? "(null)",
- Challenge.HttpResourceValue);
+ challenge.HttpResourceValue);
}
}
catch (HttpRequestException hrex)
@@ -130,15 +132,22 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins
}
/// <summary>
+ /// Default commit function, doesn't do anything because
+ /// default doesn't do parallel operation
+ /// </summary>
+ /// <returns></returns>
+ public override Task Commit() => Task.CompletedTask;
+
+ /// <summary>
/// Warm up the target site, giving the application a little
/// time to start up before the validation request comes in.
/// Mostly relevant to classic FileSystem validation
/// </summary>
/// <param name="uri"></param>
- private async Task<string> WarmupSite()
+ private async Task<string> WarmupSite(Http01ChallengeValidationDetails challenge)
{
using var client = _proxy.GetHttpClient(false);
- var response = await client.GetAsync(Challenge.HttpResourceUrl);
+ var response = await client.GetAsync(challenge.HttpResourceUrl);
return await response.Content.ReadAsStringAsync();
}
@@ -147,14 +156,18 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins
/// </summary>
/// <param name="answerPath">where the answerFile should be located</param>
/// <param name="fileContents">the contents of the file to write</param>
- private void WriteAuthorizationFile()
+ private void WriteAuthorizationFile(Http01ChallengeValidationDetails challenge)
{
if (_path == null)
{
throw new InvalidOperationException();
}
- WriteFile(CombinePath(_path, Challenge.HttpResourcePath), Challenge.HttpResourceValue);
- _challengeWritten = true;
+ var path = CombinePath(_path, challenge.HttpResourcePath);
+ WriteFile(path, challenge.HttpResourceValue);
+ if (!_filesWritten.Contains(path))
+ {
+ _filesWritten.Add(path);
+ }
}
/// <summary>
@@ -163,7 +176,7 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins
/// <param name="target"></param>
/// <param name="answerPath"></param>
/// <param name="token"></param>
- private void WriteWebConfig()
+ private void WriteWebConfig(Http01ChallengeValidationDetails challenge)
{
if (_path == null)
{
@@ -173,13 +186,20 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins
{
try
{
- _log.Debug("Writing web.config");
- var partialPath = Challenge.HttpResourcePath.Split('/').Last();
- var destination = CombinePath(_path, Challenge.HttpResourcePath.Replace(partialPath, "web.config"));
- var content = GetWebConfig();
- WriteFile(destination, content);
- _webConfigWritten = true;
- }
+ var partialPath = challenge.HttpResourcePath.Split('/').Last();
+ var destination = CombinePath(_path, challenge.HttpResourcePath.Replace(partialPath, "web.config"));
+ if (!_filesWritten.Contains(destination))
+ {
+ var content = GetWebConfig().Value;
+ if (content != null)
+ {
+ _log.Debug("Writing web.config");
+ WriteFile(destination, content);
+ _filesWritten.Add(destination);
+ }
+
+ }
+ }
catch (Exception ex)
{
_log.Warning("Unable to write web.config: {ex}", ex.Message); ;
@@ -191,66 +211,16 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins
/// Get the template for the web.config
/// </summary>
/// <returns></returns>
- private string GetWebConfig() => File.ReadAllText(TemplateWebConfig);
-
- /// <summary>
- /// Can be used to write out server specific configuration, to handle extensionless files etc.
- /// </summary>
- /// <param name="target"></param>
- /// <param name="answerPath"></param>
- /// <param name="token"></param>
- private void DeleteWebConfig()
- {
- if (_path == null)
- {
- throw new InvalidOperationException();
- }
- if (_webConfigWritten)
- {
- _log.Debug("Deleting web.config");
- var partialPath = Challenge.HttpResourcePath.Split('/').Last();
- var destination = CombinePath(_path, Challenge.HttpResourcePath.Replace(partialPath, "web.config"));
- DeleteFile(destination);
- }
- }
-
- /// <summary>
- /// Should delete any authorizations
- /// </summary>
- /// <param name="answerPath">where the answerFile should be located</param>
- /// <param name="token">the token</param>
- /// <param name="webRootPath">the website root path</param>
- /// <param name="filePath">the file path for the authorization file</param>
- private void DeleteAuthorization()
- {
+ private Lazy<string?> GetWebConfig() => new Lazy<string?>(() => {
try
{
- if (_path != null && _challengeWritten)
- {
- _log.Debug("Deleting answer");
- var path = CombinePath(_path, Challenge.HttpResourcePath);
- var partialPath = Challenge.HttpResourcePath.Split('/').Last();
- DeleteFile(path);
- if (_settings.Validation.CleanupFolders)
- {
- path = path.Replace($"{PathSeparator}{partialPath}", "");
- if (DeleteFolderIfEmpty(path))
- {
- var idx = path.LastIndexOf(PathSeparator);
- if (idx >= 0)
- {
- path = path.Substring(0, path.LastIndexOf(PathSeparator));
- DeleteFolderIfEmpty(path);
- }
- }
- }
- }
- }
- catch (Exception ex)
+ return File.ReadAllText(TemplateWebConfig);
+ }
+ catch
{
- _log.Warning("Error occured while deleting folder structure. Error: {@ex}", ex);
+ return null;
}
- }
+ });
/// <summary>
/// Combine root path with relative path
@@ -271,11 +241,11 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
- private bool DeleteFolderIfEmpty(string path)
+ private async Task<bool> DeleteFolderIfEmpty(string path)
{
- if (IsEmpty(path))
+ if (await IsEmpty(path))
{
- DeleteFolder(path);
+ await DeleteFolder(path);
return true;
}
else
@@ -291,44 +261,78 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins
/// <param name="root"></param>
/// <param name="path"></param>
/// <param name="content"></param>
- protected abstract void WriteFile(string path, string content);
+ protected abstract Task WriteFile(string path, string content);
/// <summary>
/// Delete file from specific location
/// </summary>
/// <param name="root"></param>
/// <param name="path"></param>
- protected abstract void DeleteFile(string path);
+ protected abstract Task DeleteFile(string path);
/// <summary>
/// Check if folder is empty
/// </summary>
/// <param name="root"></param>
/// <param name="path"></param>
- protected abstract bool IsEmpty(string path);
+ protected abstract Task<bool> IsEmpty(string path);
/// <summary>
/// Delete folder if not empty
/// </summary>
/// <param name="root"></param>
/// <param name="path"></param>
- protected abstract void DeleteFolder(string path);
+ protected abstract Task DeleteFolder(string path);
/// <summary>
/// Refresh
/// </summary>
/// <param name="scheduled"></param>
/// <returns></returns>
- protected virtual void Refresh() { }
+ protected virtual void Refresh(TargetPart targetPart) { }
/// <summary>
/// Dispose
/// </summary>
- public override Task CleanUp()
+ public override async Task CleanUp()
{
- DeleteWebConfig();
- DeleteAuthorization();
- return Task.CompletedTask;
+ try
+ {
+ if (_path != null)
+ {
+ var folders = new List<string>();
+ foreach (var file in _filesWritten)
+ {
+ _log.Debug("Deleting files");
+ await DeleteFile(file);
+ var folder = file.Substring(0, file.LastIndexOf(PathSeparator));
+ if (!folders.Contains(folder))
+ {
+ folders.Add(folder);
+ }
+ }
+ if (_settings.Validation.CleanupFolders)
+ {
+ _log.Debug("Deleting empty folders");
+ foreach (var folder in folders)
+ {
+ if (await DeleteFolderIfEmpty(folder))
+ {
+ var idx = folder.LastIndexOf(PathSeparator);
+ if (idx >= 0)
+ {
+ var parent = folder.Substring(0, folder.LastIndexOf(PathSeparator));
+ await DeleteFolderIfEmpty(parent);
+ }
+ }
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ _log.Warning("Error occured while deleting folder structure. Error: {@ex}", ex);
+ }
}
}
}
diff --git a/src/main.lib/Plugins/ValidationPlugins/Http/HttpValidationOptionsFactory.cs b/src/main.lib/Plugins/ValidationPlugins/Http/HttpValidationOptionsFactory.cs
index f98a2e8..99583f4 100644
--- a/src/main.lib/Plugins/ValidationPlugins/Http/HttpValidationOptionsFactory.cs
+++ b/src/main.lib/Plugins/ValidationPlugins/Http/HttpValidationOptionsFactory.cs
@@ -61,7 +61,7 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins
var args = _arguments.GetArguments<HttpValidationArguments>();
if (string.IsNullOrEmpty(path) && !allowEmpty)
{
- path = _arguments.TryGetRequiredArgument(nameof(args.WebRoot), args.WebRoot);
+ path = _arguments.TryGetRequiredArgument(nameof(args.WebRoot), args?.WebRoot);
}
if (!string.IsNullOrEmpty(path) && !PathIsValid(path))
{
@@ -70,7 +70,7 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins
return new TOptions
{
Path = path,
- CopyWebConfig = target.IIS || args.ManualTargetIsIIS
+ CopyWebConfig = target.IIS || (args?.ManualTargetIsIIS ?? false)
};
}
diff --git a/src/main.lib/Plugins/ValidationPlugins/Http/HttpValidationParameters.cs b/src/main.lib/Plugins/ValidationPlugins/Http/HttpValidationParameters.cs
index b1958b4..7092cdd 100644
--- a/src/main.lib/Plugins/ValidationPlugins/Http/HttpValidationParameters.cs
+++ b/src/main.lib/Plugins/ValidationPlugins/Http/HttpValidationParameters.cs
@@ -7,9 +7,7 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins
{
public ISettingsService Settings { get; private set; }
public Renewal Renewal { get; private set; }
- public TargetPart TargetPart { get; private set; }
public RunLevel RunLevel { get; private set; }
- public string Identifier { get; private set; }
public ILogService LogService { get; private set; }
public IInputService InputService { get; private set; }
public ProxyService ProxyService { get; private set; }
@@ -20,14 +18,10 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins
ISettingsService settings,
ProxyService proxy,
Renewal renewal,
- TargetPart target,
- RunLevel runLevel,
- string identifier)
+ RunLevel runLevel)
{
Renewal = renewal;
- TargetPart = target;
RunLevel = runLevel;
- Identifier = identifier;
Settings = settings;
ProxyService = proxy;
LogService = log;
diff --git a/src/main.lib/Plugins/ValidationPlugins/Http/SelfHosting/SelfHosting.cs b/src/main.lib/Plugins/ValidationPlugins/Http/SelfHosting/SelfHosting.cs
index 2efacfa..c81966f 100644
--- a/src/main.lib/Plugins/ValidationPlugins/Http/SelfHosting/SelfHosting.cs
+++ b/src/main.lib/Plugins/ValidationPlugins/Http/SelfHosting/SelfHosting.cs
@@ -1,7 +1,9 @@
using ACMESharp.Authorizations;
+using PKISharp.WACS.Context;
+using PKISharp.WACS.Plugins.Interfaces;
using PKISharp.WACS.Services;
using System;
-using System.Collections.Generic;
+using System.Collections.Concurrent;
using System.IO;
using System.Net;
using System.Threading.Tasks;
@@ -13,12 +15,18 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Http
internal const int DefaultHttpValidationPort = 80;
internal const int DefaultHttpsValidationPort = 443;
+ private readonly object _listenerLock = new object();
private HttpListener? _listener;
- private readonly Dictionary<string, string> _files;
+ private readonly ConcurrentDictionary<string, string> _files;
private readonly SelfHostingOptions _options;
private readonly ILogService _log;
private readonly IUserRoleService _userRoleService;
+ /// <summary>
+ /// We can answer requests for multiple domains
+ /// </summary>
+ public override ParallelOperations Parallelism => ParallelOperations.Answer | ParallelOperations.Prepare;
+
private bool HasListener => _listener != null;
private HttpListener Listener
{
@@ -37,11 +45,11 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Http
{
_log = log;
_options = options;
- _files = new Dictionary<string, string>();
+ _files = new ConcurrentDictionary<string, string>();
_userRoleService = userRoleService;
}
- public async Task ReceiveRequests()
+ private async Task ReceiveRequests()
{
while (Listener.IsListening)
{
@@ -61,41 +69,61 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Http
}
}
- public override Task CleanUp()
+ public override Task PrepareChallenge(ValidationContext context, Http01ChallengeValidationDetails challenge)
+ {
+ // Add validation file
+ _files.GetOrAdd("/" + challenge.HttpResourcePath, challenge.HttpResourceValue);
+ return Task.CompletedTask;
+ }
+
+ public override Task Commit()
{
- if (HasListener)
+ // Create listener if it doesn't exist yet
+ lock (_listenerLock)
{
- try
- {
- Listener.Stop();
- Listener.Close();
- }
- catch
+ if (_listener == null)
{
+ var protocol = _options.Https == true ? "https" : "http";
+ var port = _options.Port ?? (_options.Https == true ?
+ DefaultHttpsValidationPort :
+ DefaultHttpValidationPort);
+ var prefix = $"{protocol}://+:{port}/.well-known/acme-challenge/";
+ try
+ {
+ Listener = new HttpListener();
+ Listener.Prefixes.Add(prefix);
+ Listener.Start();
+ Task.Run(ReceiveRequests);
+ }
+ catch
+ {
+ _log.Error("Unable to activate listener, this may be because of insufficient rights or a non-Microsoft webserver using port {port}", port);
+ throw;
+ }
}
}
return Task.CompletedTask;
}
- public override Task PrepareChallenge()
+ public override Task CleanUp()
{
- _files.Add("/" + Challenge.HttpResourcePath, Challenge.HttpResourceValue);
- try
- {
- var postfix = "/.well-known/acme-challenge/";
- var prefix = _options.Https == true ?
- $"https://+:{_options.Port ?? DefaultHttpsValidationPort}{postfix}" :
- $"http://+:{_options.Port ?? DefaultHttpValidationPort}{postfix}";
- Listener = new HttpListener();
- Listener.Prefixes.Add(prefix);
- Listener.Start();
- Task.Run(ReceiveRequests);
- }
- catch
+ // Cleanup listener if nobody else has done it yet
+ lock (_listenerLock)
{
- _log.Error("Unable to activate HttpListener, this may be because of insufficient rights or a non-Microsoft webserver using port 80");
- throw;
+ if (HasListener)
+ {
+ try
+ {
+ Listener.Stop();
+ Listener.Close();
+ }
+ finally
+ {
+ _listener = null;
+ }
+ }
}
+
return Task.CompletedTask;
}
diff --git a/src/main.lib/Plugins/ValidationPlugins/Http/SelfHosting/SelfHostingOptionsFactory.cs b/src/main.lib/Plugins/ValidationPlugins/Http/SelfHosting/SelfHostingOptionsFactory.cs
index 04bb38c..4db84e0 100644
--- a/src/main.lib/Plugins/ValidationPlugins/Http/SelfHosting/SelfHostingOptionsFactory.cs
+++ b/src/main.lib/Plugins/ValidationPlugins/Http/SelfHosting/SelfHostingOptionsFactory.cs
@@ -26,8 +26,8 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Http
var args = _arguments.GetArguments<SelfHostingArguments>();
return new SelfHostingOptions()
{
- Port = args.ValidationPort,
- Https = string.Equals(args.ValidationProtocol, "https", StringComparison.OrdinalIgnoreCase) ? true : (bool?)null
+ Port = args?.ValidationPort,
+ Https = string.Equals(args?.ValidationProtocol, "https", StringComparison.OrdinalIgnoreCase) ? true : (bool?)null
};
}
}
diff --git a/src/main.lib/Plugins/ValidationPlugins/Http/Sftp/Sftp.cs b/src/main.lib/Plugins/ValidationPlugins/Http/Sftp/Sftp.cs
index c3d5c08..a7a88ee 100644
--- a/src/main.lib/Plugins/ValidationPlugins/Http/Sftp/Sftp.cs
+++ b/src/main.lib/Plugins/ValidationPlugins/Http/Sftp/Sftp.cs
@@ -1,5 +1,6 @@
using PKISharp.WACS.Clients;
using System.Linq;
+using System.Threading.Tasks;
namespace PKISharp.WACS.Plugins.ValidationPlugins.Http
{
@@ -11,12 +12,12 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Http
protected override char PathSeparator => '/';
- protected override void DeleteFile(string path) => _sshFtpClient.Delete(path, SshFtpClient.FileType.File);
+ protected override async Task DeleteFile(string path) => _sshFtpClient.Delete(path, SshFtpClient.FileType.File);
- protected override void DeleteFolder(string path) => _sshFtpClient.Delete(path, SshFtpClient.FileType.Directory);
+ protected override async Task DeleteFolder(string path) => _sshFtpClient.Delete(path, SshFtpClient.FileType.Directory);
- protected override bool IsEmpty(string path) => !_sshFtpClient.GetFiles(path).Any();
+ protected override async Task<bool> IsEmpty(string path) => !_sshFtpClient.GetFiles(path).Any();
- protected override void WriteFile(string path, string content) => _sshFtpClient.Upload(path, content);
+ protected override async Task WriteFile(string path, string content) => _sshFtpClient.Upload(path, content);
}
}
diff --git a/src/main.lib/Plugins/ValidationPlugins/Http/WebDav/WebDav.cs b/src/main.lib/Plugins/ValidationPlugins/Http/WebDav/WebDav.cs
index 990f338..f1adaea 100644
--- a/src/main.lib/Plugins/ValidationPlugins/Http/WebDav/WebDav.cs
+++ b/src/main.lib/Plugins/ValidationPlugins/Http/WebDav/WebDav.cs
@@ -1,4 +1,6 @@
-using PKISharp.WACS.Client;
+using ACMESharp.Authorizations;
+using PKISharp.WACS.Client;
+using PKISharp.WACS.Context;
using PKISharp.WACS.Services;
using System.Threading.Tasks;
@@ -13,15 +15,15 @@ namespace PKISharp.WACS.Plugins.ValidationPlugins.Http
RunLevel runLevel, ProxyService proxy) :
base(options, runLevel, pars) => _webdavClient = new WebDavClientWrapper(_options.Credential, pars.LogService, proxy);
- protected override void DeleteFile(string path) => _webdavClient.Delete(path);
+ protected override async Task DeleteFile(string path) => _webdavClient.Delete(path);
- protected override void DeleteFolder(string path) => _webdavClient.Delete(path);
+ protected override async Task DeleteFolder(string path) => _webdavClient.Delete(path);
- protected override bool IsEmpty(string path) => !_webdavClient.IsEmpty(path);
+ protected override async Task<bool> IsEmpty(string path) => !_webdavClient.IsEmpty(path);
protected override char PathSeparator => '/';
- protected override void WriteFile(string path, string content) => _webdavClient.Upload(path, content);
+ protected override async Task WriteFile(string path, string content) => _webdavClient.Upload(path, content);
public override Task CleanUp()
{
base.CleanUp();