Commit c052699b authored by Claude Paroz's avatar Claude Paroz
Browse files

Fixed #20338 -- Stripped ending dot during host validation

Thanks manfre for the report and Timo Graham for the review.
parent 08c9ab5a
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -520,6 +520,8 @@ def validate_host(host, allowed_hosts):
    Return ``True`` for a valid host, ``False`` otherwise.

    """
    host = host[:-1] if host.endswith('.') else host

    for pattern in allowed_hosts:
        pattern = pattern.lower()
        match = (
+9 −5
Original line number Diff line number Diff line
@@ -79,18 +79,22 @@ responsible to provide your own validation of the ``Host`` header (perhaps in a
middleware; if so this middleware must be listed first in
:setting:`MIDDLEWARE_CLASSES`).

.. note::
.. versionchanged:: 1.7

    If you want to also allow the `fully qualified domain name (FQDN)`_, which
    some browsers can send in the Host header, you must explicitly add another
    ALLOWED_HOSTS entry that includes a trailing period. This entry can also be
    a subdomain wildcard::
    In previous versions of Django, if you wanted to also allow the
    `fully qualified domain name (FQDN)`_, which some browsers can send in the
    ``Host`` header, you had to explicitly add another ``ALLOWED_HOSTS`` entry
    that included a trailing period. This entry could also be a subdomain
    wildcard::

        ALLOWED_HOSTS = [
            '.example.com', # Allow domain and subdomains
            '.example.com.', # Also allow FQDN and subdomains
        ]

    In Django 1.7, the trailing dot is stripped when performing host validation,
    thus an entry with a trailing dot isn't required.

.. _`fully qualified domain name (FQDN)`: http://en.wikipedia.org/wiki/Fully_qualified_domain_name

If the ``Host`` header (or ``X-Forwarded-Host`` if
+3 −1
Original line number Diff line number Diff line
@@ -529,6 +529,8 @@ class HostValidationTests(SimpleTestCase):
            'anything.multitenant.com',
            'multitenant.com',
            'insensitive.com',
            'example.com.',
            'example.com.:80',
        ]

        for host in legit_hosts:
@@ -539,7 +541,7 @@ class HostValidationTests(SimpleTestCase):
            request.get_host()

        # Poisoned host headers are rejected as suspicious
        for host in chain(self.poisoned_hosts, ['other.com']):
        for host in chain(self.poisoned_hosts, ['other.com', 'example.com..']):
            with self.assertRaises(SuspiciousOperation):
                request = HttpRequest()
                request.META = {