protected void ProcessOrders(AcmeResponse response)
 {
     if (response.Content is Protocol.OrderList orderList)
     {
         orderList.Orders = orderList.Orders.Select(o => $"{BaseUri}order/{o}").ToArray();
     }
 }
        protected ActionResult CreateActionResult(AcmeResponse response)
        {
            // TODO NewNoce must return 200 status for HEAD request
            ActionResult result = response.Content == null
                ? new NoContentResult()
                : (ActionResult) new OkObjectResult(response.Content)
            {
                StatusCode = response.StatusCode,
            };

            #region Add headers
            foreach (var header in response.Headers.AllKeys)
            {
                Response.Headers.Add(header, response.Headers.Get(header));
            }
            #endregion

            #region Add Content-Type for Error
            if (response.Content is Error)
            {
                Response.Headers.Add("Content-Type", new string[] { "application/problem+json" });
            }
            #endregion

            return(result);
        }
Exemple #3
0
 private void ThrowIfError <T>(AcmeResponse <T> response)
 {
     if (response.Error != null)
     {
         throw new Exception($"{response.Error.Type}: {response.Error.Detail} ({response.Error.Status})");
     }
 }
Exemple #4
0
        public void POST_Nonce_Empty()
        {
            AcmeResponse response = null;

            using var provider = Application.CreateProvider();
            IAcmeController controller = (IAcmeController)provider.GetService(typeof(IAcmeController));

            var accountKey = RSA.Create(2048);
            var token      = new JsonWebSignature();

            token.SetProtected(new JsonWebSignatureProtected
            {
                Url       = $"{Application.BaseAddress}new-acct",
                Algorithm = AlgorithmsEnum.RS256,
                Key       = new JsonWebKey(accountKey),
            });
            token.Sign(accountKey);

            response = controller.CreateAccount(new AcmeRequest
            {
                Path   = $"{Application.BaseAddress}new-acct",
                Method = "POST",
                Token  = token,
            });

            Assert.Equal(400, response.StatusCode);

            var content = response.GetContent <Protocol.Error>();

            Assert.Equal(Protocol.ErrorType.Malformed, content.Type);
            Assert.NotNull(content.Detail);
        }
Exemple #5
0
        /// <summary>
        /// Deactivates an authorization.
        /// </summary>
        /// <param name="AccountLocation">Account location.</param>
        /// <param name="AuthorizationLocation">Authorization location</param>
        /// <returns>New authorization object.</returns>
        public async Task <AcmeAuthorization> DeactivateAuthorization(Uri AccountLocation, Uri AuthorizationLocation)
        {
            AcmeResponse Response = await this.POST(AuthorizationLocation, AccountLocation,
                                                    new KeyValuePair <string, object>("status", "deactivated"));

            return(new AcmeAuthorization(this, AccountLocation, Response.Location, Response.Payload));
        }
Exemple #6
0
        /// <summary>
        /// Finalize order.
        /// </summary>
        /// <param name="AccountLocation">Account location.</param>
        /// <param name="FinalizeLocation">Finalize location.</param>
        /// <param name="CertificateRequest">Certificate request.</param>
        /// <returns>New order object.</returns>
        public async Task <AcmeOrder> FinalizeOrder(Uri AccountLocation, Uri FinalizeLocation, CertificateRequest CertificateRequest)
        {
            byte[]       CSR      = CertificateRequest.BuildCSR();
            AcmeResponse Response = await this.POST(FinalizeLocation, AccountLocation,
                                                    new KeyValuePair <string, object>("csr", Base64Url.Encode(CSR)));

            return(new AcmeOrder(this, AccountLocation, Response.Location, Response.Payload, Response.ResponseMessage));
        }
Exemple #7
0
 private void ThrowIfError <T>(AcmeResponse <T> response, Uri uri)
 {
     if (response.Error != null)
     {
         throw new AcmeRequestException(
                   string.Format(Strings.ErrorFetchResource, uri),
                   response.Error);
     }
 }
Exemple #8
0
        /// <summary>
        /// Creates <see cref="AcmeResponse"/> with headers
        /// </summary>
        /// <returns></returns>
        public AcmeResponse CreateResponse()
        {
            var resp = new AcmeResponse
            {
                StatusCode = 200, // OK
            };

            resp.Headers.Link.Add(new LinkHeader($"{Options.BaseAddress}directory", new LinkHeaderItem("rel", "index", true)));
            resp.Headers.ReplayNonce = NonceService.Create();
            return(resp);
        }
Exemple #9
0
        /// <summary>
        /// Updates an account.
        /// </summary>
        /// <param name="AccountLocation">Account location.</param>
        /// <param name="Contact">New contact information.</param>
        /// <returns>New account object.</returns>
        public async Task <AcmeAccount> UpdateAccount(Uri AccountLocation, string[] Contact)
        {
            if (this.directory == null)
            {
                await this.GetDirectory();
            }

            AcmeResponse Response = await this.POST(AccountLocation, AccountLocation,
                                                    new KeyValuePair <string, object>("contact", Contact));

            return(new AcmeAccount(this, Response.Location, Response.Payload));
        }
Exemple #10
0
        /// <summary>
        /// Deactivates an account.
        /// </summary>
        /// <param name="AccountLocation">Account location.</param>
        /// <returns>New account object.</returns>
        public async Task <AcmeAccount> DeactivateAccount(Uri AccountLocation)
        {
            if (this.directory == null)
            {
                await this.GetDirectory();
            }

            AcmeResponse Response = await this.POST(AccountLocation, AccountLocation,
                                                    new KeyValuePair <string, object>("status", "deactivated"));

            return(new AcmeAccount(this, Response.Location, Response.Payload));
        }
Exemple #11
0
        internal async Task <AcmeResponse> POST(Uri URL, Uri KeyID, params KeyValuePair <string, object>[] Payload)
        {
            HttpResponseMessage Response = await this.HttpPost(URL, KeyID, null, Payload);

            byte[] Bin = await Response.Content.ReadAsByteArrayAsync();

            string   CharSet = Response.Content.Headers.ContentType?.CharSet;
            Encoding Encoding;

            if (string.IsNullOrEmpty(CharSet))
            {
                Encoding = Encoding.UTF8;
            }
            else
            {
                Encoding = InternetContent.GetEncoding(CharSet);
            }

            AcmeResponse AcmeResponse = new AcmeResponse()
            {
                Json            = Encoding.GetString(Bin),
                Location        = URL,
                ResponseMessage = Response,
                Payload         = null
            };

            if (Response.Headers.TryGetValues("Location", out IEnumerable <string> Values))
            {
                foreach (string s in Values)
                {
                    AcmeResponse.Location = new Uri(s);
                    break;
                }
            }

            if (string.IsNullOrEmpty(AcmeResponse.Json))
            {
                AcmeResponse.Payload = null;
            }
            else if ((AcmeResponse.Payload = JSON.Parse(AcmeResponse.Json) as IEnumerable <KeyValuePair <string, object> >) is null)
            {
                throw new Exception("Unexpected response returned.");
            }

            if (Response.IsSuccessStatusCode)
            {
                return(AcmeResponse);
            }
            else
            {
                throw CreateException(AcmeResponse.Payload, Response);
            }
        }
Exemple #12
0
        /// <summary>
        /// Creates an account on the ACME server.
        /// </summary>
        /// <param name="ContactURLs">URLs for contacting the account holder.</param>
        /// <param name="TermsOfServiceAgreed">If the terms of service have been accepted.</param>
        /// <returns>ACME account object.</returns>
        public async Task <AcmeAccount> CreateAccount(string[] ContactURLs, bool TermsOfServiceAgreed)
        {
            if (this.directory == null)
            {
                await this.GetDirectory();
            }

            AcmeResponse Response = await this.POST(this.directory.NewAccount, null,
                                                    new KeyValuePair <string, object>("termsOfServiceAgreed", TermsOfServiceAgreed),
                                                    new KeyValuePair <string, object>("contact", ContactURLs));

            AcmeAccount Account;

            if (Response.Payload == null)
            {
                Response = await this.POST(Response.Location, Response.Location);

                Account = new AcmeAccount(this, Response.Location, Response.Payload);

                bool ContactsDifferent = false;
                int  i, c = ContactURLs.Length;

                if (c != Account.Contact.Length)
                {
                    ContactsDifferent = true;
                }
                else
                {
                    for (i = 0; i < c; i++)
                    {
                        if (ContactURLs[i] != Account.Contact[i])
                        {
                            ContactsDifferent = true;
                            break;
                        }
                    }
                }

                if (ContactsDifferent)
                {
                    Account = await this.UpdateAccount(Account.Location, ContactURLs);
                }
            }
            else
            {
                Account = new AcmeAccount(this, Response.Location, Response.Payload);
            }

            return(Account);
        }
Exemple #13
0
        public void Account_New_TermsOfService_Enabled_TermsOfServiceAgreed_False()
        {
            AcmeResponse response = null;

            using var provider = Application.CreateProvider(o =>
            {
                o.TermsOfService = "https://some.com/acme/terms.pdf";
            });
            IAcmeController controller = (IAcmeController)provider.GetService(typeof(IAcmeController));

            // Get nonce
            response = controller.GetNonce(new AcmeRequest
            {
                Path   = $"{Application.BaseAddress}new-nonce",
                Method = "HEAD",
            });

            // Create token
            var accountKey = RSA.Create(2048);
            var token      = new JsonWebSignature();

            token.SetProtected(new JsonWebSignatureProtected
            {
                Url       = $"{Application.BaseAddress}new-acct",
                Algorithm = AlgorithmsEnum.RS256,
                Key       = new JsonWebKey(accountKey),
                Nonce     = response.Headers.ReplayNonce,
            });
            token.SetPayload(new NewAccount
            {
                Contacts             = new string[] { "mailto:[email protected]" },
                TermsOfServiceAgreed = false,
            });
            token.Sign(accountKey);

            // Create account
            response = controller.CreateAccount(new AcmeRequest
            {
                Path   = $"{Application.BaseAddress}new-acct",
                Method = "POST",
                Token  = token,
            });

            Assert.Equal(400, response.StatusCode);

            var content = response.GetContent <Protocol.Error>();

            Assert.Equal(Protocol.ErrorType.Malformed, content.Type);
            Assert.NotNull(content.Detail);
        }
Exemple #14
0
        /// <summary>
        /// Generates a new key for the account. (Account keys are managed by the CSP.)
        /// </summary>
        /// <param name="AccountLocation">URL of the account resource.</param>
        public async Task <AcmeAccount> NewKey(Uri AccountLocation)
        {
            if (this.directory == null)
            {
                await this.GetDirectory();
            }
            RSA NewKey = RSA.Create();

            NewKey.KeySize = KeySize;

            if (NewKey.KeySize != KeySize)              // Happens when using library from traditioanl .NET FW
            {
                Type T = Runtime.Inventory.Types.GetType("System.Security.Cryptography.RSACryptoServiceProvider");
                if (T == null)
                {
                    throw new Exception("Unable to set RSA key size to anything but default (" + NewKey.KeySize.ToString() + " bits).");
                }

                NewKey = Activator.CreateInstance(T, KeySize) as RSA;
            }

            RsaSsaPkcsSha256 Jws2 = new RsaSsaPkcsSha256(NewKey);

            try
            {
                Jws2.Sign(new KeyValuePair <string, object>[]
                {
                    new KeyValuePair <string, object>("url", this.directory.KeyChange.ToString())
                }, new KeyValuePair <string, object>[]
                {
                    new KeyValuePair <string, object>("account", AccountLocation.ToString()),
                    new KeyValuePair <string, object>("oldkey", this.jws.PublicWebKey),
                }, out string Header, out string Payload, out string Signature);

                AcmeResponse Response = await this.POST(this.directory.KeyChange, AccountLocation,
                                                        new KeyValuePair <string, object>("protected", Header),
                                                        new KeyValuePair <string, object>("payload", Payload),
                                                        new KeyValuePair <string, object>("signature", Signature));

                this.jwkThumbprint = null;
                this.jws.ImportKey(NewKey);

                return(new AcmeAccount(this, Response.Location, Response.Payload));
            }
            finally
            {
                Jws2.Dispose();
            }
        }
Exemple #15
0
        public void Account_New_TermsOfService_Disabled()
        {
            AcmeResponse response = null;

            using var provider = Application.CreateProvider();
            IAcmeController controller = (IAcmeController)provider.GetService(typeof(IAcmeController));

            // Get nonce
            response = controller.GetNonce(new AcmeRequest
            {
                Path   = $"{Application.BaseAddress}new-nonce",
                Method = "HEAD",
            });

            // Create token
            var accountKey = RSA.Create(2048);
            var token      = new JsonWebSignature();

            token.SetProtected(new JsonWebSignatureProtected
            {
                Url       = $"{Application.BaseAddress}new-acct",
                Algorithm = AlgorithmsEnum.RS256,
                Key       = new JsonWebKey(accountKey),
                Nonce     = response.Headers.ReplayNonce,
            });
            token.SetPayload(new NewAccount
            {
                Contacts = new string[] { "mailto:[email protected]" },
            });
            token.Sign(accountKey);

            // Create account
            response = controller.CreateAccount(new AcmeRequest
            {
                Path   = $"{Application.BaseAddress}new-acct",
                Method = "POST",
                Token  = token,
            });

            Assert.Equal(201, response.StatusCode);

            var content = response.GetContent <Protocol.Account>();

            Assert.Single(response.Headers.Link);
            Assert.Equal("https://test.server.com/acme/acct/1", response.Headers.Location);
            Assert.NotNull(content);
            Assert.NotNull(content.Key);
            Assert.Null(content.TermsOfServiceAgreed);
        }
Exemple #16
0
        /// <summary>
        /// Deactivates an account.
        /// </summary>
        /// <param name="AccountLocation">Account location.</param>
        /// <returns>New account object.</returns>
        public async Task <AcmeAccount> DeactivateAccount(Uri AccountLocation)
        {
            if (this.directory == null)
            {
                await this.GetDirectory();
            }

            AcmeResponse Response = await this.POST(AccountLocation, AccountLocation,
                                                    new KeyValuePair <string, object>("status", "deactivated"));

            this.jws.DeleteRsaKeyFromCsp();
            this.jws = null;
            this.jws = new RsaSsaPkcsSha256(KeySize, this.directoryEndpoint.ToString());

            return(new AcmeAccount(this, Response.Location, Response.Payload));
        }
Exemple #17
0
        /// <summary>
        /// Gets the account object from the ACME server.
        /// </summary>
        /// <returns>ACME account object.</returns>
        public async Task <AcmeAccount> GetAccount()
        {
            if (this.directory == null)
            {
                await this.GetDirectory();
            }

            AcmeResponse Response = await this.POST(this.directory.NewAccount, null,
                                                    new KeyValuePair <string, object>("onlyReturnExisting", true));

            if (Response.Payload == null)
            {
                Response = await this.POST(Response.Location, Response.Location);
            }

            return(new AcmeAccount(this, Response.Location, Response.Payload));
        }
Exemple #18
0
        /// <summary>
        /// Download the issued certificate.
        /// </summary>
        /// <see cref="https://tools.ietf.org/html/rfc8555#section-7.4.2"/>
        public async Task <AcmeResponse <X509Certificate2Collection> > OrderCertificateGetAsync(string certificateUrl)
        {
            Logger.Info("Getting an ACME certificate list. Params:{@params}", certificateUrl);

            var response = await Request(certificateUrl,
                                         new RequestParams
            {
                Method  = HttpMethod.Post,
                Payload = ""
            });

            var chain        = new X509Certificate2Collection();
            var mediaContnet = (MediaTypeContent)response.Content;
            var rawData      = mediaContnet.ToArray();

            switch (mediaContnet.Type)
            {
            case "application/pkix-cert":
                chain.Add(new X509Certificate2(rawData));
                break;

            case "application/pem-certificate-chain":
                var dec = Encoding.UTF8.GetString(rawData);
                chain.AddRange(PemConverter.Decode(dec).Select(o => new X509Certificate2(o)).ToArray());
                break;

            case "application/pkcs7-mime":
                chain.Import(rawData);
                break;

            default:
                throw new Exception("Wrong Content type");
            }
            var resp = new AcmeResponse <X509Certificate2Collection>()
            {
                StatusCode = (int)response.StatusCode,
                // todo need upgrade
                //ReplayNonce = replayNonceValues?.FirstOrDefault(),
                //Location = locationValues?.FirstOrDefault(),
                //Links = linksValues != null ? new LinkHeaderCollection(linksValues.ToArray()) : null,
                Content = chain,
            };

            return(resp);
        }
Exemple #19
0
        public void POST_Url_WrongTargetUrl()
        {
            /// The value of the "url" header
            /// parameter MUST be a string representing the target URL

            AcmeResponse response = null;

            using var provider = Application.CreateProvider();
            IAcmeController controller = (IAcmeController)provider.GetService(typeof(IAcmeController));

            // Get nonce
            response = controller.GetNonce(new AcmeRequest
            {
                Path   = $"{Application.BaseAddress}new-nonce",
                Method = "HEAD",
            });

            var accountKey = RSA.Create(2048);
            var token      = new JsonWebSignature();

            token.SetProtected(new JsonWebSignatureProtected
            {
                Url       = "https://wrong.com/acme/new-account",
                Nonce     = response.Headers.ReplayNonce,
                Algorithm = AlgorithmsEnum.RS256,
                Key       = new JsonWebKey(accountKey),
            });
            token.Sign(accountKey);

            response = controller.CreateAccount(new AcmeRequest
            {
                Path   = $"{Application.BaseAddress}new-acct",
                Method = "POST",
                Token  = token,
            });

            Assert.Equal(400, response.StatusCode);

            var content = response.GetContent <Protocol.Error>();

            Assert.Equal(Protocol.ErrorType.Malformed, content.Type);
            Assert.NotNull(content.Detail);
        }
Exemple #20
0
        /// <summary>
        /// Orders certificate.
        /// </summary>
        /// <param name="AccountLocation">Account resource location.</param>
        /// <param name="Identifiers">Identifiers to include in the certificate.</param>
        /// <param name="NotBefore">If provided, certificate is not valid before this point in time.</param>
        /// <param name="NotAfter">If provided, certificate is not valid after this point in time.</param>
        /// <returns>ACME order object.</returns>
        public async Task <AcmeOrder> OrderCertificate(Uri AccountLocation, AcmeIdentifier[] Identifiers,
                                                       DateTime?NotBefore, DateTime?NotAfter)
        {
            if (this.directory == null)
            {
                await this.GetDirectory();
            }

            int i, c = Identifiers.Length;

            IEnumerable <KeyValuePair <string, object> >[] Identifiers2 = new IEnumerable <KeyValuePair <string, object> > [c];

            for (i = 0; i < c; i++)
            {
                Identifiers2[i] = new KeyValuePair <string, object>[]
                {
                    new KeyValuePair <string, object>("type", Identifiers[i].Type),
                    new KeyValuePair <string, object>("value", Identifiers[i].Value)
                };
            }

            List <KeyValuePair <string, object> > Payload = new List <KeyValuePair <string, object> >()
            {
                new KeyValuePair <string, object>("identifiers", Identifiers2)
            };

            if (NotBefore.HasValue)
            {
                Payload.Add(new KeyValuePair <string, object>("notBefore", NotBefore.Value));
            }

            if (NotAfter.HasValue)
            {
                Payload.Add(new KeyValuePair <string, object>("notAfter", NotAfter.Value));
            }

            AcmeResponse Response = await this.POST(this.directory.NewOrder, AccountLocation,
                                                    Payload.ToArray());

            return(new AcmeOrder(this, AccountLocation, Response.Location, Response.Payload, Response.ResponseMessage));
        }
        protected HttpResponseMessage CreateHttpResponseMessage(AcmeResponse response)
        {
            HttpResponseMessage result;

            if (response.Content != null)
            {
                if (response.Content is MediaTypeContent content)
                {
                    result = Request.CreateResponse((HttpStatusCode)response.StatusCode);
                    var streamContent = new StreamContent(content.Content);
                    streamContent.Headers.Add("Content-Type", content.Type);
                    result.Content = streamContent;
                }
                else
                {
                    result = Request.CreateResponse((HttpStatusCode)response.StatusCode);

                    result.Content = new StringContent(
                        JsonConvert.SerializeObject(response.Content),
                        Encoding.UTF8,
                        response.Content is Error
                            ? "application/problem+json"
                            : "application/json");
                }
            }
            else
            {
                result = Request.CreateResponse(response.StatusCode);
            }

            #region Add headers
            foreach (var header in response.Headers.AllKeys)
            {
                result.Headers.Add(header, response.Headers.Get(header));
            }
            #endregion

            return(result);
        }
Exemple #22
0
        public void POST_Nonce_WrongEncoding()
        {
            AcmeResponse response = null;

            using var provider = Application.CreateProvider();
            IAcmeController controller = (IAcmeController)provider.GetService(typeof(IAcmeController));

            var accountKey = RSA.Create(2048);
            var token      = new JsonWebSignature();

            token.SetProtected(new JsonWebSignatureProtected
            {
                Url       = $"{Application.BaseAddress}new-acct",
                Algorithm = AlgorithmsEnum.RS256,
                Key       = new JsonWebKey(accountKey),
                Nonce     = "Wrong encoded nonce"
            });
            token.Sign(accountKey);

            response = controller.CreateAccount(new AcmeRequest
            {
                Path   = $"{Application.BaseAddress}new-acct",
                Method = "POST",
                Token  = token,
            });

            // If the value of a "nonce" header parameter is not valid
            // according to this encoding, then the verifier MUST reject the JWS as
            // malformed.
            Assert.Equal(400, response.StatusCode);

            var content = response.GetContent <Protocol.Error>();

            Assert.Equal(Protocol.ErrorType.Malformed, content.Type);
            Assert.NotNull(content.Detail);
        }
Exemple #23
0
        /// <summary>
        /// Generates a new key for the account. (Account keys are managed by the CSP.)
        /// </summary>
        /// <param name="AccountLocation">URL of the account resource.</param>
        public async Task <AcmeAccount> NewKey(Uri AccountLocation)
        {
            if (this.directory == null)
            {
                await this.GetDirectory();
            }

            RSACryptoServiceProvider NewKey = new RSACryptoServiceProvider(KeySize);
            RsaSsaPkcsSha256         Jws2   = new RsaSsaPkcsSha256(NewKey);

            try
            {
                Jws2.Sign(new KeyValuePair <string, object>[]
                {
                    new KeyValuePair <string, object>("url", this.directory.KeyChange.ToString())
                }, new KeyValuePair <string, object>[]
                {
                    new KeyValuePair <string, object>("account", AccountLocation.ToString()),
                    new KeyValuePair <string, object>("newkey", Jws2.PublicWebKey)
                }, out string Header, out string Payload, out string Signature);

                AcmeResponse Response = await this.POST(this.directory.KeyChange, AccountLocation,
                                                        new KeyValuePair <string, object>("protected", Header),
                                                        new KeyValuePair <string, object>("payload", Payload),
                                                        new KeyValuePair <string, object>("signature", Signature));

                this.jwkThumbprint = null;
                this.jws.ImportKey(NewKey);

                return(new AcmeAccount(this, Response.Location, Response.Payload));
            }
            finally
            {
                Jws2.Dispose();
            }
        }
Exemple #24
0
        internal async Task <AcmeResponse> POST(Uri URL, Uri KeyID, params KeyValuePair <string, object>[] Payload)
        {
            string HeaderString;
            string PayloadString;
            string Signature;

            if (KeyID == null)
            {
                this.jws.Sign(new KeyValuePair <string, object>[]
                {
                    new KeyValuePair <string, object>("nonce", await this.NextNonce()),
                    new KeyValuePair <string, object>("url", URL.ToString())
                }, Payload, out HeaderString, out PayloadString, out Signature);
            }
            else
            {
                this.jws.Sign(new KeyValuePair <string, object>[]
                {
                    new KeyValuePair <string, object>("kid", KeyID.ToString()),
                    new KeyValuePair <string, object>("nonce", await this.NextNonce()),
                    new KeyValuePair <string, object>("url", URL.ToString())
                }, Payload, out HeaderString, out PayloadString, out Signature);
            }

            string Json = JSON.Encode(new KeyValuePair <string, object>[]
            {
                new KeyValuePair <string, object>("protected", HeaderString),
                new KeyValuePair <string, object>("payload", PayloadString),
                new KeyValuePair <string, object>("signature", Signature)
            }, null);

            HttpContent Content = new ByteArrayContent(System.Text.Encoding.ASCII.GetBytes(Json));

            Content.Headers.Add("Content-Type", JwsAlgorithm.JwsContentType);
            HttpResponseMessage Response = await this.httpClient.PostAsync(URL, Content);

            this.GetNextNonce(Response);

            Stream Stream = await Response.Content.ReadAsStreamAsync();

            byte[] Bin = await Response.Content.ReadAsByteArrayAsync();

            string   CharSet = Response.Content.Headers.ContentType?.CharSet;
            Encoding Encoding;

            if (string.IsNullOrEmpty(CharSet))
            {
                Encoding = Encoding.UTF8;
            }
            else
            {
                Encoding = System.Text.Encoding.GetEncoding(CharSet);
            }

            AcmeResponse AcmeResponse = new AcmeResponse()
            {
                Json            = Encoding.GetString(Bin),
                Location        = URL,
                ResponseMessage = Response,
                Payload         = null
            };

            if (Response.Headers.TryGetValues("Location", out IEnumerable <string> Values))
            {
                foreach (string s in Values)
                {
                    AcmeResponse.Location = new Uri(s);
                    break;
                }
            }

            if (string.IsNullOrEmpty(AcmeResponse.Json))
            {
                AcmeResponse.Payload = null;
            }
            else if ((AcmeResponse.Payload = JSON.Parse(AcmeResponse.Json) as IEnumerable <KeyValuePair <string, object> >) == null)
            {
                throw new Exception("Unexpected response returned.");
            }

            if (Response.IsSuccessStatusCode)
            {
                return(AcmeResponse);
            }
            else
            {
                throw CreateException(AcmeResponse.Payload, Response);
            }
        }
Exemple #25
0
        public void Account_ChangeKey_DuplicateKey()
        {
            AcmeResponse response = null;

            using var provider = Application.CreateProvider();
            IAcmeController controller = (IAcmeController)provider.GetService(typeof(IAcmeController));

            // Get nonce
            response = controller.GetNonce(new AcmeRequest
            {
                Path   = $"{Application.BaseAddress}new-nonce",
                Method = "HEAD",
            });

            // Create token
            var accountKey = RSA.Create(2048);
            var token      = new JsonWebSignature();

            token.SetProtected(new JsonWebSignatureProtected
            {
                Url       = $"{Application.BaseAddress}new-acct",
                Algorithm = AlgorithmsEnum.RS256,
                Key       = new JsonWebKey(accountKey),
                Nonce     = response.Headers.ReplayNonce,
            });
            token.SetPayload(new NewAccount
            {
                Contacts = new string[] { "mailto:[email protected]" },
            });
            token.Sign(accountKey);

            // Create account
            response = controller.CreateAccount(new AcmeRequest
            {
                Path   = $"{Application.BaseAddress}new-acct",
                Method = "POST",
                Token  = token,
            });

            Assert.Equal(201, response.StatusCode);

            // Create token
            var duplicateKey = RSA.Create(2048);

            token = new JsonWebSignature();
            token.SetProtected(new JsonWebSignatureProtected
            {
                Url       = $"{Application.BaseAddress}new-acct",
                Algorithm = AlgorithmsEnum.RS256,
                Key       = new JsonWebKey(duplicateKey),
                Nonce     = response.Headers.ReplayNonce,
            });
            token.SetPayload(new NewAccount
            {
                Contacts = new string[] { "mailto:[email protected]" },
            });
            token.Sign(duplicateKey);

            // Create account
            response = controller.CreateAccount(new AcmeRequest
            {
                Path   = $"{Application.BaseAddress}new-acct",
                Method = "POST",
                Token  = token,
            });

            Assert.Equal(201, response.StatusCode);

            token = new JsonWebSignature();
            token.SetProtected(new JsonWebSignatureProtected
            {
                Url       = $"{Application.BaseAddress}key-change",
                Algorithm = AlgorithmsEnum.RS256,
                KeyID     = $"{Application.BaseAddress}acct/1",
                Nonce     = response.Headers.ReplayNonce,
            });
            #region New key
            var newKeyToken = new JsonWebSignature();
            newKeyToken.SetProtected(new JsonWebSignatureProtected
            {
                Url       = $"{Application.BaseAddress}key-change",
                Algorithm = AlgorithmsEnum.RS256,
                Key       = new JsonWebKey(duplicateKey),
            });
            newKeyToken.SetPayload(new ChangeKey
            {
                Account = $"{Application.BaseAddress}acct/1",
                Key     = new JsonWebKey(accountKey),
            });
            newKeyToken.Sign(duplicateKey);
            #endregion

            token.SetPayload(newKeyToken);
            token.Sign(accountKey);

            // Update account
            response = controller.ChangeKey(new AcmeRequest
            {
                Path   = $"{Application.BaseAddress}key-change",
                Method = "POST",
                Token  = token,
            });

            Assert.Equal(409, response.StatusCode);
            Assert.Equal($"{Application.BaseAddress}acct/2", response.Headers.Location);

            var content = response.GetContent <Protocol.Error>();
            Assert.Equal(Protocol.ErrorType.Malformed, content.Type);
            Assert.NotNull(content.Detail);
        }
Exemple #26
0
        /// <summary>
        /// Acknowledges a challenge from the server.
        /// </summary>
        /// <param name="AccountLocation">Account location.</param>
        /// <param name="ChallengeLocation">Challenge location.</param>
        /// <returns>Acknowledged challenge object.</returns>
        public async Task <AcmeChallenge> AcknowledgeChallenge(Uri AccountLocation, Uri ChallengeLocation)
        {
            AcmeResponse Response = await this.POST(ChallengeLocation, AccountLocation);

            return(this.CreateChallenge(AccountLocation, Response.Payload));
        }
Exemple #27
0
        /// <summary>
        /// Gets the state of an authorization.
        /// </summary>
        /// <param name="AccountLocation">URI of account.</param>
        /// <param name="AuthorizationLocation">URI of authorization.</param>
        /// <returns>ACME authorization object.</returns>
        public async Task <AcmeAuthorization> GetAuthorization(Uri AccountLocation, Uri AuthorizationLocation)
        {
            AcmeResponse Response = await this.GET(AuthorizationLocation);

            return(new AcmeAuthorization(this, AccountLocation, AuthorizationLocation, Response.Payload));
        }
Exemple #28
0
        /// <summary>
        /// Gets the list of current orders for an account.
        /// </summary>
        /// <param name="AccountLocation">URI of account.</param>
        /// <param name="OrdersLocation">URI of orders.</param>
        /// <returns>ACME order object.</returns>
        public async Task <AcmeOrder[]> GetOrders(Uri AccountLocation, Uri OrdersLocation)
        {
            AcmeResponse Response = await this.GET(OrdersLocation);

            return(null);
        }
Exemple #29
0
        /// <summary>
        /// Gets the state of an order.
        /// </summary>
        /// <param name="AccountLocation">URI of account.</param>
        /// <param name="OrderLocation">URI of order.</param>
        /// <returns>ACME order object.</returns>
        public async Task <AcmeOrder> GetOrder(Uri AccountLocation, Uri OrderLocation)
        {
            AcmeResponse Response = await this.GET(OrderLocation);

            return(new AcmeOrder(this, AccountLocation, OrderLocation, Response.Payload, Response.ResponseMessage));
        }
Exemple #30
0
        /// <summary>
        /// Gets the list of current orders for an account.
        /// </summary>
        /// <param name="AccountLocation">URI of account.</param>
        /// <param name="OrdersLocation">URI of orders.</param>
        /// <returns>ACME order object.</returns>
        public async Task <AcmeOrder[]> GetOrders(Uri AccountLocation, Uri OrdersLocation)
        {
            AcmeResponse _ = await this.GET(OrdersLocation);

            throw new NotImplementedException("Method not implemented.");
        }