From 7cead7d4382c49702a4fff47cf0933782f32ace2 Mon Sep 17 00:00:00 2001 From: WouterTinus Date: Sat, 9 Feb 2019 11:55:23 +0100 Subject: [PATCH 1/2] Add ability to decode TLS-ALPN-01 challenges --- .../Authorizations/AuthorizationDecoder.cs | 21 +++++++++++++++++-- .../TlsAlpn01ChallengeValidationDetails.cs | 16 ++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 src/ACMESharp/Authorizations/TlsAlpn01ChallengeValidationDetails.cs diff --git a/src/ACMESharp/Authorizations/AuthorizationDecoder.cs b/src/ACMESharp/Authorizations/AuthorizationDecoder.cs index b672558..603b91c 100644 --- a/src/ACMESharp/Authorizations/AuthorizationDecoder.cs +++ b/src/ACMESharp/Authorizations/AuthorizationDecoder.cs @@ -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( @@ -78,5 +80,20 @@ public static Http01ChallengeValidationDetails ResolveChallengeForHttp01( HttpResourceValue = keyAuthz, }; } + + /// + /// + /// + /// https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-05 + /// + public static TlsAlpn01ChallengeValidationDetails ResolveChallengeForTlsAlpn01( + Authorization authz, Challenge challenge, IJwsTool signer) + { + var keyAuthz = JwsHelper.ComputeKeyAuthorization(signer, challenge.Token); + return new TlsAlpn01ChallengeValidationDetails + { + TokenValue = keyAuthz, + }; + } } } \ No newline at end of file diff --git a/src/ACMESharp/Authorizations/TlsAlpn01ChallengeValidationDetails.cs b/src/ACMESharp/Authorizations/TlsAlpn01ChallengeValidationDetails.cs new file mode 100644 index 0000000..acad99e --- /dev/null +++ b/src/ACMESharp/Authorizations/TlsAlpn01ChallengeValidationDetails.cs @@ -0,0 +1,16 @@ +namespace ACMESharp.Authorizations +{ + /// + /// https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-05 + /// + 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; } + } +} \ No newline at end of file From fa67abb3180a376d10070dc95ecdcb24793503e8 Mon Sep 17 00:00:00 2001 From: WouterTinus Date: Sat, 9 Feb 2019 11:56:47 +0100 Subject: [PATCH 2/2] Revert "Revocation support" This reverts commit ed3097e901f6f49bfcde27b62ba0695262da00ac. --- .../Controllers/AcmeController.cs | 27 +------------------ .../Controllers/AcmeDirectoryController.cs | 4 +-- src/ACMESharp/Protocol/AcmeProtocolClient.cs | 26 ------------------ .../Messages/RevokeCertificateRequest.cs | 22 --------------- .../AcmeControllerTests.cs | 18 ------------- 5 files changed, 2 insertions(+), 95 deletions(-) delete mode 100644 src/ACMESharp/Protocol/Messages/RevokeCertificateRequest.cs diff --git a/src/ACMESharp.MockServer/Controllers/AcmeController.cs b/src/ACMESharp.MockServer/Controllers/AcmeController.cs index e7c2050..0a53339 100644 --- a/src/ACMESharp.MockServer/Controllers/AcmeController.cs +++ b/src/ACMESharp.MockServer/Controllers/AcmeController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -392,30 +392,6 @@ public ActionResult 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 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 @@ -549,7 +525,6 @@ public ActionResult AnswerChallenge(string authzKey, string challenge return dbChlng.Payload; } - T ExtractPayload(JwsSignedPayload signedPayload) { var payloadBytes = CryptoHelper.Base64.UrlDecode(signedPayload.Payload); diff --git a/src/ACMESharp.MockServer/Controllers/AcmeDirectoryController.cs b/src/ACMESharp.MockServer/Controllers/AcmeDirectoryController.cs index 2c4b586..6b27fe1 100644 --- a/src/ACMESharp.MockServer/Controllers/AcmeDirectoryController.cs +++ b/src/ACMESharp.MockServer/Controllers/AcmeDirectoryController.cs @@ -29,9 +29,7 @@ public ActionResult 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 { diff --git a/src/ACMESharp/Protocol/AcmeProtocolClient.cs b/src/ACMESharp/Protocol/AcmeProtocolClient.cs index a5b5324..a6aae80 100644 --- a/src/ACMESharp/Protocol/AcmeProtocolClient.cs +++ b/src/ACMESharp/Protocol/AcmeProtocolClient.cs @@ -615,32 +615,6 @@ public async Task GetOrderCertificateAsync( } } - /// - /// Revoke certificate - /// - /// - /// https://tools.ietf.org/html/draft-ietf-acme-acme-18#section-7.6 - /// - public async Task 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; - } - /// /// Generic fetch routine to retrieve raw bytes from a URL associated /// with an ACME endpoint. diff --git a/src/ACMESharp/Protocol/Messages/RevokeCertificateRequest.cs b/src/ACMESharp/Protocol/Messages/RevokeCertificateRequest.cs deleted file mode 100644 index 0671ed9..0000000 --- a/src/ACMESharp/Protocol/Messages/RevokeCertificateRequest.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using Newtonsoft.Json; - -namespace ACMESharp.Protocol.Messages -{ - /// - /// https://tools.ietf.org/html/draft-ietf-acme-acme-18#section-7.6 - /// - public class RevokeCertificateRequest - { - [JsonProperty("certificate", Required = Required.Always)] - [Required] - public string Certificate { get; set; } - - // Possible reasons specified here - // https://tools.ietf.org/html/rfc5280#section-5.3.1 - // Not sure where best to create an enum and how to handle the (optional) - // serialization of this property, so leaving it out for now - //[JsonProperty("reason")] - //public int Reason { get; set; } - } -} \ No newline at end of file diff --git a/test/ACMESharp.MockServer.UnitTests/AcmeControllerTests.cs b/test/ACMESharp.MockServer.UnitTests/AcmeControllerTests.cs index 795a4d3..85be4d3 100644 --- a/test/ACMESharp.MockServer.UnitTests/AcmeControllerTests.cs +++ b/test/ACMESharp.MockServer.UnitTests/AcmeControllerTests.cs @@ -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 GetDir() {