From b68c5ace0c50a16af482be8e901102c5d7a3bfdc Mon Sep 17 00:00:00 2001 From: TheNavigat Date: Wed, 3 Feb 2016 11:54:39 +0200 Subject: [PATCH] Creating CSR after auth --- letsencrypt/auth_handler.py | 32 +++++++++++++++++++++++++------- letsencrypt/client.py | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 56 insertions(+), 9 deletions(-) diff --git a/letsencrypt/auth_handler.py b/letsencrypt/auth_handler.py index ffbd70ced..94cf8639c 100644 --- a/letsencrypt/auth_handler.py +++ b/letsencrypt/auth_handler.py @@ -42,6 +42,7 @@ class AuthHandler(object): form of :class:`letsencrypt.achallenges.AnnotatedChallenge` """ + def __init__(self, dv_auth, cont_auth, acme, account): self.dv_auth = dv_auth self.cont_auth = cont_auth @@ -75,19 +76,32 @@ class AuthHandler(object): self._choose_challenges(domains) + failed_domains = set() + # While there are still challenges remaining... while self.dv_c or self.cont_c: cont_resp, dv_resp = self._solve_challenges() logger.info("Waiting for verification...") # Send all Responses - this modifies dv_c and cont_c - self._respond(cont_resp, dv_resp, best_effort) + response = self._respond(cont_resp, dv_resp, best_effort) + + if response: + failed_domains = failed_domains.union(response) + + my_authzr = self.authzr + + returnDomains = set() + #Remove failing domains if best_effort is true + for domain in domains: + if not domain in failed_domains: + returnDomains.add(domain) # Just make sure all decisions are complete. self.verify_authzr_complete() # Only return valid authorizations - return [authzr for authzr in self.authzr.values() - if authzr.body.status == messages.STATUS_VALID] + return ([authzr for authzr in my_authzr.values() + if authzr.body.status == messages.STATUS_VALID], returnDomains) def _choose_challenges(self, domains): """Retrieve necessary challenges to satisfy server.""" @@ -139,11 +153,13 @@ class AuthHandler(object): # Check for updated status... try: - self._poll_challenges(chall_update, best_effort) + result = self._poll_challenges(chall_update, best_effort) finally: # This removes challenges from self.dv_c and self.cont_c self._cleanup_challenges(active_achalls) + return result + def _send_responses(self, achalls, resps, chall_update): """Send responses and make sure errors are handled. @@ -175,6 +191,7 @@ class AuthHandler(object): """Wait for all challenge results to be determined.""" dom_to_check = set(chall_update.keys()) comp_domains = set() + failed_domains = set() rounds = 0 while dom_to_check and rounds < max_rounds: @@ -192,9 +209,8 @@ class AuthHandler(object): chall_update[domain].remove(achall) # We failed some challenges... damage control else: - # Right now... just assume a loss and carry on... if best_effort: - comp_domains.add(domain) + failed_domains.add(domain) else: all_failed_achalls.update( updated for _, updated in failed_achalls) @@ -203,10 +219,12 @@ class AuthHandler(object): _report_failed_challs(all_failed_achalls) raise errors.FailedChallenges(all_failed_achalls) - dom_to_check -= comp_domains + dom_to_check -= comp_domains.union(failed_domains) comp_domains.clear() rounds += 1 + return failed_domains + def _handle_check(self, domain, achalls): """Returns tuple of ('completed', 'failed').""" completed = [] diff --git a/letsencrypt/client.py b/letsencrypt/client.py index 06a09257a..928249caa 100644 --- a/letsencrypt/client.py +++ b/letsencrypt/client.py @@ -195,7 +195,7 @@ class Client(object): else: self.auth_handler = None - def obtain_certificate_from_csr(self, domains, csr, + def _obtain_certificate(self, domains, csr, authzr, typ=OpenSSL.crypto.FILETYPE_ASN1): """Obtain certificate. @@ -222,13 +222,35 @@ class Client(object): logger.debug("CSR: %s, domains: %s", csr, domains) - authzr = self.auth_handler.get_authorizations(domains, self.config.allow_subset_of_names) certr = self.acme.request_issuance( jose.ComparableX509( OpenSSL.crypto.load_certificate_request(typ, csr.data)), authzr) return certr, self.acme.fetch_chain(certr) +<<<<<<< HEAD +======= + def obtain_certificate_from_csr(self, csr): + """Obtain certficiate from CSR. + + :param .le_util.CSR csr: DER-encoded Certificate Signing + Request. + + :returns: `.CertificateResource` and certificate chain (as + returned by `.fetch_chain`). + :rtype: tuple + + """ + domains = crypto_util.get_sans_from_csr( + csr.data, OpenSSL.crypto.FILETYPE_ASN1) + + authzr, domains = self.auth_handler.get_authorizations(domains, + self.config.allow_subset_of_names) + + return self._obtain_certificate( + # TODO: add CN to domains? + domains, csr, authzr) +>>>>>>> Creating CSR after auth def obtain_certificate(self, domains): """Obtains a certificate from the ACME server. @@ -244,12 +266,19 @@ class Client(object): :rtype: tuple """ + authzr, domains = self.auth_handler.get_authorizations(domains, + self.config.allow_subset_of_names) + # Create CSR from names key = crypto_util.init_save_key( self.config.rsa_key_size, self.config.key_dir) csr = crypto_util.init_save_csr(key, domains, self.config.csr_dir) +<<<<<<< HEAD return self.obtain_certificate_from_csr(domains, csr) + (key, csr) +======= + return self._obtain_certificate(domains, csr, authzr) + (key, csr) +>>>>>>> Creating CSR after auth def obtain_and_enroll_certificate(self, domains): """Obtain and enroll certificate.