예제 #1
0
        public void RefreshAuthorizeChallenge(AuthorizationState authzState, string type, bool useRootUrl = false)
        {
            AssertInit();
            AssertRegistration();

            var c = authzState.Challenges.FirstOrDefault(x => x.Type == type);

            if (c == null)
            {
                throw new ArgumentOutOfRangeException(nameof(type), "no challenge found matching requested type")
                      .With(nameof(type), type);
            }

            var requUri = new Uri(c.Uri);

            if (useRootUrl)
            {
                requUri = new Uri(RootUrl, requUri.PathAndQuery);
            }

            var resp = RequestHttpGet(requUri);
            var cp   = JsonConvert.DeserializeObject <ChallengePart>(resp.ContentAsString);

            c.Type   = cp.Type;
            c.Uri    = cp.Uri;
            c.Token  = cp.Token;
            c.Status = cp.Status;
        }
예제 #2
0
        public AuthorizeChallenge SubmitAuthorizeChallengeAnswer(AuthorizationState authzState,
                                                                 string type, bool useRootUrl = false)
        {
            AssertInit();
            AssertRegistration();

            var c = authzState.Challenges.FirstOrDefault(x => x.Type == type);

            if (c == null)
            {
                throw new ArgumentException("no challenge found matching requested type");
            }

            if (c.ChallengeAnswer.Key == null || c.ChallengeAnswer.Value == null || c.ChallengeAnswerMessage == null)
            {
                throw new InvalidOperationException("challenge answer has not been generated");
            }

            var requUri = new Uri(c.Uri);

            if (useRootUrl)
            {
                requUri = new Uri(RootUrl, requUri.PathAndQuery);
            }

            var resp = RequestHttpPost(requUri, c.ChallengeAnswerMessage);

            if (resp.IsError)
            {
                throw new AcmeWebException(resp.Error as WebException,
                                           "Unexpected error", resp);
            }

            return(c);
        }
예제 #3
0
        public AuthorizeChallenge DecodeChallenge(AuthorizationState authzState, string challengeType)
        {
            AssertInit();
            AssertRegistration();

            var authzChallenge = authzState.Challenges.FirstOrDefault(x => x.Type == challengeType);

            if (authzChallenge == null)
            {
                throw new ArgumentOutOfRangeException(nameof(challengeType),
                                                      "no challenge found matching requested type")
                      .With("challengeType", challengeType);
            }

            var provider = ChallengeDecoderExtManager.GetProvider(challengeType);

            if (provider == null)
            {
                throw new NotSupportedException("no provider exists for requested challenge type")
                      .With("challengeType", challengeType);
            }

            using (var decoder = provider.GetDecoder(authzState.IdentifierPart, authzChallenge.ChallengePart))
            {
                authzChallenge.Challenge = decoder.Decode(authzState.IdentifierPart, authzChallenge.ChallengePart, Signer);

                if (authzChallenge.Challenge == null)
                {
                    throw new InvalidDataException("challenge decoder produced no output");
                }
            }

            return(authzChallenge);
        }
예제 #4
0
        public AuthorizationState AuthorizeIdentifier(string dnsIdentifier)
        {
            AssertInit();
            AssertRegistration();

            var requMsg = new NewAuthzRequest
            {
                Identifier = new IdentifierPart
                {
                    Type  = AcmeProtocol.IDENTIFIER_TYPE_DNS,
                    Value = dnsIdentifier
                }
            };

            var resp = RequestHttpPost(new Uri(RootUrl,
                                               Directory[AcmeServerDirectory.RES_NEW_AUTHZ]), requMsg);

            if (resp.IsError)
            {
                throw new AcmeWebException(resp.Error as WebException,
                                           "Unexpected error", resp);
            }

            var uri = resp.Headers[AcmeProtocol.HEADER_LOCATION];

            if (string.IsNullOrEmpty(uri))
            {
                throw new AcmeProtocolException("Response is missing an identifier authorization resource URI", resp);
            }

            var respMsg = JsonConvert.DeserializeObject <NewAuthzResponse>(resp.ContentAsString);

            var authzState = new AuthorizationState
            {
                IdentifierPart = respMsg.Identifier,
                IdentifierType = respMsg.Identifier.Type,
                Identifier     = respMsg.Identifier.Value,
                Uri            = uri,
                Status         = respMsg.Status,
                Expires        = respMsg.Expires,
                Combinations   = respMsg.Combinations,

                // Simple copy/conversion from one form to another
                Challenges = respMsg.Challenges.Select(x => new AuthorizeChallenge
                {
                    ChallengePart = x,
                    Type          = x.Type,
                    Status        = x.Status,
                    Uri           = x.Uri,
                    Token         = x.Token,
                }),
            };

            return(authzState);
        }
예제 #5
0
        public AuthorizeChallenge HandleChallenge(AuthorizationState authzState,
                                                  string challengeType,
                                                  string handlerName, IReadOnlyDictionary <string, object> handlerParams,
                                                  bool cleanUp = false)
        {
            var provider = ChallengeHandlerExtManager.GetProvider(handlerName);

            if (provider == null)
            {
                throw new InvalidOperationException("unable to resolve Challenge Handler provider")
                      .With("handlerName", handlerName);
            }

            var authzChallenge = authzState.Challenges.FirstOrDefault(x => x.Type == challengeType);

            if (authzChallenge == null)
            {
                throw new ArgumentOutOfRangeException(nameof(challengeType),
                                                      "no challenge found matching requested type")
                      .With("challengeType", challengeType);
            }

            if (!provider.IsSupported(authzChallenge.Challenge))
            {
                throw new InvalidOperationException("Challenge Handler does not support given Challenge")
                      .With("handlerName", handlerName)
                      .With("challengeType", authzChallenge.Challenge.Type);
            }

            var handler = provider.GetHandler(authzChallenge.Challenge, handlerParams);

            if (handler == null)
            {
                throw new InvalidOperationException("no Challenge Handler provided for given Challenge")
                      .With("handlerName", handlerName)
                      .With("challengeType", authzChallenge.Challenge.Type);
            }

            authzChallenge.HandlerName = handlerName;

            if (cleanUp)
            {
                handler.CleanUp(authzChallenge.Challenge);
                authzChallenge.HandlerCleanUpDate = DateTime.Now;
            }
            else
            {
                handler.Handle(authzChallenge.Challenge);
                authzChallenge.HandlerHandleDate = DateTime.Now;
            }

            handler.Dispose();

            return(authzChallenge);
        }
예제 #6
0
        public AuthorizationState RefreshIdentifierAuthorization(AuthorizationState authzState, bool useRootUrl = false)
        {
            AssertInit();
            AssertRegistration();

            var requUri = new Uri(authzState.Uri);

            if (useRootUrl)
            {
                requUri = new Uri(RootUrl, requUri.PathAndQuery);
            }

            var resp = RequestHttpGet(requUri);

            if (resp.IsError)
            {
                throw new AcmeWebException(resp.Error as WebException,
                                           "Unexpected error", resp);
            }

            var uri = authzState.Uri;

            if (resp.Headers.AllKeys.Contains(AcmeProtocol.HEADER_LOCATION))
            {
                uri = resp.Headers[AcmeProtocol.HEADER_LOCATION];
            }

            var respMsg = JsonConvert.DeserializeObject <AuthzStatusResponse>(resp.ContentAsString);

            var authzStatusState = new AuthorizationState
            {
                // This is computed above
                Uri = uri,

                // These are updated
                IdentifierPart = respMsg.Identifier,
                IdentifierType = respMsg.Identifier.Type,
                Identifier     = respMsg.Identifier.Value,
                Status         = respMsg.Status,
                Expires        = respMsg.Expires,
                Combinations   = respMsg.Combinations,

                Challenges = respMsg.Challenges.Select(x => new AuthorizeChallenge
                {
                    ChallengePart = x,
                    Type          = x.Type,
                    Status        = x.Status,
                    Uri           = x.Uri,
                    Token         = x.Token,
                }),
            };

            return(authzStatusState);
        }
예제 #7
0
        public void Test0141_HandleHttpChallenge()
        {
            using (var signer = new RS256Signer())
            {
                signer.Init();
                using (var fs = new FileStream(_testRegister_AcmeSignerFile, FileMode.Open))
                {
                    signer.Load(fs);
                }

                AcmeRegistration reg;
                using (var fs = new FileStream(_testRegister_AcmeRegFile, FileMode.Open))
                {
                    reg = AcmeRegistration.Load(fs);
                }

                using (var client = BuildClient(testTagHeader: nameof(Test0141_HandleHttpChallenge)))
                {
                    client.RootUrl      = _rootUrl;
                    client.Signer       = signer;
                    client.Registration = reg;
                    client.Init();

                    client.GetDirectory(true);

                    AuthorizationState authzState;
                    using (var fs = new FileStream(_testAuthz_AcmeAuthzFile, FileMode.Open))
                    {
                        authzState = AuthorizationState.Load(fs);
                    }

                    var authzChallenge = client.GenerateAuthorizeChallengeAnswer(authzState, AcmeProtocol.CHALLENGE_TYPE_HTTP);
                    _testAuthzChallengeHttpHandled_AcmeAuthzFile = $"{_baseLocalStore}\\TestAuthz-ChallengeAnswersHandleHttp.acmeAuthz";
                    using (var fs = new FileStream(_testAuthzChallengeHttpHandled_AcmeAuthzFile, FileMode.Create))
                    {
                        authzState.Save(fs);
                    }

                    var wsFilePath = authzChallenge.ChallengeAnswer.Key;
                    var wsFileBody = authzChallenge.ChallengeAnswer.Value;

                    var wsInfo = WebServerInfo.Load(File.ReadAllText("config\\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);
        }
예제 #8
0
        public AuthorizeChallenge GenerateAuthorizeChallengeAnswer(AuthorizationState authzState, string type)
        {
            AssertInit();
            AssertRegistration();

            var c = authzState.Challenges.FirstOrDefault(x => x.Type == type);

            if (c == null)
            {
                throw new ArgumentOutOfRangeException("no challenge found matching requested type");
            }

            switch (type)
            {
            case AcmeProtocol.CHALLENGE_TYPE_DNS:
                c.ChallengeAnswer        = c.GenerateDnsChallengeAnswer(authzState.Identifier, Signer);
                c.ChallengeAnswerMessage = new AnswerDnsChallengeRequest
                {
                    ClientPublicKey = Signer.ExportJwk(),
                    Validation      = new
                    {
                        header  = new { alg = Signer.JwsAlg },
                        payload = JwsHelper.Base64UrlEncode(JsonConvert.SerializeObject(new
                        {
                            type  = type,
                            token = c.Token
                        })),
                        signature = c.ChallengeAnswer.Value,
                    }
                };
                break;

            case AcmeProtocol.CHALLENGE_TYPE_HTTP:
                c.ChallengeAnswer        = c.GenerateHttpChallengeAnswer(authzState.Identifier, Signer);
                c.ChallengeAnswerMessage = new AnswerHttpChallengeRequest
                {
                    KeyAuthorization = c.ChallengeAnswer.Value,
                };
                break;

            case AcmeProtocol.CHALLENGE_TYPE_SNI:
            case AcmeProtocol.CHALLENGE_TYPE_PRIORKEY:
                throw new ArgumentException("unimplemented or unsupported challenge type", nameof(type));

            default:
                throw new ArgumentException("unknown challenge type", nameof(type));
            }

            return(c);
        }
예제 #9
0
        public AuthorizeChallenge SubmitChallengeAnswer(AuthorizationState authzState,
                                                        string type, bool useRootUrl = false)
        {
            AssertInit();
            AssertRegistration();

            var authzChallenge = authzState.Challenges.FirstOrDefault(x => x.Type == type);

            if (authzChallenge == null)
            {
                throw new ArgumentException("no challenge found matching requested type");
            }

            if (authzChallenge.Challenge == null)
            {
                throw new InvalidOperationException("challenge has not been decoded");
            }
            if (authzChallenge.Challenge.Answer == null)
            {
                throw new InvalidOperationException("challenge answer has not been generated");
            }

            var requUri = new Uri(authzChallenge.Uri);

            if (useRootUrl)
            {
                requUri = new Uri(RootUrl, requUri.PathAndQuery);
            }

            var requ = ChallengeAnswerRequest.CreateRequest(authzChallenge.Challenge.Answer);
            var resp = RequestHttpPost(requUri, requ);

            if (resp.IsError)
            {
                throw new AcmeWebException(resp.Error as WebException,
                                           "Unexpected error", resp);
            }

            authzChallenge.SubmitResponse = resp;
            authzChallenge.SubmitDate     = DateTime.Now;

            return(authzChallenge);
        }
예제 #10
0
        public void Test0120_GenerateChallengeAnswers()
        {
            using (var signer = new RS256Signer())
            {
                signer.Init();
                using (var fs = new FileStream(_testRegister_AcmeSignerFile, FileMode.Open))
                {
                    signer.Load(fs);
                }

                AcmeRegistration reg;
                using (var fs = new FileStream(_testRegister_AcmeRegFile, FileMode.Open))
                {
                    reg = AcmeRegistration.Load(fs);
                }

                using (var client = BuildClient(testTagHeader: nameof(Test0120_GenerateChallengeAnswers)))
                {
                    client.RootUrl      = _rootUrl;
                    client.Signer       = signer;
                    client.Registration = reg;
                    client.Init();

                    client.GetDirectory(true);

                    AuthorizationState authzState;
                    using (var fs = new FileStream(_testAuthz_AcmeAuthzFile, FileMode.Open))
                    {
                        authzState = AuthorizationState.Load(fs);
                    }

                    //client.GenerateAuthorizeChallengeAnswer(authzState, AcmeProtocol.CHALLENGE_TYPE_DNS);
                    //client.GenerateAuthorizeChallengeAnswer(authzState, AcmeProtocol.CHALLENGE_TYPE_LEGACY_HTTP);
                    client.GenerateAuthorizeChallengeAnswer(authzState, AcmeProtocol.CHALLENGE_TYPE_HTTP);

                    _testAuthzChallengeAnswers_AcmeAuthzFile = $"{_baseLocalStore}\\TestAuthz-ChallengeAnswers.acmeAuthz";
                    using (var fs = new FileStream(_testAuthzChallengeAnswers_AcmeAuthzFile, FileMode.Create))
                    {
                        authzState.Save(fs);
                    }
                }
            }
        }
예제 #11
0
        public AuthorizationState RefreshIdentifierAuthorization(AuthorizationState authzState, bool useRootUrl = false)
        {
            AssertInit();
            AssertRegistration();

            var requUri = new Uri(authzState.Uri);

            if (useRootUrl)
            {
                requUri = new Uri(RootUrl, requUri.PathAndQuery);
            }

            var resp = RequestHttpGet(requUri);

            if (resp.IsError)
            {
                throw new AcmeWebException(resp.Error as WebException,
                                           "Unexpected error", resp);
            }

            var respMsg = JsonConvert.DeserializeObject <AuthzStatusResponse>(resp.ContentAsString);

            var authzStatusState = new AuthorizationState
            {
                IdentifierType = respMsg.Identifier.Type,
                Identifier     = respMsg.Identifier.Value,
                Status         = respMsg.Status,
                Expires        = respMsg.Expires,

                Challenges = respMsg.Challenges.Select(x => new AuthorizeChallenge
                {
                    Type             = x.Type,
                    Status           = x.Status,
                    Uri              = x.Uri,
                    Token            = x.Token,
                    Tls              = x.Tls,
                    ValidationRecord = x.ValidationRecord,
                }),
            };

            return(authzStatusState);
        }
예제 #12
0
        public void Test0095_RefreshIdentifierAuthorization()
        {
            using (var signer = new RS256Signer())
            {
                signer.Init();
                using (var fs = new FileStream(_testRegister_AcmeSignerFile, FileMode.Open))
                {
                    signer.Load(fs);
                }

                AcmeRegistration reg;
                using (var fs = new FileStream(_testRegister_AcmeRegFile, FileMode.Open))
                {
                    reg = AcmeRegistration.Load(fs);
                }

                using (var client = BuildClient(testTagHeader: nameof(Test0095_RefreshIdentifierAuthorization)))
                {
                    client.RootUrl      = _rootUrl;
                    client.Signer       = signer;
                    client.Registration = reg;
                    client.Init();

                    client.GetDirectory(true);

                    AuthorizationState authzState;
                    using (var fs = new FileStream(_testAuthz_AcmeAuthzFile, FileMode.Open))
                    {
                        authzState = AuthorizationState.Load(fs);
                    }

                    var authzRefreshState = client.RefreshIdentifierAuthorization(authzState, true);

                    _testAuthzRefresh_AcmeAuthzFile = $"{_baseLocalStore}\\TestAuthz-Refresh.acmeAuthz";
                    using (var fs = new FileStream(_testAuthzRefresh_AcmeAuthzFile, FileMode.Create))
                    {
                        authzRefreshState.Save(fs);
                    }
                }
            }
        }
예제 #13
0
        public AuthorizeChallenge GenerateAuthorizeChallengeAnswer(AuthorizationState authzState, string type)
        {
            AssertInit();
            AssertRegistration();

            var c = authzState.Challenges.FirstOrDefault(x => x.Type == type);

            if (c == null)
            {
                throw new ArgumentOutOfRangeException(nameof(type),
                                                      "no challenge found matching requested type");
            }

            switch (type)
            {
            case AcmeProtocol.CHALLENGE_TYPE_DNS:
                c.OldChallengeAnswer     = c.GenerateDnsChallengeAnswer(authzState.Identifier, Signer);
                c.ChallengeAnswerMessage = new AnswerDnsChallengeRequest
                {
                    KeyAuthorization = c.OldChallengeAnswer.Value,
                };
                break;

            case AcmeProtocol.CHALLENGE_TYPE_HTTP:
                c.OldChallengeAnswer     = c.GenerateHttpChallengeAnswer(authzState.Identifier, Signer);
                c.ChallengeAnswerMessage = new AnswerHttpChallengeRequest
                {
                    KeyAuthorization = c.OldChallengeAnswer.Value,
                };
                break;

            case AcmeProtocol.CHALLENGE_TYPE_SNI:
            case AcmeProtocol.CHALLENGE_TYPE_PRIORKEY:
                throw new ArgumentException("unimplemented or unsupported challenge type", nameof(type));

            default:
                throw new ArgumentException("unknown challenge type", nameof(type));
            }

            return(c);
        }
예제 #14
0
        public AuthorizeChallenge GenerateAuthorizeChallengeAnswer(AuthorizationState authzState, string type)
        {
            AssertInit();
            AssertRegistration();

            var c = authzState.Challenges.FirstOrDefault(x => x.Type == type);
            if (c == null)
                throw new ArgumentOutOfRangeException(nameof(type),
                        "no challenge found matching requested type");

            switch (type)
            {
                case AcmeProtocol.CHALLENGE_TYPE_DNS:
                    c.OldChallengeAnswer = c.GenerateDnsChallengeAnswer(authzState.Identifier, Signer);
                    c.ChallengeAnswerMessage = new AnswerDnsChallengeRequest
                    {
                        KeyAuthorization = c.OldChallengeAnswer.Value,
                    };
                    break;

                case AcmeProtocol.CHALLENGE_TYPE_HTTP:
                    c.OldChallengeAnswer = c.GenerateHttpChallengeAnswer(authzState.Identifier, Signer);
                    c.ChallengeAnswerMessage = new AnswerHttpChallengeRequest
                    {
                        KeyAuthorization = c.OldChallengeAnswer.Value,
                    };
                    break;

                case AcmeProtocol.CHALLENGE_TYPE_SNI:
                case AcmeProtocol.CHALLENGE_TYPE_PRIORKEY:
                    throw new ArgumentException("unimplemented or unsupported challenge type", nameof(type));

                default:
                    throw new ArgumentException("unknown challenge type", nameof(type));
            }

            return c;
        }
예제 #15
0
        public AuthorizeChallenge HandleChallenge(AuthorizationState authzState,
                string challengeType,
                string handlerName, IReadOnlyDictionary<string, object> handlerParams,
                bool cleanUp = false)
        {
            var provider = ChallengeHandlerExtManager.GetProvider(handlerName);
            if (provider == null)
                throw new InvalidOperationException("unable to resolve Challenge Handler provider")
                        .With("handlerName", handlerName);

            var authzChallenge = authzState.Challenges.FirstOrDefault(x => x.Type == challengeType);
            if (authzChallenge == null)
                throw new ArgumentOutOfRangeException(nameof(challengeType),
                        "no challenge found matching requested type")
                        .With("challengeType", challengeType);

            if (!provider.IsSupported(authzChallenge.Challenge))
                throw new InvalidOperationException("Challenge Handler does not support given Challenge")
                        .With("handlerName", handlerName)
                        .With("challengeType", authzChallenge.Challenge.Type);

            var handler = provider.GetHandler(authzChallenge.Challenge, handlerParams);
            if (handler == null)
                throw new InvalidOperationException("no Challenge Handler provided for given Challenge")
                        .With("handlerName", handlerName)
                        .With("challengeType", authzChallenge.Challenge.Type);

            authzChallenge.HandlerName = handlerName;

            if (cleanUp)
            {
                handler.CleanUp(authzChallenge.Challenge);
                authzChallenge.HandlerCleanUpDate = DateTime.Now;
            }
            else
            {
                handler.Handle(authzChallenge.Challenge);
                authzChallenge.HandlerHandleDate = DateTime.Now;
            }

            handler.Dispose();

            return authzChallenge;
        }
예제 #16
0
        public AuthorizationState RefreshIdentifierAuthorization(AuthorizationState authzState, bool useRootUrl = false)
        {
            AssertInit();
            AssertRegistration();

            var requUri = new Uri(authzState.Uri);
            if (useRootUrl)
                requUri = new Uri(RootUrl, requUri.PathAndQuery);

            var resp = RequestHttpGet(requUri);

            if (resp.IsError)
            {
                throw new AcmeWebException(resp.Error as WebException,
                        "Unexpected error", resp);
            }

            var uri = authzState.Uri;
            if (resp.Headers.AllKeys.Contains(AcmeProtocol.HEADER_LOCATION))
                uri = resp.Headers[AcmeProtocol.HEADER_LOCATION];

            var respMsg = JsonConvert.DeserializeObject<AuthzStatusResponse>(resp.ContentAsString);

            var authzStatusState = new AuthorizationState
            {
                // This is computed above
                Uri = uri,

                // These are updated
                IdentifierPart = respMsg.Identifier,
                IdentifierType = respMsg.Identifier.Type,
                Identifier = respMsg.Identifier.Value,
                Status = respMsg.Status,
                Expires = respMsg.Expires,
                Combinations = respMsg.Combinations,

                Challenges = respMsg.Challenges.Select(x => new AuthorizeChallenge
                {
                    ChallengePart = x,
                    Type = x.Type,
                    Status = x.Status,
                    Uri = x.Uri,
                    Token = x.Token,
                }),
            };

            return authzStatusState;
        }
예제 #17
0
        public AuthorizeChallenge SubmitChallengeAnswer(AuthorizationState authzState,
                string type, bool useRootUrl = false)
        {
            AssertInit();
            AssertRegistration();

            var authzChallenge = authzState.Challenges.FirstOrDefault(x => x.Type == type);
            if (authzChallenge == null)
                throw new ArgumentException("no challenge found matching requested type");

            if (authzChallenge.Challenge == null)
                throw new InvalidOperationException("challenge has not been decoded");
            if (authzChallenge.Challenge.Answer == null)
                throw new InvalidOperationException("challenge answer has not been generated");

            var requUri = new Uri(authzChallenge.Uri);
            if (useRootUrl)
                requUri = new Uri(RootUrl, requUri.PathAndQuery);

            var requ = ChallengeAnswerRequest.CreateRequest(authzChallenge.Challenge.Answer);
            var resp = RequestHttpPost(requUri, requ);

            if (resp.IsError)
            {
                throw new AcmeWebException(resp.Error as WebException,
                        "Unexpected error", resp);
            }

            authzChallenge.SubmitResponse = resp;
            authzChallenge.SubmitDate = DateTime.Now;

            return authzChallenge;
        }
예제 #18
0
        public AuthorizationState AuthorizeIdentifier(string dnsIdentifier)
        {
            AssertInit();
            AssertRegistration();

            var requMsg = new NewAuthzRequest
            {
                Identifier = new IdentifierPart
                {
                    Type = AcmeProtocol.IDENTIFIER_TYPE_DNS,
                    Value = dnsIdentifier
                }
            };

            var resp = RequestHttpPost(new Uri(RootUrl,
                    Directory[AcmeServerDirectory.RES_NEW_AUTHZ]), requMsg);

            if (resp.IsError)
            {
                throw new AcmeWebException(resp.Error as WebException,
                        "Unexpected error", resp);
            }

            var uri = resp.Headers[AcmeProtocol.HEADER_LOCATION];
            if (string.IsNullOrEmpty(uri))
                throw new AcmeProtocolException("Response is missing an identifier authorization resource URI", resp);

            var respMsg = JsonConvert.DeserializeObject<NewAuthzResponse>(resp.ContentAsString);

            var authzState = new AuthorizationState
            {
                IdentifierType = respMsg.Identifier.Type,
                Identifier = respMsg.Identifier.Value,
                Uri = uri,
                Status = respMsg.Status,
                Expires = respMsg.Expires,
                Combinations = respMsg.Combinations,

                // Simple copy/conversion from one form to another
                Challenges = respMsg.Challenges.Select(x => new AuthorizeChallenge
                {
                    Type = x.Type,
                    Status = x.Status,
                    Uri = x.Uri,
                    Token = x.Token,
                    ValidationRecord = x.ValidationRecord,
                }),
            };

            return authzState;
        }
예제 #19
0
        public AuthorizationState RefreshIdentifierAuthorization(AuthorizationState authzState, bool useRootUrl = false)
        {
            AssertInit();
            AssertRegistration();

            var requUri = new Uri(authzState.Uri);
            if (useRootUrl)
                requUri = new Uri(RootUrl, requUri.PathAndQuery);

            var resp = RequestHttpGet(requUri);

            if (resp.IsError)
            {
                throw new AcmeWebException(resp.Error as WebException,
                        "Unexpected error", resp);
            }

            var respMsg = JsonConvert.DeserializeObject<AuthzStatusResponse>(resp.ContentAsString);

            var authzStatusState = new AuthorizationState
            {
                IdentifierType = respMsg.Identifier.Type,
                Identifier = respMsg.Identifier.Value,
                Status = respMsg.Status,
                Expires = respMsg.Expires,

                Challenges = respMsg.Challenges.Select(x => new AuthorizeChallenge
                {
                    Type = x.Type,
                    Status = x.Status,
                    Uri = x.Uri,
                    Token = x.Token,
                    ValidationRecord = x.ValidationRecord,
                }),
            };

            return authzStatusState;
        }
예제 #20
0
        public void RefreshAuthorizeChallenge(AuthorizationState authzState, string type, bool useRootUrl = false)
        {
            AssertInit();
            AssertRegistration();

            var c = authzState.Challenges.FirstOrDefault(x => x.Type == type);
            if (c == null)
                throw new ArgumentOutOfRangeException("no challenge found matching requested type");

            var requUri = new Uri(c.Uri);
            if (useRootUrl)
                requUri = new Uri(RootUrl, requUri.PathAndQuery);

            var resp = RequestHttpGet(requUri);
            var cp = JsonConvert.DeserializeObject<ChallengePart>(resp.ContentAsString);

            c.Type = cp.Type;
            c.Uri = cp.Uri;
            c.Token = cp.Token;
            c.Status = cp.Status;
        }
예제 #21
0
        public AuthorizeChallenge DecodeChallenge(AuthorizationState authzState, string challengeType)
        {
            AssertInit();
            AssertRegistration();

            var authzChallenge = authzState.Challenges.FirstOrDefault(x => x.Type == challengeType);
            if (authzChallenge == null)
                throw new ArgumentOutOfRangeException(nameof(challengeType),
                        "no challenge found matching requested type")
                        .With("challengeType", challengeType);

            var provider = ChallengeDecoderExtManager.GetProvider(challengeType);
            if (provider == null)
                throw new NotSupportedException("no provider exists for requested challenge type")
                        .With("challengeType", challengeType);

            using (var decoder = provider.GetDecoder(authzState.IdentifierPart, authzChallenge.ChallengePart))
            {
                authzChallenge.Challenge = decoder.Decode(authzState.IdentifierPart, authzChallenge.ChallengePart, Signer);

                if (authzChallenge.Challenge == null)
                    throw new InvalidDataException("challenge decoder produced no output");
            }

            return authzChallenge;
        }
예제 #22
0
        public AuthorizeChallenge SubmitAuthorizeChallengeAnswer(AuthorizationState authzState,
                string type, bool useRootUrl = false)
        {
            AssertInit();
            AssertRegistration();

            var c = authzState.Challenges.FirstOrDefault(x => x.Type == type);
            if (c == null)
                throw new ArgumentException("no challenge found matching requested type");

            if (c.ChallengeAnswer.Key == null || c.ChallengeAnswer.Value == null || c.ChallengeAnswerMessage == null)
                throw new InvalidOperationException("challenge answer has not been generated");

            var requUri = new Uri(c.Uri);
            if (useRootUrl)
                requUri = new Uri(RootUrl, requUri.PathAndQuery);

            var resp = RequestHttpPost(requUri, c.ChallengeAnswerMessage);

            if (resp.IsError)
            {
                throw new AcmeWebException(resp.Error as WebException,
                        "Unexpected error", resp);
            }

            return c;
        }
예제 #23
0
        public AuthorizeChallenge GenerateAuthorizeChallengeAnswer(AuthorizationState authzState, string type)
        {
            AssertInit();
            AssertRegistration();

            var c = authzState.Challenges.FirstOrDefault(x => x.Type == type);
            if (c == null)
                throw new ArgumentOutOfRangeException("no challenge found matching requested type");

            switch (type)
            {
                case AcmeProtocol.CHALLENGE_TYPE_DNS:
                    c.ChallengeAnswer = c.GenerateDnsChallengeAnswer(authzState.Identifier, Signer);
                    c.ChallengeAnswerMessage = new AnswerDnsChallengeRequest
                    {
                        ClientPublicKey = Signer.ExportJwk(),
                        Validation = new
                        {
                            header = new { alg = Signer.JwsAlg },
                            payload = JwsHelper.Base64UrlEncode(JsonConvert.SerializeObject(new
                            {
                                type = type,
                                token = c.Token
                            })),
                            signature = c.ChallengeAnswer.Value,
                        }
                    };
                    break;

                case AcmeProtocol.CHALLENGE_TYPE_HTTP:
                    c.ChallengeAnswer = c.GenerateHttpChallengeAnswer(authzState.Identifier, Signer);
                    c.ChallengeAnswerMessage = new AnswerHttpChallengeRequest
                    {
                        KeyAuthorization = c.ChallengeAnswer.Value,
                    };
                    break;

                case AcmeProtocol.CHALLENGE_TYPE_SNI:
                case AcmeProtocol.CHALLENGE_TYPE_PRIORKEY:
                    throw new ArgumentException("unimplemented or unsupported challenge type", nameof(type));

                default:
                    throw new ArgumentException("unknown challenge type", nameof(type));
            }

            return c;
        }