1
0
mirror of https://github.com/certbot/certbot.git synced 2026-01-23 07:20:55 +03:00

Adjust achallanges to be used with ChallengeBody

This commit is contained in:
Jakub Warmuz
2015-04-14 13:40:56 +00:00
parent 1672e07b2c
commit fc52600c4d
2 changed files with 44 additions and 39 deletions

View File

@@ -1,17 +1,20 @@
"""Client annotated ACME challenges.
Please use names such as ``achall`` to distiguish from variables "of type"
:class:`letsencrypt.acme.challenges.Challenge` (denoted by ``chall``)::
:class:`letsencrypt.acme.challenges.Challenge` (denoted by ``chall``)
and :class:`.ChallengeBody` (denoted by ``challb``)::
from letsencrypt.acme import challenges
from letsencrypt.acme import messages2
from letsencrypt.client import achallenges
chall = challenges.DNS(token='foo')
achall = achallenges.DNS(chall=chall, domain='example.com')
challb = messages2.ChallengeBody(chall=chall)
achall = achallenges.DNS(chall=challb, domain='example.com')
Note, that all annotated challenges act as a proxy objects::
achall.token == chall.token
achall.token == challb.token
"""
from letsencrypt.acme import challenges
@@ -29,19 +32,19 @@ class AnnotatedChallenge(jose_util.ImmutableMap):
Wraps around server provided challenge and annotates with data
useful for the client.
:ivar chall: Wrapped `~.ChallengeBody` (or just `~.challenges.Challenge`).
:ivar challb: Wrapped `~.ChallengeBody`.
"""
__slots__ = ('chall',)
__slots__ = ('challb',)
acme_type = NotImplemented
def __getattr__(self, name):
return getattr(self.chall, name)
return getattr(self.challb, name)
class DVSNI(AnnotatedChallenge):
"""Client annotated "dvsni" ACME challenge."""
__slots__ = ('chall', 'domain', 'key')
__slots__ = ('challb', 'domain', 'key')
acme_type = challenges.DVSNI
def gen_cert_and_response(self, s=None): # pylint: disable=invalid-name
@@ -55,35 +58,35 @@ class DVSNI(AnnotatedChallenge):
"""
response = challenges.DVSNIResponse(s=s)
cert_pem = crypto_util.make_ss_cert(self.key.pem, [
self.nonce_domain, self.domain, response.z_domain(self.chall)])
self.nonce_domain, self.domain, response.z_domain(self.challb)])
return cert_pem, response
class SimpleHTTPS(AnnotatedChallenge):
"""Client annotated "simpleHttps" ACME challenge."""
__slots__ = ('chall', 'domain', 'key')
__slots__ = ('challb', 'domain', 'key')
acme_type = challenges.SimpleHTTPS
class DNS(AnnotatedChallenge):
"""Client annotated "dns" ACME challenge."""
__slots__ = ('chall', 'domain')
__slots__ = ('challb', 'domain')
acme_type = challenges.DNS
class RecoveryContact(AnnotatedChallenge):
"""Client annotated "recoveryContact" ACME challenge."""
__slots__ = ('chall', 'domain')
__slots__ = ('challb', 'domain')
acme_type = challenges.RecoveryContact
class RecoveryToken(AnnotatedChallenge):
"""Client annotated "recoveryToken" ACME challenge."""
__slots__ = ('chall', 'domain')
__slots__ = ('challb', 'domain')
acme_type = challenges.RecoveryToken
class ProofOfPossession(AnnotatedChallenge):
"""Client annotated "proofOfPossession" ACME challenge."""
__slots__ = ('chall', 'domain')
__slots__ = ('challb', 'domain')
acme_type = challenges.ProofOfPossession

View File

@@ -138,7 +138,7 @@ class AuthHandler(object): # pylint: disable=too-many-instance-attributes
for achall, resp in itertools.izip(achalls, resps):
# Don't send challenges for None and False authenticator responses
if resp:
challr = self.network.answer_challenge(achall.chall, resp)
challr = self.network.answer_challenge(achall.challb, resp)
if achall.domain in chall_update:
chall_update[achall.domain].append(achall)
else:
@@ -267,31 +267,32 @@ class AuthHandler(object): # pylint: disable=too-many-instance-attributes
cont_chall = set()
for index in path:
chall = self.authzr[domain].body.challenges[index]
challb = self.authzr[domain].body.challenges[index]
chall = challb.chall
if isinstance(chall, challenges.DVSNI):
logging.info(" DVSNI challenge for %s.", domain)
achall = achallenges.DVSNI(
chall=chall, domain=domain, key=self.authkey)
challb=challb, domain=domain, key=self.authkey)
elif isinstance(chall, challenges.SimpleHTTPS):
logging.info(" SimpleHTTPS challenge for %s.", domain)
achall = achallenges.SimpleHTTPS(
chall=chall, domain=domain, key=self.authkey)
challb=challb, domain=domain, key=self.authkey)
elif isinstance(chall, challenges.DNS):
logging.info(" DNS challenge for %s.", domain)
achall = achallenges.DNS(chall=chall, domain=domain)
achall = achallenges.DNS(challb=challb, domain=domain)
elif isinstance(chall, challenges.RecoveryToken):
logging.info(" Recovery Token Challenge for %s.", domain)
achall = achallenges.RecoveryToken(chall=chall, domain=domain)
achall = achallenges.RecoveryToken(challb=challb, domain=domain)
elif isinstance(chall, challenges.RecoveryContact):
logging.info(" Recovery Contact Challenge for %s.", domain)
achall = achallenges.RecoveryContact(
chall=chall, domain=domain)
challb=challb, domain=domain)
elif isinstance(chall, challenges.ProofOfPossession):
logging.info(" Proof-of-Possession Challenge for %s", domain)
achall = achallenges.ProofOfPossession(
chall=chall, domain=domain)
challb=challb, domain=domain)
else:
raise errors.LetsEncryptClientError(
@@ -306,15 +307,15 @@ class AuthHandler(object): # pylint: disable=too-many-instance-attributes
return dv_chall, cont_chall
def gen_challenge_path(challs, preferences, combinations):
def gen_challenge_path(challbs, preferences, combinations):
"""Generate a plan to get authority over the identity.
.. todo:: This can be possibly be rewritten to use resolved_combinations.
:param tuple challs: A tuple of challenges
(:class:`letsencrypt.acme.challenges.Challenge`) from
:class:`letsencrypt.acme.messages.Challenge` server message to
be fulfilled by the client in order to prove possession of the
:param tuple challbs: A tuple of challenges
(:class:`letsencrypt.acme.messages2.Challenge`) from
:class:`letsencrypt.acme.messages2.AuthorizationResource` to be
fulfilled by the client in order to prove possession of the
identifier.
:param list preferences: List of challenge preferences for domain
@@ -333,12 +334,12 @@ def gen_challenge_path(challs, preferences, combinations):
"""
if combinations:
return _find_smart_path(challs, preferences, combinations)
return _find_smart_path(challbs, preferences, combinations)
else:
return _find_dumb_path(challs, preferences)
return _find_dumb_path(challbs, preferences)
def _find_smart_path(challs, preferences, combinations):
def _find_smart_path(challbs, preferences, combinations):
"""Find challenge path with server hints.
Can be called if combinations is included. Function uses a simple
@@ -360,8 +361,8 @@ def _find_smart_path(challs, preferences, combinations):
combo_total = 0
for combo in combinations:
for challenge_index in combo:
combo_total += chall_cost.get(challs[
challenge_index].__class__, max_cost)
combo_total += chall_cost.get(challbs[
challenge_index].chall.__class__, max_cost)
if combo_total < best_combo_cost:
best_combo = combo
@@ -378,7 +379,7 @@ def _find_smart_path(challs, preferences, combinations):
return best_combo
def _find_dumb_path(challs, preferences):
def _find_dumb_path(challbs, preferences):
"""Find challenge path without server hints.
Should be called if the combinations hint is not included by the
@@ -391,11 +392,11 @@ def _find_dumb_path(challs, preferences):
path = []
satisfied = set()
for pref_c in preferences:
for i, offered_chall in enumerate(challs):
if (isinstance(offered_chall, pref_c) and
is_preferred(offered_chall, satisfied)):
for i, offered_challb in enumerate(challbs):
if (isinstance(offered_challb.chall, pref_c) and
is_preferred(offered_challb, satisfied)):
path.append(i)
satisfied.add(offered_chall)
satisfied.add(offered_challb)
return path
@@ -415,11 +416,12 @@ def mutually_exclusive(obj1, obj2, groups, different=False):
return True
def is_preferred(offered_chall, satisfied,
def is_preferred(offered_challb, satisfied,
exclusive_groups=constants.EXCLUSIVE_CHALLENGES):
"""Return whether or not the challenge is preferred in path."""
for chall in satisfied:
for challb in satisfied:
if not mutually_exclusive(
offered_chall, chall, exclusive_groups, different=True):
offered_challb.chall, challb.chall, exclusive_groups,
different=True):
return False
return True