From eb99571a981e97e80f6c62b47ebd3e3a2a1d9a50 Mon Sep 17 00:00:00 2001 From: James Kasten Date: Mon, 22 Dec 2014 00:29:33 -0800 Subject: [PATCH] Use DVSNI_Chall namedtuple --- letsencrypt/client/apache/configurator.py | 44 +++++++++++------------ letsencrypt/client/client.py | 21 +++++++---- letsencrypt/scripts/main.py | 2 +- 3 files changed, 35 insertions(+), 32 deletions(-) diff --git a/letsencrypt/client/apache/configurator.py b/letsencrypt/client/apache/configurator.py index 2e2a02238..028157349 100644 --- a/letsencrypt/client/apache/configurator.py +++ b/letsencrypt/client/apache/configurator.py @@ -949,12 +949,14 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator): `chall_dict` composed of: - list_sni_tuple: - List of tuples with form `(name, r, nonce)`, where - `name` (`str`), `r` (base64 `str`), `nonce` (hex `str`) + `type`: `dvsni` (`str`) - dvsni_key: - DVSNI key (:class:`letsencrypt.client.client.Client.Key`) + `dvsni_chall`: + List of DVSNI_Chall namedtuples + (:class:`letsencrypt.client.client.Client.DVSNI_Chall`) + where DVSNI_Chall tuples have the following fields + `domain` (`str`), `r_b64` (base64 `str`), `nonce` (hex `str`) + `key` (:class:`letsencrypt.client.client.Client.Key`) :param dict chall_dict: dvsni challenge - see documentation @@ -964,18 +966,19 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator): self.save() # Do weak validation that challenge is of expected type - if not ("list_sni_tuple" in chall_dict and "dvsni_key" in chall_dict): + if "dvsni_chall" not in chall_dict: logging.fatal("Incorrect parameter given to Apache DVSNI challenge") logging.fatal("Chall dict: %s", chall_dict) sys.exit(1) addresses = [] default_addr = "*:443" - for tup in chall_dict["list_sni_tuple"]: - vhost = self.choose_virtual_host(tup[0]) + for chall in chall_dict["dvsni_chall"]: + vhost = self.choose_virtual_host(chall.domain) if vhost is None: logging.error( - "No vhost exists with servername or alias of: %s", tup[0]) + "No vhost exists with servername or alias of: %s", + chall.domain) logging.error("No _default_:443 vhost exists") logging.error("Please specify servernames in the Apache config") return None @@ -993,18 +996,16 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator): responses = [] # Create all of the challenge certs - for tup in chall_dict["list_sni_tuple"]: - cert_path = self.dvsni_get_cert_file(tup[2]) + for chall in chall_dict["dvsni_chall"]: + cert_path = self.dvsni_get_cert_file(chall.nonce) self.register_file_creation(cert_path) s_b64 = challenge_util.dvsni_gen_cert( - cert_path, tup[0], tup[1], tup[2], chall_dict["dvsni_key"]) + cert_path, chall.domain, chall.r_b64, chall.nonce, chall.key) responses.append({"type": "dvsni", "s": s_b64}) # Setup the configuration - self.dvsni_mod_config(chall_dict["list_sni_tuple"], - chall_dict["dvsni_key"], - addresses) + self.dvsni_mod_config(chall_dict["dvsni_chall"], addresses) # Save reversible changes and restart the server self.save("SNI Challenge", True) @@ -1019,18 +1020,13 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator): self.restart() # TODO: Variable names - def dvsni_mod_config(self, list_sni_tuple, dvsni_key, - ll_addrs): + def dvsni_mod_config(self, dvsni_chall, ll_addrs): """Modifies Apache config files to include challenge vhosts. Result: Apache config includes virtual servers for issued challs - :param list list_sni_tuple: list of tuples with the form - `(addr, y, nonce)`, where `addr` is `str`, `y` is `bytearray`, - and nonce is hex `str` - - :param dvsni_key: DVSNI key - :type dvsni_key: :class:`letsencrypt.client.client.Client.Key` + :param list dvsni_chall: list of + :class:`letsencrypt.client.client.Client.DVSNI_Chall` :param list ll_addrs: list of list of :class:`letsencrypt.client.apache.obj.Addr` to apply @@ -1052,7 +1048,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator): config_text = "\n" for idx, lis in enumerate(ll_addrs): config_text += self.get_config_text( - list_sni_tuple[idx][2], lis, dvsni_key.file) + dvsni_chall[idx].nonce, lis, dvsni_chall[idx].key.file) config_text += "\n" self.dvsni_conf_include_check(self.parser.loc["default"]) diff --git a/letsencrypt/client/client.py b/letsencrypt/client/client.py index 8c5f4525f..fdb8f542c 100644 --- a/letsencrypt/client/client.py +++ b/letsencrypt/client/client.py @@ -47,6 +47,7 @@ class Client(object): """ Key = collections.namedtuple("Key", "file pem") CSR = collections.namedtuple("CSR", "file data form") + DVSNI_Chall = collections.namedtuple("DVSNI_Chall", "domain, r_b64, nonce, key") def __init__(self, server, names, authkey, auth, installer): """Initialize a client.""" @@ -419,8 +420,9 @@ class Client(object): if chall["type"] == "dvsni": logging.info(" DVSNI challenge for name %s.", name) sni_satisfies.append(index) - sni_todo.append((str(name), str(chall["r"]), - str(chall["nonce"]))) + sni_todo.append(Client.DVSNI_Chall( + str(name), str(chall["r"]), + str(chall["nonce"]), self.authkey)) elif chall["type"] == "recoveryToken": logging.info("\tRecovery Token Challenge for name: %s.", name) @@ -438,8 +440,7 @@ class Client(object): # one "challenge object" is issued for all sni_challenges challenge_objs.append({ "type": "dvsni", - "list_sni_tuple": sni_todo, - "dvsni_key": self.authkey, + "dvsni_chall": sni_todo }) challenge_obj_indices.append(sni_satisfies) logging.debug(sni_todo) @@ -447,11 +448,17 @@ class Client(object): return challenge_objs, challenge_obj_indices -def validate_key_csr(privkey, csr, names): +def validate_key_csr(privkey, csr): """Validate CSR and key files. - Verifies that the client key and csr arguments are valid and - correspond to one another. + Verifies that the client key and csr arguments are valid and correspond to + one another. This does not currently check the names in the CSR. + + :param privkey: Key associated with CSR + :type privkey: :class:`letsencrypt.client.client.Client.Key` + + :param csr: CSR + :type csr: :class:`letsencrypt.client.client.Client.CSR` :raises LetsEncryptClientError: if validation fails diff --git a/letsencrypt/scripts/main.py b/letsencrypt/scripts/main.py index 8aeb43136..211525ed8 100755 --- a/letsencrypt/scripts/main.py +++ b/letsencrypt/scripts/main.py @@ -122,7 +122,7 @@ def main(): acme = client.Client(server, domains, privkey, auth, installer) # Validate the key and csr - client.validate_key_csr(privkey, csr, domains) + client.validate_key_csr(privkey, csr) cert_file, chain_file = acme.obtain_certificate(csr) vhost = acme.deploy_certificate(privkey, cert_file, chain_file)