mirror of
https://github.com/certbot/certbot.git
synced 2025-12-18 21:46:05 -05:00
Merge pull request #10519 from jsha/dedupe-enforce-domain-sanity
De-duplicate enforce_domain_sanity
This commit is contained in:
parent
fb3e95e372
commit
17a1f0e114
4 changed files with 4 additions and 100 deletions
|
|
@ -6,7 +6,7 @@ from typing import Any, Iterable
|
|||
from acme import crypto_util as acme_crypto_util
|
||||
from cryptography import x509
|
||||
|
||||
from certbot import errors
|
||||
from certbot.util import enforce_domain_sanity
|
||||
|
||||
class SAN:
|
||||
"""A domain or IP address.
|
||||
|
|
@ -27,49 +27,7 @@ class DNSName(SAN):
|
|||
def __init__(self, dns_name: str) -> None:
|
||||
if not isinstance(dns_name, str):
|
||||
raise TypeError("tried to initialize DNSName with non-str")
|
||||
try:
|
||||
dns_name.encode('ascii')
|
||||
except UnicodeError:
|
||||
raise errors.ConfigurationError("Non-ASCII domain names not supported. "
|
||||
"To issue for an Internationalized Domain Name, use Punycode.")
|
||||
dns_name = dns_name.lower()
|
||||
# Remove trailing dot
|
||||
dns_name = dns_name.removesuffix(".")
|
||||
|
||||
# Separately check for odd "domains" like "http://example.com" to fail
|
||||
# fast and provide a clear error message
|
||||
for scheme in ["http", "https"]: # Other schemes seem unlikely
|
||||
if dns_name.startswith("{0}://".format(scheme)):
|
||||
raise errors.ConfigurationError(
|
||||
"Requested name {0} appears to be a URL, not a FQDN. "
|
||||
"Try again without the leading \"{1}://\".".format(
|
||||
dns_name, scheme
|
||||
)
|
||||
)
|
||||
|
||||
try:
|
||||
IPAddress(dns_name)
|
||||
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(dns_name))
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# FQDN checks according to RFC 2181: domain name should be less than 255
|
||||
# octets (inclusive). And each label is 1 - 63 octets (inclusive).
|
||||
# https://tools.ietf.org/html/rfc2181#section-11
|
||||
msg = "Requested domain {0} is not a FQDN because".format(dns_name)
|
||||
if len(dns_name) > 255:
|
||||
raise errors.ConfigurationError("{0} it is too long.".format(msg))
|
||||
labels = dns_name.split('.')
|
||||
for l in labels:
|
||||
if not l:
|
||||
raise errors.ConfigurationError("{0} it contains an empty label.".format(msg))
|
||||
if len(l) > 63:
|
||||
raise errors.ConfigurationError("{0} label {1} is too long.".format(msg, l))
|
||||
|
||||
self.dns_name = dns_name
|
||||
self.dns_name = enforce_domain_sanity(dns_name)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.dns_name
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ from cryptography.x509.oid import NameOID
|
|||
from cryptography.hazmat.primitives import hashes
|
||||
from cryptography.hazmat.primitives.asymmetric import ec
|
||||
|
||||
from certbot import errors
|
||||
from certbot._internal import san
|
||||
|
||||
class SanTest(unittest.TestCase):
|
||||
|
|
@ -66,58 +65,6 @@ class SanTest(unittest.TestCase):
|
|||
with pytest.raises(ValueError):
|
||||
san.IPAddress("example.com")
|
||||
|
||||
class EnforceDomainSyntaxTest(unittest.TestCase):
|
||||
"""Test validation of domain names."""
|
||||
def _call(self, dns_name: str) -> None:
|
||||
san.DNSName(dns_name)
|
||||
|
||||
def test_nonascii_str(self) -> None:
|
||||
with pytest.raises(errors.ConfigurationError):
|
||||
self._call("eichh\u00f6rnchen.example.com")
|
||||
|
||||
def test_too_long(self) -> None:
|
||||
long_domain = "a"*256
|
||||
with pytest.raises(errors.ConfigurationError):
|
||||
self._call(long_domain)
|
||||
|
||||
def test_not_too_long(self) -> None:
|
||||
not_too_long_domain = "{0}.{1}.{2}.{3}".format("a"*63, "b"*63, "c"*63, "d"*63)
|
||||
self._call(not_too_long_domain)
|
||||
|
||||
def test_empty_label(self) -> None:
|
||||
empty_label_domain = "fizz..example.com"
|
||||
with pytest.raises(errors.ConfigurationError):
|
||||
self._call(empty_label_domain)
|
||||
|
||||
def test_empty_trailing_label(self) -> None:
|
||||
empty_trailing_label_domain = "example.com.."
|
||||
with pytest.raises(errors.ConfigurationError):
|
||||
self._call(empty_trailing_label_domain)
|
||||
|
||||
def test_long_label_1(self) -> None:
|
||||
long_label_domain = "a"*64
|
||||
with pytest.raises(errors.ConfigurationError):
|
||||
self._call(long_label_domain)
|
||||
|
||||
def test_long_label_2(self) -> None:
|
||||
long_label_domain = "{0}.{1}.com".format("a"*64, "b"*63)
|
||||
with pytest.raises(errors.ConfigurationError):
|
||||
self._call(long_label_domain)
|
||||
|
||||
def test_not_long_label(self) -> None:
|
||||
not_too_long_label_domain = "{0}.{1}.com".format("a"*63, "b"*63)
|
||||
self._call(not_too_long_label_domain)
|
||||
|
||||
def test_empty_domain(self) -> None:
|
||||
empty_domain = ""
|
||||
with pytest.raises(errors.ConfigurationError):
|
||||
self._call(empty_domain)
|
||||
|
||||
def test_punycode_ok(self) -> None:
|
||||
# Punycode is now legal, so no longer an error; instead check
|
||||
# that it's _not_ an error (at the initial sanity check stage)
|
||||
self._call('this.is.xn--ls8h.tld')
|
||||
|
||||
class FromX509Test(unittest.TestCase):
|
||||
def test_csr(self) -> None:
|
||||
key = ec.generate_private_key(ec.SECP256R1())
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ import configargparse
|
|||
from certbot import errors
|
||||
from certbot._internal import constants
|
||||
from certbot._internal import lock
|
||||
from certbot._internal import san
|
||||
from certbot.compat import filesystem
|
||||
from certbot.compat import os
|
||||
|
||||
|
|
@ -577,8 +576,7 @@ def enforce_le_validity(domain: str) -> str:
|
|||
|
||||
"""
|
||||
|
||||
# Do basic validation on a DNSName
|
||||
domain = san.DNSName(domain).dns_name
|
||||
domain = enforce_domain_sanity(domain)
|
||||
if not re.match("^[A-Za-z0-9.-]*$", domain):
|
||||
raise errors.ConfigurationError(
|
||||
"{0} contains an invalid character. "
|
||||
|
|
|
|||
1
newsfragments/10519.changed
Normal file
1
newsfragments/10519.changed
Normal file
|
|
@ -0,0 +1 @@
|
|||
san.DNSName now calls util.enforce_domain_sanity to reduce code duplication
|
||||
Loading…
Reference in a new issue