Skip to content

Commit

Permalink
Merge pull request #16 from WouterTinus/tlsalpn
Browse files Browse the repository at this point in the history
Add ability to decode TLS-ALPN-01 challenges
  • Loading branch information
ebekker authored Feb 17, 2019
2 parents 13c9d06 + fa67abb commit ba46184
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 97 deletions.
27 changes: 1 addition & 26 deletions src/ACMESharp.MockServer/Controllers/AcmeController.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
Expand Down Expand Up @@ -392,30 +392,6 @@ public ActionResult<string> GetCertificate(string certKey)
return dbCert.Pem;
}

// "revoke-cert": "https://tools.ietf.org/html/draft-ietf-acme-acme-18#section-7.6"
[HttpPost("revoke-cert")]
public ActionResult<bool> Revoke(string acctId,
[FromBody]JwsSignedPayload signedPayload)
{
if (!int.TryParse(acctId, out var acctIdNum))
return NotFound();

var ph = ExtractProtectedHeader(signedPayload);

ValidateNonce(ph);

var acct = _repo.GetAccountByKid(ph.Kid);
if (acct == null)
throw new Exception("could not resolve account");

ValidateAccount(acct, signedPayload);

// TODO: do stuff?

GenerateNonce();
return true;
}

// "https://acme-staging-v02.api.letsencrypt.org/acme/authz/740KRMwcT0UrLXdUKOlgMnfNbzpSQtRaWjbyA1UgIJ4",
/*
// OK
Expand Down Expand Up @@ -549,7 +525,6 @@ public ActionResult<Challenge> AnswerChallenge(string authzKey, string challenge
return dbChlng.Payload;
}


T ExtractPayload<T>(JwsSignedPayload signedPayload)
{
var payloadBytes = CryptoHelper.Base64.UrlDecode(signedPayload.Payload);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ public ActionResult<object> GetDirectory()
values: null, protocol: Request.Scheme),
NewAuthz = null,
KeyChange = null,
RevokeCert = Url.Action(nameof(AcmeController.Revoke),
controller: AcmeController.ControllerRoute,
values: null, protocol: Request.Scheme),
RevokeCert = null,

Meta = new DirectoryMeta
{
Expand Down
21 changes: 19 additions & 2 deletions src/ACMESharp/Authorizations/AuthorizationDecoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@ public static IChallengeValidationDetails DecodeChallengeValidation(

switch (challengeType)
{
case "dns-01":
case Dns01ChallengeValidationDetails.Dns01ChallengeType:
return ResolveChallengeForDns01(authz, challenge, signer);
case "http-01":
case Http01ChallengeValidationDetails.Http01ChallengeType:
return ResolveChallengeForHttp01(authz, challenge, signer);
case TlsAlpn01ChallengeValidationDetails.TlsAlpn01ChallengeType:
return ResolveChallengeForTlsAlpn01(authz, challenge, signer);
}

throw new NotImplementedException(
Expand Down Expand Up @@ -78,5 +80,20 @@ public static Http01ChallengeValidationDetails ResolveChallengeForHttp01(
HttpResourceValue = keyAuthz,
};
}

/// <summary>
/// </summary>
/// <remarks>
/// https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-05
/// </remarks>
public static TlsAlpn01ChallengeValidationDetails ResolveChallengeForTlsAlpn01(
Authorization authz, Challenge challenge, IJwsTool signer)
{
var keyAuthz = JwsHelper.ComputeKeyAuthorization(signer, challenge.Token);
return new TlsAlpn01ChallengeValidationDetails
{
TokenValue = keyAuthz,
};
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace ACMESharp.Authorizations
{
/// <summary>
/// https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-05
/// </summary>
public class TlsAlpn01ChallengeValidationDetails : IChallengeValidationDetails
{
public const string TlsAlpn01ChallengeType = "tls-alpn-01";
public const string AlpnExtensionName = "acme-tls/1";
public const string AcmeIdentifierExtension = "acmeIdentifier";

public string ChallengeType => TlsAlpn01ChallengeType;

public string TokenValue { get; set; }
}
}
26 changes: 0 additions & 26 deletions src/ACMESharp/Protocol/AcmeProtocolClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -615,32 +615,6 @@ public async Task<byte[]> GetOrderCertificateAsync(
}
}

/// <summary>
/// Revoke certificate
/// </summary>
/// <remarks>
/// https://tools.ietf.org/html/draft-ietf-acme-acme-18#section-7.6
/// </remarks>
public async Task<bool> RevokeCertificateAsync(
byte[] derEncodedCertificate,
CancellationToken cancel = default(CancellationToken))
{
var message = new RevokeCertificateRequest
{
Certificate = CryptoHelper.Base64.UrlEncode(derEncodedCertificate),
};
var resp = await SendAcmeAsync(
new Uri(_http.BaseAddress, Directory.RevokeCert),
method: HttpMethod.Post,
message: message,
expectedStatuses: new[] { HttpStatusCode.OK },
cancel: cancel);

// If OK is returned, we're all done. Otherwise general
// exception handling will kick in
return true;
}

/// <summary>
/// Generic fetch routine to retrieve raw bytes from a URL associated
/// with an ACME endpoint.
Expand Down
22 changes: 0 additions & 22 deletions src/ACMESharp/Protocol/Messages/RevokeCertificateRequest.cs

This file was deleted.

18 changes: 0 additions & 18 deletions test/ACMESharp.MockServer.UnitTests/AcmeControllerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -388,24 +388,6 @@ public async Task FinalizeOrder()
}


[TestMethod]
public async Task RevokeCertificate()
{
using (var http = _server.CreateClient())
{
var dir = await GetDir();
var signer = new Crypto.JOSE.Impl.RSJwsTool();
signer.Init();
using (var acme = new AcmeProtocolClient(http, dir,
signer: signer))
{
await acme.GetNonceAsync();
// TODO go through the motions as the FinalizeOrder test?
await acme.RevokeCertificateAsync(new byte[] { });
}
}
}


private async Task<ServiceDirectory> GetDir()
{
Expand Down

0 comments on commit ba46184

Please sign in to comment.