public AcmeRegistration Register(string[] contacts) { AssertInit(); var requMsg = new NewRegRequest { Contact = contacts, }; var resp = RequestHttpPost(new Uri(RootUrl, Directory[AcmeServerDirectory.RES_NEW_REG]), requMsg); // HTTP 409 (Conflict) response for a previously registered pub key // Location: still had the regUri if (resp.IsError) { if (resp.StatusCode == HttpStatusCode.Conflict) { throw new AcmeWebException(resp.Error as WebException, "Conflict due to previously registered public key", resp); } else if (resp.IsError) { throw new AcmeWebException(resp.Error as WebException, "Unexpected error", resp); } } var regUri = resp.Headers[AcmeProtocol.HEADER_LOCATION]; if (string.IsNullOrEmpty(regUri)) { throw new AcmeException("server did not provide a registration URI in the response"); } var respMsg = JsonConvert.DeserializeObject <RegResponse>(resp.ContentAsString); var newReg = new AcmeRegistration { PublicKey = Signer.ExportJwk(), RegistrationUri = regUri, Contacts = respMsg.Contact, Links = resp.Links, /// Extracts the "Terms of Service" related link header if there is one and /// returns the URI associated with it. Otherwise returns <c>null</c>. TosLinkUri = resp.Links[AcmeProtocol.LINK_HEADER_REL_TOS].FirstOrDefault(), AuthorizationsUri = respMsg.Authorizations, CertificatesUri = respMsg.Certificates, TosAgreementUri = respMsg.Agreement, }; Registration = newReg; return(Registration); }
public AcmeClient(Uri rootUrl = null, AcmeServerDirectory dir = null, ISigner signer = null, AcmeRegistration reg = null) { RootUrl = rootUrl; Directory = dir; Signer = signer; Registration = reg; UserAgent = string.Format(AcmeProtocol.HTTP_USER_AGENT_FMT, this.GetType().Assembly.GetName().Version); }
public AcmeClient(Uri rootUrl = null, AcmeServerDirectory dir = null, ISigner signer = null, AcmeRegistration reg = null) { RootUrl = rootUrl; Directory = dir; Signer = signer; Registration = reg; UserAgent = string.Format(AcmeProtocol.HTTP_USER_AGENT_FMT, this.GetType().Assembly.GetName().Version); }
public AcmeRegistration UpdateRegistration(bool useRootUrl = false, bool agreeToTos = false, string[] contacts = null) { AssertInit(); AssertRegistration(); var requMsg = new UpdateRegRequest(); if (contacts != null) { requMsg.Contact = contacts; } if (agreeToTos && !string.IsNullOrWhiteSpace(Registration.TosLinkUri)) { requMsg.Agreement = Registration.TosLinkUri; } // Compute the URL to submit the request to, either exactly as // provided in the Registration object or relative to the Root URL var requUri = new Uri(Registration.RegistrationUri); if (useRootUrl) { requUri = new Uri(RootUrl, requUri.PathAndQuery); } var resp = RequestHttpPost(requUri, requMsg); if (resp.IsError) { throw new AcmeWebException(resp.Error as WebException, "Unexpected error", resp); } var respMsg = JsonConvert.DeserializeObject <RegResponse>(resp.ContentAsString); var updReg = new AcmeRegistration { PublicKey = Signer.ExportJwk(), RegistrationUri = Registration.RegistrationUri, Contacts = respMsg.Contact, Links = resp.Links, /// Extracts the "Terms of Service" related link header if there is one and /// returns the URI associated with it. Otherwise returns <c>null</c>. TosLinkUri = resp.Links[AcmeProtocol.LINK_HEADER_REL_TOS].FirstOrDefault(), AuthorizationsUri = respMsg.Authorizations, CertificatesUri = respMsg.Certificates, TosAgreementUri = respMsg.Agreement, }; Registration = updReg; return(Registration); }
public void Test0140_HandleHttpChallenge() { using (var signer = new RS256Signer()) { signer.Init(); using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestRegister.acmeSigner", FileMode.Open)) { signer.Load(fs); } AcmeRegistration reg; using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestRegister.acmeReg", FileMode.Open)) { reg = AcmeRegistration.Load(fs); } using (var client = BuildClient()) { client.RootUrl = _rootUrl; client.Signer = signer; client.Registration = reg; client.Init(); client.GetDirectory(true); AuthorizationState authzState; using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestAuthz.acmeAuthz", FileMode.Open)) { authzState = AuthorizationState.Load(fs); } var authzChallenge = client.GenerateAuthorizeChallengeAnswer(authzState, "simpleHttp"); using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestAuthz-ChallengeAnswersHandleHttp.acmeAuthz", FileMode.Create)) { authzState.Save(fs); } var wsFilePath = authzChallenge.ChallengeAnswer.Key; var wsFileBody = authzChallenge.ChallengeAnswer.Value; var wsInfo = WebServerInfo.Load(File.ReadAllText("webServerInfo.json")); using (var s = new MemoryStream(Encoding.UTF8.GetBytes(wsFileBody))) { var fileUrl = new Uri($"http://{authzState.Identifier}/{wsFilePath}"); wsInfo.Provider.UploadFile(fileUrl, s); } } } Thread.Sleep(90 * 1000); }
public void Test0190_RefreshCertificateRequest() { using (var signer = new RS256Signer()) { signer.Init(); using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestRegister.acmeSigner", FileMode.Open)) { signer.Load(fs); } AcmeRegistration reg; using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestRegister.acmeReg", FileMode.Open)) { reg = AcmeRegistration.Load(fs); } //var csrRaw = File.ReadAllBytes($"{BASE_LOCAL_STORE}test-csr.der"); //var csrB64u = JwsHelper.Base64UrlEncode(csrRaw); using (var client = BuildClient()) { client.RootUrl = _rootUrl; client.Signer = signer; client.Registration = reg; client.Init(); client.GetDirectory(true); CertificateRequest certRequ; using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestCertRequ.acmeCertRequ", FileMode.Open)) { certRequ = CertificateRequest.Load(fs); } client.RefreshCertificateRequest(certRequ, true); using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestCertRequ-Refreshed.acmeCertRequ", FileMode.Create)) { certRequ.Save(fs); } if (!string.IsNullOrEmpty(certRequ.CertificateContent)) { using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestCertRequ-Refreshed.cer", FileMode.Create)) { certRequ.SaveCertificate(fs); } } } } }
public void Test0130_HandleDnsChallenge() { using (var signer = new RS256Signer()) { signer.Init(); using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestRegister.acmeSigner", FileMode.Open)) { signer.Load(fs); } AcmeRegistration reg; using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestRegister.acmeReg", FileMode.Open)) { reg = AcmeRegistration.Load(fs); } using (var client = BuildClient()) { client.RootUrl = _rootUrl; client.Signer = signer; client.Registration = reg; client.Init(); client.GetDirectory(true); AuthorizationState authzState; using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestAuthz.acmeAuthz", FileMode.Open)) { authzState = AuthorizationState.Load(fs); } var authzChallenge = client.GenerateAuthorizeChallengeAnswer(authzState, "dns"); using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestAuthz-ChallengeAnswersHandleDns.acmeAuthz", FileMode.Create)) { authzState.Save(fs); } var dnsName = authzChallenge.ChallengeAnswer.Key; var dnsValue = Regex.Replace(authzChallenge.ChallengeAnswer.Value, "\\s", ""); var dnsValues = Regex.Replace(dnsValue, "(.{100,100})", "$1\n").Split('\n'); var dnsInfo = DnsInfo.Load(File.ReadAllText("dnsInfo.json")); dnsInfo.Provider.EditTxtRecord(dnsName, dnsValues); } } Thread.Sleep(90 * 1000); }
public void Test0090_AuthorizeIdentifier() { using (var signer = new RS256Signer()) { signer.Init(); using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestRegister.acmeSigner", FileMode.Open)) { signer.Load(fs); } AcmeRegistration reg; using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestRegister.acmeReg", FileMode.Open)) { reg = AcmeRegistration.Load(fs); } using (var client = BuildClient()) { client.RootUrl = _rootUrl; client.Signer = signer; client.Registration = reg; client.Init(); client.GetDirectory(true); var authzState = client.AuthorizeIdentifier(TEST_CN1); foreach (var c in authzState.Challenges) { if (c.Type == "dns") { var dnsResponse = c.GenerateDnsChallengeAnswer( authzState.Identifier, signer); } } using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestAuthz.acmeAuthz", FileMode.Create)) { authzState.Save(fs); } } } }
public void Test0145_SubmitHttpChallengeAnswers() { using (var signer = new RS256Signer()) { signer.Init(); using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestRegister.acmeSigner", FileMode.Open)) { signer.Load(fs); } AcmeRegistration reg; using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestRegister.acmeReg", FileMode.Open)) { reg = AcmeRegistration.Load(fs); } using (var client = BuildClient()) { client.RootUrl = _rootUrl; client.Signer = signer; client.Registration = reg; client.Init(); client.GetDirectory(true); AuthorizationState authzState; using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestAuthz-ChallengeAnswersHandleHttp.acmeAuthz", FileMode.Open)) { authzState = AuthorizationState.Load(fs); } client.GenerateAuthorizeChallengeAnswer(authzState, "simpleHttp"); client.SubmitAuthorizeChallengeAnswer(authzState, "simpleHttp", true); using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestAuthz-HttpChallengeAnswered.acmeAuthz", FileMode.Create)) { authzState.Save(fs); } } } }
public void Test0080_AuthorizeDnsBlacklisted() { using (var signer = new RS256Signer()) { signer.Init(); using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestRegister.acmeSigner", FileMode.Open)) { signer.Load(fs); } AcmeRegistration reg; using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestRegister.acmeReg", FileMode.Open)) { reg = AcmeRegistration.Load(fs); } using (var client = BuildClient()) { client.RootUrl = _rootUrl; client.Signer = signer; client.Registration = reg; client.Init(); client.GetDirectory(true); try { client.AuthorizeIdentifier("acme-win-test.example.com"); } catch (AcmeClient.AcmeWebException ex) { Assert.IsNotNull(ex.WebException); Assert.IsNotNull(ex.Response); Assert.IsNotNull(ex.Response.ProblemDetail); Assert.AreEqual(HttpStatusCode.Forbidden, ex.Response.StatusCode); Assert.AreEqual("urn:acme:error:unauthorized", ex.Response.ProblemDetail.Type); StringAssert.Contains(ex.Response.ProblemDetail.Detail, "blacklist"); } } } }
public void Test0100_RefreshAuthzDnsChallenge() { using (var signer = new RS256Signer()) { signer.Init(); using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestRegister.acmeSigner", FileMode.Open)) { signer.Load(fs); } AcmeRegistration reg; using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestRegister.acmeReg", FileMode.Open)) { reg = AcmeRegistration.Load(fs); } using (var client = BuildClient()) { client.RootUrl = _rootUrl; client.Signer = signer; client.Registration = reg; client.Init(); client.GetDirectory(true); AuthorizationState authzState; using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestAuthz.acmeAuthz", FileMode.Open)) { authzState = AuthorizationState.Load(fs); } client.RefreshAuthorizeChallenge(authzState, "dns", true); using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestAuthz-DnsChallengeRefreshed.acmeAuthz", FileMode.Create)) { authzState.Save(fs); } } } }
public void Test0095_RefreshIdentifierAuthorization() { using (var signer = new RS256Signer()) { signer.Init(); using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestRegister.acmeSigner", FileMode.Open)) { signer.Load(fs); } AcmeRegistration reg; using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestRegister.acmeReg", FileMode.Open)) { reg = AcmeRegistration.Load(fs); } using (var client = BuildClient()) { client.RootUrl = _rootUrl; client.Signer = signer; client.Registration = reg; client.Init(); client.GetDirectory(true); AuthorizationState authzState; using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestAuthz.acmeAuthz", FileMode.Open)) { authzState = AuthorizationState.Load(fs); } var authzRefreshState = client.RefreshIdentifierAuthorization(authzState, true); using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestAuthz-Refresh.acmeAuthz", FileMode.Create)) { authzRefreshState.Save(fs); } } } }
public void Test0160_RequestCertificateInvalidCsr() { using (var signer = new RS256Signer()) { signer.Init(); using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestRegister.acmeSigner", FileMode.Open)) { signer.Load(fs); } AcmeRegistration reg; using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestRegister.acmeReg", FileMode.Open)) { reg = AcmeRegistration.Load(fs); } using (var client = BuildClient()) { client.RootUrl = _rootUrl; client.Signer = signer; client.Registration = reg; client.Init(); client.GetDirectory(true); try { client.RequestCertificate("FOOBARNON"); Assert.Fail("WebException expected"); } catch (AcmeClient.AcmeWebException ex) { Assert.IsNotNull(ex.WebException); Assert.IsNotNull(ex.Response); Assert.AreEqual(HttpStatusCode.BadRequest, ex.Response.StatusCode); } } } }
public void Test0040_RegisterEmptyUpdate() { using (var signer = new RS256Signer()) { signer.Init(); using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestRegister.acmeSigner", FileMode.Open)) { signer.Load(fs); } AcmeRegistration reg; using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestRegister.acmeReg", FileMode.Open)) { reg = AcmeRegistration.Load(fs); } using (var client = BuildClient()) { client.RootUrl = _rootUrl; client.Signer = signer; client.Registration = reg; client.Init(); client.GetDirectory(true); // Do a simple update with no data changes requested client.UpdateRegistration(true); Assert.IsNotNull(client.Registration); Assert.IsFalse(string.IsNullOrWhiteSpace(client.Registration.RegistrationUri)); using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestRegisterUpdate.acmeReg", FileMode.Create)) { client.Registration.Save(fs); } } } }
public void Test0060_RegisterUpdateContacts() { using (var signer = new RS256Signer()) { signer.Init(); using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestRegister.acmeSigner", FileMode.Open)) { signer.Load(fs); } AcmeRegistration reg; using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestRegister.acmeReg", FileMode.Open)) { reg = AcmeRegistration.Load(fs); } using (var client = BuildClient()) { client.RootUrl = _rootUrl; client.Signer = signer; client.Registration = reg; client.Init(); client.GetDirectory(true); client.UpdateRegistration(true, contacts: new string[] { TEST_EM2, }); Assert.IsNotNull(client.Registration); Assert.IsFalse(string.IsNullOrWhiteSpace(client.Registration.RegistrationUri)); using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestRegisterUpdate.acmeReg", FileMode.Create)) { client.Registration.Save(fs); } } } }
public AcmeRegistration UpdateRegistration(bool useRootUrl = false, bool agreeToTos = false, string[] contacts = null) { AssertInit(); AssertRegistration(); var requMsg = new UpdateRegRequest(); if (contacts != null) requMsg.Contact = contacts; if (agreeToTos && !string.IsNullOrWhiteSpace(Registration.TosLinkUri)) requMsg.Agreement = Registration.TosLinkUri; // Compute the URL to submit the request to, either exactly as // provided in the Registration object or relative to the Root URL var requUri = new Uri(Registration.RegistrationUri); if (useRootUrl) requUri = new Uri(RootUrl, requUri.PathAndQuery); var resp = RequestHttpPost(requUri, requMsg); if (resp.IsError) { throw new AcmeWebException(resp.Error as WebException, "Unexpected error", resp); } var respMsg = JsonConvert.DeserializeObject<RegResponse>(resp.ContentAsString); var updReg = new AcmeRegistration { PublicKey = Signer.ExportJwk(), RegistrationUri = Registration.RegistrationUri, Contacts = respMsg.Contact, Links = resp.Links, /// Extracts the "Terms of Service" related link header if there is one and /// returns the URI associated with it. Otherwise returns <c>null</c>. TosLinkUri = resp.Links[AcmeProtocol.LINK_HEADER_REL_TOS].FirstOrDefault(), AuthorizationsUri = respMsg.Authorizations, CertificatesUri = respMsg.Certificates, TosAgreementUri = respMsg.Agreement, }; Registration = updReg; return Registration; }
public AcmeRegistration Register(string[] contacts) { AssertInit(); var requMsg = new NewRegRequest { Contact = contacts, }; var resp = RequestHttpPost(new Uri(RootUrl, Directory[AcmeServerDirectory.RES_NEW_REG]), requMsg); // HTTP 409 (Conflict) response for a previously registered pub key // Location: still had the regUri if (resp.IsError) { if (resp.StatusCode == HttpStatusCode.Conflict) throw new AcmeWebException(resp.Error as WebException, "Conflict due to previously registered public key", resp); else if (resp.IsError) throw new AcmeWebException(resp.Error as WebException, "Unexpected error", resp); } var regUri = resp.Headers[AcmeProtocol.HEADER_LOCATION]; if (string.IsNullOrEmpty(regUri)) throw new AcmeException("server did not provide a registration URI in the response"); var respMsg = JsonConvert.DeserializeObject<RegResponse>(resp.ContentAsString); var newReg = new AcmeRegistration { PublicKey = Signer.ExportJwk(), RegistrationUri = regUri, Contacts = respMsg.Contact, Links = resp.Links, /// Extracts the "Terms of Service" related link header if there is one and /// returns the URI associated with it. Otherwise returns <c>null</c>. TosLinkUri = resp.Links[AcmeProtocol.LINK_HEADER_REL_TOS].FirstOrDefault(), AuthorizationsUri = respMsg.Authorizations, CertificatesUri = respMsg.Certificates, TosAgreementUri = respMsg.Agreement, }; Registration = newReg; return Registration; }
public void Test0170_GenCsrAndRequestCertificate() { var rsaKeys = CsrHelper.GenerateRsaPrivateKey(); using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestGenCsr-rsaKeys.txt", FileMode.Create)) { rsaKeys.Save(fs); } var csrDetails = new CsrHelper.CsrDetails { CommonName = TEST_CN1 }; var csr = CsrHelper.GenerateCsr(csrDetails, rsaKeys); using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestGenCsr-csrDetails.txt", FileMode.Create)) { csrDetails.Save(fs); } using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestGenCsr-csr.txt", FileMode.Create)) { csr.Save(fs); } using (var signer = new RS256Signer()) { signer.Init(); using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestRegister.acmeSigner", FileMode.Open)) { signer.Load(fs); } AcmeRegistration reg; using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestRegister.acmeReg", FileMode.Open)) { reg = AcmeRegistration.Load(fs); } byte[] derRaw; using (var bs = new MemoryStream()) { csr.ExportAsDer(bs); derRaw = bs.ToArray(); } var derB64u = JwsHelper.Base64UrlEncode(derRaw); using (var client = BuildClient()) { client.RootUrl = _rootUrl; client.Signer = signer; client.Registration = reg; client.Init(); client.GetDirectory(true); var certRequ = client.RequestCertificate(derB64u); using (var fs = new FileStream($"{BASE_LOCAL_STORE}TestCertRequ.acmeCertRequ", FileMode.Create)) { certRequ.Save(fs); } } } }