@@ -215,11 +215,12 @@ def get_host(self):
215
215
if server_port != (self .is_secure () and '443' or '80' ):
216
216
host = '%s:%s' % (host , server_port )
217
217
218
- # Disallow potentially poisoned hostnames.
219
- if not host_validation_re .match (host .lower ()):
220
- raise SuspiciousOperation ('Invalid HTTP_HOST header: %s' % host )
221
-
222
- return host
218
+ allowed_hosts = ['*' ] if settings .DEBUG else settings .ALLOWED_HOSTS
219
+ if validate_host (host , allowed_hosts ):
220
+ return host
221
+ else :
222
+ raise SuspiciousOperation (
223
+ "Invalid HTTP_HOST header (you may need to set ALLOWED_HOSTS): %s" % host )
223
224
224
225
def get_full_path (self ):
225
226
# RFC 3986 requires query string arguments to be in the ASCII range.
@@ -799,3 +800,43 @@ def str_to_unicode(s, encoding):
799
800
else :
800
801
return s
801
802
803
+ def validate_host (host , allowed_hosts ):
804
+ """
805
+ Validate the given host header value for this site.
806
+
807
+ Check that the host looks valid and matches a host or host pattern in the
808
+ given list of ``allowed_hosts``. Any pattern beginning with a period
809
+ matches a domain and all its subdomains (e.g. ``.example.com`` matches
810
+ ``example.com`` and any subdomain), ``*`` matches anything, and anything
811
+ else must match exactly.
812
+
813
+ Return ``True`` for a valid host, ``False`` otherwise.
814
+
815
+ """
816
+ # All validation is case-insensitive
817
+ host = host .lower ()
818
+
819
+ # Basic sanity check
820
+ if not host_validation_re .match (host ):
821
+ return False
822
+
823
+ # Validate only the domain part.
824
+ if host [- 1 ] == ']' :
825
+ # It's an IPv6 address without a port.
826
+ domain = host
827
+ else :
828
+ domain = host .rsplit (':' , 1 )[0 ]
829
+
830
+ for pattern in allowed_hosts :
831
+ pattern = pattern .lower ()
832
+ match = (
833
+ pattern == '*' or
834
+ pattern .startswith ('.' ) and (
835
+ domain .endswith (pattern ) or domain == pattern [1 :]
836
+ ) or
837
+ pattern == domain
838
+ )
839
+ if match :
840
+ return True
841
+
842
+ return False
0 commit comments