Skip to content

Commit

Permalink
bug fixes
Browse files Browse the repository at this point in the history
manual registration now working again
  • Loading branch information
oocx committed Dec 4, 2015
1 parent 887a735 commit dbfee1d
Show file tree
Hide file tree
Showing 11 changed files with 80 additions and 21 deletions.
Binary file modified .vs/ACME.net/v14/.suo
Binary file not shown.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,26 @@ take a look at these projects:
[.net ACME protocol library](https://github.com/ebekker/letsencrypt-win/).
[A simple ACME Client for Windows](https://github.com/Lone-Coder/letsencrypt-win-simple)

# Using acme.exe

You can use acme.exe with or without IIS integration. With IIS integration, acme.exe autoamtically
configures your IIS to respond to the ACME domain validation challenge, and it updates your IIS
web site with the new SSL certificate. To use IIS integration, you must run acme.exe on your IIS web
server.

Examples:

Request a certificate for www.yourdomain.com and accept the terms of service of the ACME server (-a):
'''
acme.exe -a www.yourdomain.com
'''

If you don't want to use IIS integration or can't use it / you are not using IIS, you can also
run acme.exe without IIS support. In that case, you need to manually copy the challenge file
that is required to validate domain ownership to your server.

Request a certificate for www.yourdomain.com without IIS integration

# Projects in this repository

## Oocx.ACME
Expand Down
3 changes: 2 additions & 1 deletion src/Oocx.ACME.CLRConsole/Oocx.ACME.CLRConsole.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@
<HintPath>..\..\artifacts\bin\Oocx.ACME.Console\Debug\net46\Oocx.ACME.Console.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Oocx.ACME.IIS">
<Reference Include="Oocx.ACME.IIS, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\artifacts\bin\Oocx.ACME.IIS\Debug\net46\Oocx.ACME.IIS.dll</HintPath>
</Reference>
<Reference Include="Oocx.Asn1PKCS">
Expand Down
4 changes: 2 additions & 2 deletions src/Oocx.ACME.Console/ContainerConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public IContainer Configure(Options options)
builder.RegisterType<FileKeyStore>().As<IKeyStore>().WithParameter("basePath", options.AccountKeyContainerLocation ?? Environment.CurrentDirectory);
}

if ("manual".Equals(options.ChallengeProvider, StringComparison.OrdinalIgnoreCase))
if ("manual-http-01".Equals(options.ChallengeProvider, StringComparison.OrdinalIgnoreCase))
{
builder.RegisterType<ManualChallengeProvider>().As<IChallengeProvider>();
}
Expand All @@ -50,7 +50,7 @@ public IContainer Configure(Options options)
}
else
{
builder.RegisterType<ManualChallengeProvider>().As<IServerConfigurationProvider>();
builder.RegisterType<ManualServerConfigurationProvider>().As<IServerConfigurationProvider>();
}

builder.RegisterType<Pkcs12>().As<IPkcs12>();
Expand Down
6 changes: 3 additions & 3 deletions src/Oocx.ACME.Console/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class Options
[Option('t', "termsOfServiceUri", HelpText = "The uri of the terms of service that you accept.", Default = "https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf")]
public string TermsOfServiceUri { get; set; }

[Option('i', "ignoreSSLErrors", HelpText = "Ignore SSL certificate errors for the HTTPS connection to the ACME server (useful for debugging messages with fiddler)")]
[Option("ignoreSSLErrors", HelpText = "Ignore SSL certificate errors for the HTTPS connection to the ACME server (useful for debugging messages with fiddler)")]
public bool IgnoreSSLCertificateErrors { get; set; }

[Option('v', "verbosity", HelpText = "Configures the log level (Verbose, Info, Warning, Error, Disabled - casing is important).", Default = LogLevel.Info)]
Expand All @@ -35,10 +35,10 @@ public class Options
[Option('n', "accountKeyName", HelpText = "The name of the key file or key container used to store the acme registration key.", Default = "acme-key")]
public string AccountKeyName { get; set; }

[Option('c', "challengeProvider", HelpText = "The type of web server integration to use for ACME challenges. Supported types are: 'manual' (no integration), 'iis-http-01' (IIS with http-01 challenge)", Default = "iis-http-01")]
[Option('c', "challengeProvider", HelpText = "The type of web server integration to use for ACME challenges. Supported types are: 'manual-http-01' (no integration with http-01 challenge), 'iis-http-01' (IIS with http-01 challenge)", Default = "iis-http-01")]
public string ChallengeProvider { get; set; }

[Option('s', "serverConfigurationProvider", HelpText = "The type of web server configuration to use to install and configure certificates. Supported types are: 'manual' (no integration), 'iis' (installs certificates to localmachine\\my and configures IIS bindings)", Default = "iis")]
[Option('i', "serverConfigurationProvider", HelpText = "The type of web server configuration to use to install and configure certificates. Supported types are: 'manual' (no integration), 'iis' (installs certificates to localmachine\\my and configures IIS bindings)", Default = "iis")]
public string ServerConfigurationProvider { get; set; }

[Option('w', "iisWebSite", HelpText = "The IIS web site that should be configured to use the new certificate (used with --serverConfigurationProvider iis). If you do not specifiy a web site, the provider will try to find a matching site with a binding for your domain.")]
Expand Down
2 changes: 1 addition & 1 deletion src/Oocx.ACME.Console/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ private void Execute(Options options)
return;
}

var process = container.Resolve<IAcmeProcess>(new Parameter[] { new NamedParameter("options", options) });
var process = container.Resolve<IAcmeProcess>(new NamedParameter("options", options));
process.StartAsync().GetAwaiter().GetResult();
}
catch (AggregateException ex)
Expand Down
7 changes: 4 additions & 3 deletions src/Oocx.ACME.IIS/Oocx.ACME.IIS.xproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,18 @@
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>

<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>cc1c7776-20ec-41a1-ad04-e7e19319b1a9</ProjectGuid>
<RootNamespace>Oocx.ACME.IIS</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>

<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<ProduceOutputsOnBuild>True</ProduceOutputsOnBuild>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>
</Project>
32 changes: 26 additions & 6 deletions src/Oocx.ACME/Client/AcmeClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,12 @@ public async Task<RegistrationResponse> RegisterAsync(string termsOfServiceUri,
{
var location = ex.Response.Headers.Location.ToString();
Info($"using existing registration: {location}");
return await PostAsync<RegistrationResponse>(new Uri(location), new UpdateRegistrationRequest());
var response = await PostAsync<RegistrationResponse>(new Uri(location), new UpdateRegistrationRequest());
if (string.IsNullOrEmpty(response.Location))
{
response.Location = location;
}
return response;
}
}

Expand Down Expand Up @@ -151,8 +156,7 @@ public async Task<CertificateResponse> NewCertificateRequestAsync(byte[] csr)
var request = new CertificateRequest {Csr = csr.Base64UrlEncoded()};
var response = await PostAsync<CertificateResponse>(directory.NewCertificate, request);

Verbose($"location: {response.Location}");
Verbose($"link: {response.Link}");
Verbose($"location: {response.Location}");

return response;
}
Expand Down Expand Up @@ -219,14 +223,30 @@ private async Task<TResult> SendAsync<TResult>(HttpMethod method, Uri uri, objec
private static void GetHeaderValues<TResult>(HttpResponseMessage response, TResult responseContent)
{
var properties =
typeof (TResult).GetProperties(BindingFlags.Public | BindingFlags.SetProperty)
typeof (TResult).GetProperties(BindingFlags.Public | BindingFlags.SetProperty | BindingFlags.Instance)
.Where(p => p.PropertyType == typeof (string))
.ToDictionary(p => p.Name, p => p);
foreach (var header in response.Headers)
{
if (properties.ContainsKey(header.Key))
if (properties.ContainsKey(header.Key) && header.Value.Count() == 1)
{
properties[header.Key].SetValue(responseContent, header.Value.First());
}

if (header.Key == "Link")
{
properties[header.Key].SetValue(responseContent, header.Value);
foreach (var link in header.Value)
{
var parts = link.Split(';');
if (parts.Length != 2)
{
continue;
}
if (parts[1] == "rel=\"terms-of-service\"" && properties.ContainsKey("Agreement"))
{
properties["Agreement"].SetValue(responseContent, parts[0].Substring(1, parts[0].Length - 2));
}
}
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/Oocx.ACME/Client/ManualChallengeProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ public async Task<PendingChallenge> AcceptChallengeAsync(string domain, string s

return new PendingChallenge()
{
Instructions = $"Copy {challengeFile} to https://{domain ?? siteName}/.well-known/acme/{challenge.Token}",
Instructions = $"Copy {challengeFile} to https://{domain ?? siteName}/.well-known/acme-challenge/{challenge.Token}",
Complete = () => client.CompleteChallengeAsync(challenge)
};
}
}
}
}
19 changes: 19 additions & 0 deletions src/Oocx.ACME/Client/ManualServerConfigurationPRovider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;
using System.Security.Cryptography;
using Oocx.ACME.Common;
using Oocx.ACME.Services;

namespace Oocx.ACME.Client
{
public class ManualServerConfigurationProvider : IServerConfigurationProvider
{
public byte[] InstallCertificateWithPrivateKey(string certificatePath, string certificateStoreName, RSAParameters privateKey)
{
return null;
}

public void ConfigureServer(string domain, byte[] certificateHash, string certificateStoreName, string siteName, string binding)
{
}
}
}
4 changes: 1 addition & 3 deletions src/Oocx.ACME/Protocol/CertificateResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ namespace Oocx.ACME.Protocol
{
public class CertificateResponse
{
public string Location { get; set; }

public string Link { get; set; }
public string Location { get; set; }

public byte[] Certificate { get; set; }
}
Expand Down

0 comments on commit dbfee1d

Please sign in to comment.