diff --git a/letsencrypt/cli.py b/letsencrypt/cli.py index 2da82412d..a115acdbf 100644 --- a/letsencrypt/cli.py +++ b/letsencrypt/cli.py @@ -1295,8 +1295,6 @@ class WebrootPathProcessor(argparse.Action): # pylint: disable=missing-docstring config.webroot_path.append(webroot) -_undot = lambda domain: domain[:-1] if domain.endswith('.') else domain - def _process_domain(config, domain_arg, webroot_path=None): """ Process a new -d flag, helping the webroot plugin construct a map of @@ -1305,8 +1303,8 @@ def _process_domain(config, domain_arg, webroot_path=None): webroot_path = webroot_path if webroot_path else config.webroot_path for domain in (d.strip() for d in domain_arg.split(",")): + domain = enforce_domain_sanity(domain) if domain not in config.domains: - domain = _undot(domain) config.domains.append(domain) # Each domain has a webroot_path of the most recent -w flag # unless it was explicitly included in webroot_map diff --git a/letsencrypt/configuration.py b/letsencrypt/configuration.py index afd5edbe4..37eaba3bd 100644 --- a/letsencrypt/configuration.py +++ b/letsencrypt/configuration.py @@ -124,4 +124,5 @@ def check_config_sanity(config): # Domain checks if config.namespace.domains is not None: for domain in config.namespace.domains: - le_util.check_domain_sanity(domain) + # This may be redundant, but let's be paranoid + le_util.enforce_domain_sanity(domain) diff --git a/letsencrypt/display/ops.py b/letsencrypt/display/ops.py index b3c057301..f0dec8b06 100644 --- a/letsencrypt/display/ops.py +++ b/letsencrypt/display/ops.py @@ -239,8 +239,7 @@ def get_valid_domains(domains): valid_domains = [] for domain in domains: try: - le_util.check_domain_sanity(domain) - valid_domains.append(domain) + valid_domains.append(le_util.enforce_domain_sanity(domain)) except errors.ConfigurationError: continue return valid_domains @@ -282,9 +281,9 @@ def _choose_names_manually(): "supported.{0}{0}Would you like to re-enter the " "names?{0}").format(os.linesep) - for domain in domain_list: + for i, domain in enumerate(domain_list): try: - le_util.check_domain_sanity(domain) + domain_list[i] = le_util.enforce_domain_sanity(domain) except errors.ConfigurationError as e: invalid_domains[domain] = e.message diff --git a/letsencrypt/le_util.py b/letsencrypt/le_util.py index d97d43dc6..35793849e 100644 --- a/letsencrypt/le_util.py +++ b/letsencrypt/le_util.py @@ -285,15 +285,17 @@ def add_deprecated_argument(add_argument, argument_name, nargs): help=argparse.SUPPRESS, nargs=nargs) -def check_domain_sanity(domain): +def enforce_domain_sanity(domain): """Method which validates domain value and errors out if the requirements are not met. :param domain: Domain to check - :type domains: `string` + :type domains: `str` or `unicode` :raises ConfigurationError: for invalid domains and cases where Let's Encrypt currently will not issue certificates + :returns: The domain cast to `str`, with ASCII-only contents + :rtype: str """ # Check if there's a wildcard domain if domain.startswith("*."): @@ -306,12 +308,15 @@ def check_domain_sanity(domain): # Unicode try: - domain.encode('ascii') + domain = domain.encode('ascii') except UnicodeDecodeError: raise errors.ConfigurationError( "Internationalized domain names are not presently supported: {0}" .format(domain)) + # Remove trailing dot + domain = domain[:-1] if domain.endswith('.') else domain + # FQDN checks from # http://www.mkyong.com/regular-expressions/domain-name-regular-expression-example/ # Characters used, domain parts < 63 chars, tld > 1 < 64 chars @@ -319,3 +324,4 @@ def check_domain_sanity(domain): fqdn = re.compile("^((?!-)[A-Za-z0-9-]{1,63}(?