diff --git a/letsencrypt/achallenges.py b/letsencrypt/achallenges.py index 4d85f5d6a..0cdec06df 100644 --- a/letsencrypt/achallenges.py +++ b/letsencrypt/achallenges.py @@ -59,15 +59,3 @@ class DNS(AnnotatedChallenge): """Client annotated "dns" ACME challenge.""" __slots__ = ('challb', 'domain') acme_type = challenges.DNS - - -class RecoveryContact(AnnotatedChallenge): - """Client annotated "recoveryContact" ACME challenge.""" - __slots__ = ('challb', 'domain') - acme_type = challenges.RecoveryContact - - -class ProofOfPossession(AnnotatedChallenge): - """Client annotated "proofOfPossession" ACME challenge.""" - __slots__ = ('challb', 'domain') - acme_type = challenges.ProofOfPossession diff --git a/letsencrypt/auth_handler.py b/letsencrypt/auth_handler.py index a324dd4b7..285a1f3b7 100644 --- a/letsencrypt/auth_handler.py +++ b/letsencrypt/auth_handler.py @@ -21,7 +21,7 @@ class AuthHandler(object): """ACME Authorization Handler for a client. :ivar auth: Authenticator capable of solving - :class:`~acme.challenges.DVChallenge` types + :class:`~acme.challenges.Challenge` types :type auth: :class:`letsencrypt.interfaces.IAuthenticator` :ivar acme.client.Client acme: ACME client API. @@ -117,9 +117,8 @@ class AuthHandler(object): """ # TODO: chall_update is a dirty hack to get around acme-spec #105 chall_update = dict() - active_achalls = [] - active_achalls.extend( - self._send_responses(self.achalls, resp, chall_update)) + active_achalls = self._send_responses(self.achalls, + resp, chall_update) # Check for updated status... try: @@ -253,8 +252,7 @@ class AuthHandler(object): if achall_list is None: achalls = self.achalls else: - achalls = [achall for achall in achall_list - if isinstance(achall.chall, challenges.DVChallenge)] + achalls = achall_list if achalls: self.auth.cleanup(achalls) @@ -280,7 +278,7 @@ class AuthHandler(object): :param list path: List of indices from `challenges`. - :returns: achalls, list of DVChallenge type + :returns: achalls, list of challenge type :class:`letsencrypt.achallenges.Indexed` :rtype: list @@ -291,12 +289,7 @@ class AuthHandler(object): for index in path: challb = self.authzr[domain].body.challenges[index] - chall = challb.chall - - achall = challb_to_achall(challb, self.account.key, domain) - - if isinstance(chall, challenges.DVChallenge): - achalls.append(achall) + achalls.append(challb_to_achall(challb, self.account.key, domain)) return achalls @@ -320,12 +313,6 @@ def challb_to_achall(challb, account_key, domain): challb=challb, domain=domain, account_key=account_key) elif isinstance(chall, challenges.DNS): return achallenges.DNS(challb=challb, domain=domain) - elif isinstance(chall, challenges.RecoveryContact): - return achallenges.RecoveryContact( - challb=challb, domain=domain) - elif isinstance(chall, challenges.ProofOfPossession): - return achallenges.ProofOfPossession( - challb=challb, domain=domain) else: raise errors.Error( "Received unsupported challenge of type: %s", chall.typ) diff --git a/letsencrypt/client.py b/letsencrypt/client.py index d0bdb1f85..6134c4e6e 100644 --- a/letsencrypt/client.py +++ b/letsencrypt/client.py @@ -163,7 +163,7 @@ class Client(object): dispatch DV challenges to appropriate authenticators (providing `.IAuthenticator` interface). :ivar .IAuthenticator auth: Prepared (`.IAuthenticator.prepare`) - authenticator that can solve the `.constants.DV_CHALLENGES`. + authenticator that can solve ACME challenges. :ivar .IInstaller installer: Installer. :ivar acme.client.Client acme: Optional ACME client API handle. You might already have one from `register`. diff --git a/letsencrypt/errors.py b/letsencrypt/errors.py index a5c3186a8..b2b078f6a 100644 --- a/letsencrypt/errors.py +++ b/letsencrypt/errors.py @@ -48,19 +48,6 @@ class FailedChallenges(AuthorizationError): for achall in self.failed_achalls if achall.error is not None)) -class ContAuthError(AuthorizationError): - """Let's Encrypt Continuity Authenticator error.""" - - -class DvAuthError(AuthorizationError): - """Let's Encrypt DV Authenticator error.""" - - -# Authenticator - Challenge specific errors -class TLSSNI01Error(DvAuthError): - """Let's Encrypt TLSSNI01 error.""" - - # Plugin Errors class PluginError(Error): """Let's Encrypt Plugin error.""" diff --git a/letsencrypt/tests/acme_util.py b/letsencrypt/tests/acme_util.py index 71ebb471d..ea5438923 100644 --- a/letsencrypt/tests/acme_util.py +++ b/letsencrypt/tests/acme_util.py @@ -17,56 +17,14 @@ HTTP01 = challenges.HTTP01( TLSSNI01 = challenges.TLSSNI01( token=jose.b64decode(b"evaGxfADs6pSRb2LAv9IZf17Dt3juxGJyPCt92wrDoA")) DNS = challenges.DNS(token="17817c66b60ce2e4012dfad92657527a") -RECOVERY_CONTACT = challenges.RecoveryContact( - activation_url="https://example.ca/sendrecovery/a5bd99383fb0", - success_url="https://example.ca/confirmrecovery/bb1b9928932", - contact="c********n@example.com") -POP = challenges.ProofOfPossession( - alg="RS256", nonce=jose.b64decode("eET5udtV7aoX8Xl8gYiZIA"), - hints=challenges.ProofOfPossession.Hints( - jwk=jose.JWKRSA(key=KEY.public_key()), - cert_fingerprints=( - "93416768eb85e33adc4277f4c9acd63e7418fcfe", - "16d95b7b63f1972b980b14c20291f3c0d1855d95", - "48b46570d9fc6358108af43ad1649484def0debf" - ), - certs=(), # TODO - subject_key_identifiers=("d0083162dcc4c8a23ecb8aecbd86120e56fd24e5"), - serial_numbers=(34234239832, 23993939911, 17), - issuers=( - "C=US, O=SuperT LLC, CN=SuperTrustworthy Public CA", - "O=LessTrustworthy CA Inc, CN=LessTrustworthy But StillSecure", - ), - authorized_for=("www.example.com", "example.net"), - ) -) -CHALLENGES = [HTTP01, TLSSNI01, DNS, RECOVERY_CONTACT, POP] -DV_CHALLENGES = [chall for chall in CHALLENGES - if isinstance(chall, challenges.DVChallenge)] -CONT_CHALLENGES = [chall for chall in CHALLENGES - if isinstance(chall, challenges.ContinuityChallenge)] +CHALLENGES = [HTTP01, TLSSNI01, DNS] def gen_combos(challbs): """Generate natural combinations for challbs.""" - dv_chall = [] - cont_chall = [] - - for i, challb in enumerate(challbs): # pylint: disable=redefined-outer-name - if isinstance(challb.chall, challenges.DVChallenge): - dv_chall.append(i) - else: - cont_chall.append(i) - - if cont_chall: - # Gen combos for 1 of each type, lowest - # index included first (makes testing easier) - return tuple((i, j) if i < j else (j, i) - for i in dv_chall for j in cont_chall) - else: - # completing a single DV chall satisfies the CA - return tuple((i,) for i in dv_chall) + # completing a single DV challenge satisfies the CA + return tuple((i,) for i, _ in enumerate(challbs)) def chall_to_challb(chall, status): # pylint: disable=redefined-outer-name @@ -87,16 +45,8 @@ def chall_to_challb(chall, status): # pylint: disable=redefined-outer-name TLSSNI01_P = chall_to_challb(TLSSNI01, messages.STATUS_PENDING) HTTP01_P = chall_to_challb(HTTP01, messages.STATUS_PENDING) DNS_P = chall_to_challb(DNS, messages.STATUS_PENDING) -RECOVERY_CONTACT_P = chall_to_challb(RECOVERY_CONTACT, messages.STATUS_PENDING) -POP_P = chall_to_challb(POP, messages.STATUS_PENDING) -CHALLENGES_P = [HTTP01_P, TLSSNI01_P, DNS_P, RECOVERY_CONTACT_P, POP_P] -DV_CHALLENGES_P = [challb for challb in CHALLENGES_P - if isinstance(challb.chall, challenges.DVChallenge)] -CONT_CHALLENGES_P = [ - challb for challb in CHALLENGES_P - if isinstance(challb.chall, challenges.ContinuityChallenge) -] +CHALLENGES_P = [HTTP01_P, TLSSNI01_P, DNS_P] def gen_authzr(authz_status, domain, challs, statuses, combos=True): diff --git a/letsencrypt/tests/auth_handler_test.py b/letsencrypt/tests/auth_handler_test.py index dcf8a5ab3..426a269ac 100644 --- a/letsencrypt/tests/auth_handler_test.py +++ b/letsencrypt/tests/auth_handler_test.py @@ -35,10 +35,10 @@ class ChallengeFactoryTest(unittest.TestCase): self.dom, range(0, len(acme_util.CHALLENGES))) self.assertEqual( - [achall.chall for achall in achalls], acme_util.DV_CHALLENGES) + [achall.chall for achall in achalls], acme_util.CHALLENGES) def test_one_tls_sni(self): - achalls = self.handler._challenge_factory(self.dom, [1, 3]) + achalls = self.handler._challenge_factory(self.dom, [1]) self.assertEqual( [achall.chall for achall in achalls], [acme_util.TLSSNI01]) @@ -83,7 +83,7 @@ class GetAuthorizationsTest(unittest.TestCase): @mock.patch("letsencrypt.auth_handler.AuthHandler._poll_challenges") def test_name1_tls_sni_01_1(self, mock_poll): self.mock_net.request_domain_challenges.side_effect = functools.partial( - gen_dom_authzr, challs=acme_util.DV_CHALLENGES) + gen_dom_authzr, challs=acme_util.CHALLENGES) mock_poll.side_effect = self._validate_all @@ -106,7 +106,7 @@ class GetAuthorizationsTest(unittest.TestCase): @mock.patch("letsencrypt.auth_handler.AuthHandler._poll_challenges") def test_name1_tls_sni_01_1_http_01_1_dns_1(self, mock_poll): self.mock_net.request_domain_challenges.side_effect = functools.partial( - gen_dom_authzr, challs=acme_util.DV_CHALLENGES, combos=False) + gen_dom_authzr, challs=acme_util.CHALLENGES, combos=False) mock_poll.side_effect = self._validate_all self.mock_auth.get_chall_pref.return_value.append(challenges.HTTP01) @@ -131,7 +131,7 @@ class GetAuthorizationsTest(unittest.TestCase): @mock.patch("letsencrypt.auth_handler.AuthHandler._poll_challenges") def test_name3_tls_sni_01_3(self, mock_poll): self.mock_net.request_domain_challenges.side_effect = functools.partial( - gen_dom_authzr, challs=acme_util.DV_CHALLENGES) + gen_dom_authzr, challs=acme_util.CHALLENGES) mock_poll.side_effect = self._validate_all @@ -156,7 +156,7 @@ class GetAuthorizationsTest(unittest.TestCase): def test_perform_failure(self): self.mock_net.request_domain_challenges.side_effect = functools.partial( - gen_dom_authzr, challs=acme_util.DV_CHALLENGES) + gen_dom_authzr, challs=acme_util.CHALLENGES) self.mock_auth.perform.side_effect = errors.AuthorizationError self.assertRaises( @@ -189,15 +189,16 @@ class PollChallengesTest(unittest.TestCase): self.doms = ["0", "1", "2"] self.handler.authzr[self.doms[0]] = acme_util.gen_authzr( messages.STATUS_PENDING, self.doms[0], - acme_util.DV_CHALLENGES, [messages.STATUS_PENDING] * 3, False) + [acme_util.HTTP01, acme_util.TLSSNI01], + [messages.STATUS_PENDING] * 2, False) self.handler.authzr[self.doms[1]] = acme_util.gen_authzr( messages.STATUS_PENDING, self.doms[1], - acme_util.DV_CHALLENGES, [messages.STATUS_PENDING] * 3, False) + acme_util.CHALLENGES, [messages.STATUS_PENDING] * 3, False) self.handler.authzr[self.doms[2]] = acme_util.gen_authzr( messages.STATUS_PENDING, self.doms[2], - acme_util.DV_CHALLENGES, [messages.STATUS_PENDING] * 3, False) + acme_util.CHALLENGES, [messages.STATUS_PENDING] * 3, False) self.chall_update = {} for dom in self.doms: @@ -234,7 +235,7 @@ class PollChallengesTest(unittest.TestCase): from letsencrypt.auth_handler import challb_to_achall self.mock_net.poll.side_effect = self._mock_poll_solve_one_valid self.chall_update[self.doms[0]].append( - challb_to_achall(acme_util.RECOVERY_CONTACT_P, "key", self.doms[0])) + challb_to_achall(acme_util.DNS_P, "key", self.doms[0])) self.assertRaises( errors.AuthorizationError, self.handler._poll_challenges, self.chall_update, False) @@ -335,32 +336,8 @@ class GenChallengePathTest(unittest.TestCase): self.assertEqual(self._call(challbs[::-1], prefs, combos), (1,)) self.assertTrue(self._call(challbs[::-1], prefs, None)) - def test_common_case_with_continuity(self): - challbs = (acme_util.POP_P, - acme_util.RECOVERY_CONTACT_P, - acme_util.TLSSNI01_P, - acme_util.HTTP01_P) - prefs = [challenges.ProofOfPossession, challenges.TLSSNI01] - combos = acme_util.gen_combos(challbs) - self.assertEqual(self._call(challbs, prefs, combos), (0, 2)) - - def test_full_cont_server(self): - challbs = (acme_util.RECOVERY_CONTACT_P, - acme_util.POP_P, - acme_util.TLSSNI01_P, - acme_util.HTTP01_P, - acme_util.DNS_P) - # Typical webserver client that can do everything except DNS - # Attempted to make the order realistic - prefs = [challenges.ProofOfPossession, - challenges.HTTP01, - challenges.TLSSNI01, - challenges.RecoveryContact] - combos = acme_util.gen_combos(challbs) - self.assertEqual(self._call(challbs, prefs, combos), (1, 3)) - def test_not_supported(self): - challbs = (acme_util.POP_P, acme_util.TLSSNI01_P) + challbs = (acme_util.DNS_P, acme_util.TLSSNI01_P) prefs = [challenges.TLSSNI01] combos = ((0, 1),)