diff --git a/ACMESharp/ACMESharp.Providers.DuckDNS/ACMESharp.Providers.DuckDNS.csproj b/ACMESharp/ACMESharp.Providers.DuckDNS/ACMESharp.Providers.DuckDNS.csproj new file mode 100644 index 00000000..aee14375 --- /dev/null +++ b/ACMESharp/ACMESharp.Providers.DuckDNS/ACMESharp.Providers.DuckDNS.csproj @@ -0,0 +1,67 @@ + + + + + Debug + AnyCPU + {9B6C05E7-A570-406D-8FFD-BF8AE5337AA1} + Library + Properties + ACMESharp.Providers.DuckDNS + ACMESharp.Providers.DuckDNS + v4.6.1 + 512 + + + true + full + false + bin\$(Configuration)\ACMESharp.Providers.DuckDNS\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\$(Configuration)\ACMESharp.Providers.DuckDNS\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + Properties\SharedAssemblyVersionInfo.cs + + + Properties\SharedGlobalSuppressions.cs + + + + + + + + {d551234b-0a8d-4dee-8178-a81998df0edb} + ACMESharp + + + + + PreserveNewest + + + + + \ No newline at end of file diff --git a/ACMESharp/ACMESharp.Providers.DuckDNS/ACMESharp.Providers.DuckDNS.nuspec b/ACMESharp/ACMESharp.Providers.DuckDNS/ACMESharp.Providers.DuckDNS.nuspec new file mode 100644 index 00000000..53c4cb47 --- /dev/null +++ b/ACMESharp/ACMESharp.Providers.DuckDNS/ACMESharp.Providers.DuckDNS.nuspec @@ -0,0 +1,23 @@ + + + + + $id$ + $version$.$buildNum$$versionLabel$ + $title$ + https://github.com/ebekker + https://github.com/ebekker + https://raw.githubusercontent.com/ebekker/ACMESharp/master/LICENSE + https://github.com/ebekker/ACMESharp + https://cdn.rawgit.com/ebekker/ACMESharp/49bf6524da8239ecf258ab3857dfbbf40366ecfd/artwork/ACMESharp-logo-square64.png + false + $description$ + Early-access release of ACMESharp Provider Lib for Duck DNS. + Copyright © 2019 Philipp Nanz + pki ssl tls security certificates letsencrypt acme acmesharp duckdns + + + + + + diff --git a/ACMESharp/ACMESharp.Providers.DuckDNS/ACMESharp.Providers.DuckDNS.psd1 b/ACMESharp/ACMESharp.Providers.DuckDNS/ACMESharp.Providers.DuckDNS.psd1 new file mode 100644 index 00000000..d2d34e23 --- /dev/null +++ b/ACMESharp/ACMESharp.Providers.DuckDNS/ACMESharp.Providers.DuckDNS.psd1 @@ -0,0 +1,112 @@ + +## For a reference of this file's elements, see: +## https://technet.microsoft.com/library/hh849709.aspx +## https://technet.microsoft.com/en-us/library/dd878297(v=vs.85).aspx + +## 64-bit: +## %SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe +## 32-bit: +## %SystemRoot%\syswow64\WindowsPowerShell\v1.0\powershell.exe + +@{ + ## This is a manifest-only module so we don't define any root + #RootModule = '' + + ModuleVersion = '0.9.2' + GUID = '9ea5edb1-319e-4f9d-a538-aec3567a410d' + + Author = 'https://github.com/ebekker' + + CompanyName = 'https://github.com/ebekker/ACMESharp' + + Copyright = '(c) 2019 Philipp Nanz. All rights reserved.' + + Description = "Duck DNS Provider extension library for ACMESharp Client." + + # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. + DefaultCommandPrefix = 'ACME' + + ## Minimum version of the Windows PowerShell engine required by this module + ## This does not appear to be enforce for versions > 2.0 as per + ## https://technet.microsoft.com/en-us/library/dd878297(v=vs.85).aspx + PowerShellVersion = '3.0' + + DotNetFrameworkVersion = '4.5' + + # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. + PrivateData = @{ + + PSData = @{ + + # Tags applied to this module. These help with module discovery in online galleries. + Tags = @('pki','ssl','tls','security','certificates','letsencrypt','acme','powershell','acmesharp','duckdns','acmesharp_ext') + + # A URL to the license for this module. + LicenseUri = 'https://raw.githubusercontent.com/ebekker/ACMESharp/master/LICENSE' + + # A URL to the main website for this project. + ProjectUri = 'https://github.com/ebekker/ACMESharp' + + # A URL to an icon representing this module. + IconUri = 'https://cdn.rawgit.com/ebekker/ACMESharp/master/artwork/ACMESharp-logo-square64.png' + + # ReleaseNotes of this module + ReleaseNotes = 'Please see the release notes from the release distribution page: https://github.com/ebekker/ACMESharp/releases' + + } # End of PSData hashtable + + } # End of PrivateData hashtable + + # Modules that must be imported into the global environment prior to importing this module + RequiredModules = @( ## FYI -- If one module uses the Hashtable spec, they all have to + + ## The minimum version of ACMESharp that supports our form of a Provider + ## extension as a dynamically installed and *enabled* POSH Extension Module + , @{ModuleName="ACMESharp";ModuleVersion="0.9.0"} + ) + + + ############################################################ + ## Unused manifest elements reserved for possible future use + ############################################################ + + # HelpInfo URI of this module for updateable help + # HelpInfoURI = '' + + # Assemblies that must be loaded prior to importing this module + # RequiredAssemblies = @() + + # Script files (.ps1) that are run in the caller's environment prior to importing this module. + # ScriptsToProcess = @() + + # Type files (.ps1xml) to be loaded when importing this module + # TypesToProcess = @() + + # Format files (.ps1xml) to be loaded when importing this module + # FormatsToProcess = @() + + # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess + # NestedModules = @() + + # Functions to export from this module + # FunctionsToExport = '*' + + # Cmdlets to export from this module + # CmdletsToExport = '*' + + # Variables to export from this module + # VariablesToExport = '*' + + # Aliases to export from this module + # AliasesToExport = '*' + + # DSC resources to export from this module + # DscResourcesToExport = @() + + # List of all modules packaged with this module + # ModuleList = @() + + # List of all files packaged with this module + # FileList = @() + +} diff --git a/ACMESharp/ACMESharp.Providers.DuckDNS/DuckDnsChallengeHandler.cs b/ACMESharp/ACMESharp.Providers.DuckDNS/DuckDnsChallengeHandler.cs new file mode 100644 index 00000000..2d1de935 --- /dev/null +++ b/ACMESharp/ACMESharp.Providers.DuckDNS/DuckDnsChallengeHandler.cs @@ -0,0 +1,65 @@ +using ACMESharp.ACME; +using System; +using System.Net; + +namespace ACMESharp.Providers.DuckDNS +{ + public class DuckDnsChallengeHandler : IChallengeHandler + { + public string Token { get; set; } + + public bool IsDisposed + { + get; private set; + } + + public void CleanUp(ChallengeHandlingContext ctx) + { + var dnsChallenge = (DnsChallenge)ctx.Challenge; + var domain = GetDomainId(dnsChallenge); + + var wr = CreateRequest(Token, domain, ""); + using (var response = wr.GetResponse()) + { } + } + + private void AssertNotDisposed() + { + if (IsDisposed) + throw new InvalidOperationException("handler is disposed"); + } + + public void Dispose() + { + IsDisposed = true; + } + + public void Handle(ChallengeHandlingContext ctx) + { + AssertNotDisposed(); + var dnsChallenge = (DnsChallenge)ctx.Challenge; + var domain = GetDomainId(dnsChallenge); + + var wr = CreateRequest(Token, domain, dnsChallenge.RecordValue); + using (var response = wr.GetResponse()) + { } + } + + string GetDomainId(DnsChallenge dnsChallenge) + { + var segments = dnsChallenge.RecordName.Split('.'); + return segments[1]; + } + + WebRequest CreateRequest(string token, string domain, string text) + { + var url = "https://www.duckdns.org/update?token=" + token + "&domains=" + domain + "&txt=" + text; + if (String.IsNullOrEmpty(text)) + { + url += "&clear=true"; + } + Console.WriteLine("Executing web request: " + url); + return WebRequest.Create(url); + } + } +} diff --git a/ACMESharp/ACMESharp.Providers.DuckDNS/DuckDnsChallengeHandlerProvider.cs b/ACMESharp/ACMESharp.Providers.DuckDNS/DuckDnsChallengeHandlerProvider.cs new file mode 100644 index 00000000..8330faeb --- /dev/null +++ b/ACMESharp/ACMESharp.Providers.DuckDNS/DuckDnsChallengeHandlerProvider.cs @@ -0,0 +1,55 @@ +using ACMESharp.ACME; +using ACMESharp.Ext; +using System.Collections.Generic; + +namespace ACMESharp.Providers.DuckDNS +{ + /// + /// Provider for a Challenge Handler that updates the TXT records on a + /// Duck DNS account. + /// + [ChallengeHandlerProvider("duckdns", + ChallengeTypeKind.DNS, + Label = "Duck DNS Provider", + Description = "A Duck DNS provider for handling Challenges." + + " This provider supports the DNS" + + " Challenge type and computes all the necessary" + + " response values.")] + public class DuckDnsChallengeHandlerProvider : IChallengeHandlerProvider + { + public static readonly ParameterDetail TOKEN = new ParameterDetail( + nameof(DuckDnsChallengeHandler.Token), + ParameterType.TEXT, isRequired: true, label: "Token", + desc: "The Token for your Duck DNS account"); + + private static readonly ParameterDetail[] PARAMS = + { + TOKEN + }; + + public IEnumerable DescribeParameters() + { + return PARAMS; + } + + public bool IsSupported(Challenge c) + { + return c is DnsChallenge; + } + + public IChallengeHandler GetHandler(Challenge c, IReadOnlyDictionary initParams) + { + if (initParams == null) + initParams = new Dictionary(); + + if (!initParams.ContainsKey(TOKEN.Name)) + throw new KeyNotFoundException($"missing required parameter [{TOKEN.Name}]"); + + var h = new DuckDnsChallengeHandler(); + + h.Token = (string)initParams[TOKEN.Name]; + + return h; + } + } +} diff --git a/ACMESharp/ACMESharp.Providers.DuckDNS/Properties/AssemblyInfo.cs b/ACMESharp/ACMESharp.Providers.DuckDNS/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..51dd355e --- /dev/null +++ b/ACMESharp/ACMESharp.Providers.DuckDNS/Properties/AssemblyInfo.cs @@ -0,0 +1,22 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ACMESharp Duck DNS Provider")] +[assembly: AssemblyDescription("Duck DNS Provider extension for ACMESharp")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("github.com/ebekker/ACMESharp")] +[assembly: AssemblyProduct("ACMESharp.Providers.DuckDNS")] +[assembly: AssemblyCopyright("Copyright © 2019 Philipp Nanz. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("bc6d303a-71fb-4cc7-8d30-3c3b09f9c92a")] diff --git a/ACMESharp/ACMESharp.Providers.DuckDNS/packages.config b/ACMESharp/ACMESharp.Providers.DuckDNS/packages.config new file mode 100644 index 00000000..6b8deb9c --- /dev/null +++ b/ACMESharp/ACMESharp.Providers.DuckDNS/packages.config @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/ACMESharp/ACMESharp.sln b/ACMESharp/ACMESharp.sln index 1e6c551d..d6251cb4 100644 --- a/ACMESharp/ACMESharp.sln +++ b/ACMESharp/ACMESharp.sln @@ -78,6 +78,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ACMESharp.PKI.Providers.Ope EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ACMESharp.Providers.DNSMadeEasy", "ACMESharp.Providers.DNSMadeEasy\ACMESharp.Providers.DNSMadeEasy.csproj", "{BC6D303A-71FB-4CC7-8D30-3C3B09F9C92A}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ACMESharp.Providers.DuckDNS", "ACMESharp.Providers.DuckDNS\ACMESharp.Providers.DuckDNS.csproj", "{9B6C05E7-A570-406D-8FFD-BF8AE5337AA1}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -156,6 +158,10 @@ Global {BC6D303A-71FB-4CC7-8D30-3C3B09F9C92A}.Debug|Any CPU.Build.0 = Debug|Any CPU {BC6D303A-71FB-4CC7-8D30-3C3B09F9C92A}.Release|Any CPU.ActiveCfg = Release|Any CPU {BC6D303A-71FB-4CC7-8D30-3C3B09F9C92A}.Release|Any CPU.Build.0 = Release|Any CPU + {9B6C05E7-A570-406D-8FFD-BF8AE5337AA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9B6C05E7-A570-406D-8FFD-BF8AE5337AA1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9B6C05E7-A570-406D-8FFD-BF8AE5337AA1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9B6C05E7-A570-406D-8FFD-BF8AE5337AA1}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE