diff --git a/letsencrypt/le_util.py b/letsencrypt/le_util.py index 527c9bdae..c8a9d24c2 100644 --- a/letsencrypt/le_util.py +++ b/letsencrypt/le_util.py @@ -6,6 +6,7 @@ import logging import os import platform import re +import socket import stat import subprocess import sys @@ -317,6 +318,18 @@ def enforce_domain_sanity(domain): # Remove trailing dot domain = domain[:-1] if domain.endswith('.') else domain + # Explain separately that IP addresses aren't allowed (apart from not + # being FQDNs) because hope springs eternal concerning this point + try: + socket.inet_aton(domain) + raise errors.ConfigurationError( + "Requested name {0} is an IP address. The Let's Encrypt " + "certificate authority will not issue certificates for a " + "bare IP address.".format(domain)) + except socket.error: + # It wasn't an IP address, so that's good + pass + # FQDN checks from # http://www.mkyong.com/regular-expressions/domain-name-regular-expression-example/ # Characters used, domain parts < 63 chars, tld > 1 < 64 chars diff --git a/letsencrypt/tests/cli_test.py b/letsencrypt/tests/cli_test.py index 8184a557e..77a4b5892 100644 --- a/letsencrypt/tests/cli_test.py +++ b/letsencrypt/tests/cli_test.py @@ -351,6 +351,11 @@ class CLITest(unittest.TestCase): # pylint: disable=too-many-public-methods self._call, ['-d', '*.wildcard.tld']) + # Bare IP address (this is actually a different error message now) + self.assertRaises(errors.ConfigurationError, + self._call, + ['-d', '204.11.231.35']) + def _get_argument_parser(self): plugins = disco.PluginsRegistry.find_all() return functools.partial(cli.prepare_and_parse_args, plugins)