def process_request(self, request): host = self.get_host(request) domain, port = split_domain_port(host) if not domain: raise DisallowedHost(f'Invalid HTTP_HOST header: {host}.') request.host = domain request.port = int(port) if port else None request.uses_custom_domain = False event_slug = resolve(request.path).kwargs.get('event') if event_slug: event = get_object_or_404(Event, slug__iexact=event_slug) request.event = event if event.settings.custom_domain: custom_domain = urlparse(event.settings.custom_domain) event_domain, event_port = split_domain_port( custom_domain.netloc) if event_domain == domain and event_port == port: request.uses_custom_domain = True return default_domain, default_port = split_domain_port(settings.SITE_NETLOC) if domain == default_domain: return if settings.DEBUG or domain in LOCAL_HOST_NAMES: return raise DisallowedHost(f'Unknown host: {host}')
def process_request(self, request): # We try three options, in order of decreasing preference. if settings.USE_X_FORWARDED_HOST and ('X-Forwarded-Host' in request.headers): host = request.headers['X-Forwarded-Host'] elif 'Host' in request.headers: host = request.headers['Host'] else: # Reconstruct the host using the algorithm from PEP 333. host = request.META['SERVER_NAME'] server_port = str(request.META['SERVER_PORT']) if server_port != ('443' if request.is_secure() else '80'): host = '%s:%s' % (host, server_port) domain, port = split_domain_port(host) default_domain, default_port = split_domain_port( urlparse(settings.SITE_URL).netloc) request.port = int(port) if port else None request.host = domain if domain == default_domain: request.urlconf = "pretix.multidomain.maindomain_urlconf" elif domain: cached = cache.get('pretix_multidomain_instance_{}'.format(domain)) if cached is None: try: kd = KnownDomain.objects.select_related( 'organizer', 'event').get(domainname=domain) # noqa orga = kd.organizer event = kd.event except KnownDomain.DoesNotExist: orga = False event = False cache.set('pretix_multidomain_instance_{}'.format(domain), (orga, event), 3600) else: orga, event = cached if event: request.event_domain = True request.organizer = orga if isinstance( orga, Organizer) else Organizer.objects.get(pk=orga) request.event = event if isinstance( event, Event) else orga.events.get(pk=event) request.urlconf = "pretix.multidomain.event_domain_urlconf" elif orga: request.organizer_domain = True request.organizer = orga if isinstance( orga, Organizer) else Organizer.objects.get(pk=orga) request.urlconf = "pretix.multidomain.organizer_domain_urlconf" elif settings.DEBUG or domain in LOCAL_HOST_NAMES: request.urlconf = "pretix.multidomain.maindomain_urlconf" else: raise DisallowedHost("Unknown host: %r" % host) else: raise DisallowedHost("Invalid HTTP_HOST header: %r." % host) # We need to manually set the urlconf for the whole thread. Normally, Django's basic request handling # would do this for us, but we already need it in place for the other middlewares. set_urlconf(request.urlconf)
def process_request(self, request): # We try three options, in order of decreasing preference. if settings.USE_X_FORWARDED_HOST and ('HTTP_X_FORWARDED_HOST' in request.META): host = request.META['HTTP_X_FORWARDED_HOST'] elif 'HTTP_HOST' in request.META: host = request.META['HTTP_HOST'] else: # Reconstruct the host using the algorithm from PEP 333. host = request.META['SERVER_NAME'] server_port = str(request.META['SERVER_PORT']) if server_port != ('443' if request.is_secure() else '80'): host = '%s:%s' % (host, server_port) domain, port = split_domain_port(host) default_domain, default_port = split_domain_port(urlparse(settings.SITE_URL).netloc) if domain: request.host = domain request.port = int(port) if port else None try: kd = KnownDomain.objects.get(domainname=domain) # noqa request.domain = kd except: if settings.DEBUG or domain in LOCAL_HOST_NAMES or domain == default_domain: request.urlconf = "pretix.multidomain.maindomain_urlconf" else: raise DisallowedHost("Unknown host: %r" % host) else: request.organizer = kd.organizer request.urlconf = "pretix.multidomain.subdomain_urlconf" else: raise DisallowedHost("Invalid HTTP_HOST header: %r." % host) # We need to manually set the urlconf for the whole thread. Normally, Django's basic request # would do this for us, but we already need it in place for the other middlewares. set_urlconf(request.urlconf)
def process_request(self, request): host = self.get_host(request) domain, port = split_domain_port(host) request.host = domain request.port = int(port) if port else None request.uses_custom_domain = False resolved = resolve(request.path) if resolved.url_name in ANY_DOMAIN_ALLOWED or request.path.startswith( "/api/"): return None event_slug = resolved.kwargs.get("event") if event_slug: event = get_object_or_404(Event, slug__iexact=event_slug) request.event = event if event.settings.custom_domain: custom_domain = urlparse(event.settings.custom_domain) event_domain, event_port = split_domain_port( custom_domain.netloc) if event_domain == domain and event_port == port: request.uses_custom_domain = True return None default_domain, default_port = split_domain_port(settings.SITE_NETLOC) if domain == default_domain: return None if settings.DEBUG or domain in LOCAL_HOST_NAMES: return None if request.path.startswith("/orga"): if default_port not in (80, 443): default_domain = f"{default_domain}:{default_port}" return redirect(urljoin(default_domain, request.get_full_path())) raise DisallowedHost(f"Unknown host: {host}")
def get_host(self): """Returns the HTTP host using the environment or request headers.""" # We try three options, in order of decreasing preference. if settings.USE_X_FORWARDED_HOST and ('HTTP_X_FORWARDED_HOST' in self.META): host = self.META['HTTP_X_FORWARDED_HOST'] elif 'HTTP_HOST' in self.META: host = self.META['HTTP_HOST'] else: # Reconstruct the host using the algorithm from PEP 333. host = self.META['SERVER_NAME'] server_port = str(self.META['SERVER_PORT']) if server_port != ('443' if self.is_secure() else '80'): host = '%s:%s' % (host, server_port) # There is no hostname validation when DEBUG=True if settings.DEBUG: return host domain, port = split_domain_port(host) if domain and validate_host(domain, settings.ALLOWED_HOSTS): return host else: msg = "Invalid HTTP_HOST header: %r." % host if domain: msg += "You may need to add %r to ALLOWED_HOSTS." % domain else: msg += "The domain name provided is not valid according to RFC 1034/1035" raise DisallowedHost(msg)
def __call__(self, env): """ Before routing requests, make sure that host is equal to WARC_HOST. """ if settings.WARC_HOST and env.get('HTTP_HOST') != settings.WARC_HOST: raise DisallowedHost("Playback request used invalid domain.") return super(PermaRouter, self).__call__(env)
def process_request(self, request): host = request.get_host().lower() hostname, port = split_domain_port(host) if not hostname: raise DisallowedHost('Invalid hostname in HTTP request') require_exact_match = getattr( settings, 'SITEDATA_MIDDLEWARE_REQUIRE_EXACT_HOSTNAME', False) if validate_host(hostname, settings.ALLOWED_HOSTS): request.sitedata = SiteData( hostname=hostname, require_exact_match=require_exact_match) LOCAL.sitedata_ref = weakref.ref( request.sitedata) # allow sitedata to be accessed from LOCAL # overrides request.urlconf if specified if hasattr(request.sitedata, 'urlconf' ) and request.sitedata.urlconf is not settings.ROOT_URLCONF: request.urlconf = request.sitedata.urlconf # Monkey patches request._get_scheme() to return 'https' instead of 'http' if hasattr(request.sitedata, 'scheme') and request.sitedata.exact_match_found \ and request.sitedata.scheme is 'https': request._get_scheme = _get_scheme_https
def host_is_allowed(request): if '*' not in settings.DOCS_ALLOWED_HOSTS: if request.META.get('HTTP_X_FORWARDED_FOR'): ip = request.META['HTTP_X_FORWARDED_FOR'] else: ip = request.META['REMOTE_ADDR'] if ip not in settings.DOCS_ALLOWED_HOSTS: raise DisallowedHost( "You may need to add '%s' to DOCS_ALLOWED_HOSTS." % ip)
def docs_view(self, request, *args, **kwargs): if '*' not in settings.DJANGO_DOCS_ALLOWED_HOST: if request.META.get('HTTP_X_FORWARDED_FOR'): ip = request.META['HTTP_X_FORWARDED_FOR'] else: ip = request.META['REMOTE_ADDR'] if ip not in settings.DJANGO_DOCS_ALLOWED_HOST: raise DisallowedHost( "You may need to add '%s' to DOCS_ALLOWED_HOSTS." % ip) return func(self, request, *args, **kwargs)
def extract_data(self): try: payload = loads(self.token, max_age=timezone.timedelta(hours=8)) parent_user = self.parent_model.objects.get( user__email=payload['parent_email'], user__user_type=payload['parent_user_type']) except self.parent_model.DoesNotExist as e: raise PermissionDenied('Super user Does Not Exist') from e except SignatureExpired as e: raise DisallowedHost("Link is expired. Request a new link") from e return parent_user, payload
def process_request(self, request): host = request.get_host() if validate_host(host, ORIG_ALLOWED_HOSTS): return None for net in self.allowed_cidr_nets: try: if host in net: return None except AddrFormatError: # not an IP break raise DisallowedHost("Invalid HTTP_HOST header: %r." % host)
def check_ip(request): """Returns the IP of the request, accounting for the possibility of being behind a proxy. """ allowed_ip = settings.ALLOWED_BCCR_IP if allowed_ip: ip = request.META.get("HTTP_X_FORWARDED_FOR", None) if ip: # X_FORWARDED_FOR returns client1, proxy1, proxy2,... ip = ip.split(", ")[0] else: ip = request.META.get("REMOTE_ADDR", "") if ip not in allowed_ip: raise DisallowedHost()
def process_request(self, request): host = self.get_host(request) domain, port = split_domain_port(host) request.host = domain request.port = int(port) if port else None request.uses_custom_domain = False resolved = resolve(request.path) if resolved.url_name in ANY_DOMAIN_ALLOWED or request.path.startswith("/api/"): return None event_slug = resolved.kwargs.get("event") if event_slug: event = get_object_or_404(Event, slug__iexact=event_slug) request.event = event if event.settings.custom_domain: custom_domain = urlparse(event.settings.custom_domain) event_domain, event_port = split_domain_port(custom_domain.netloc) if event_domain == domain and event_port == port: request.uses_custom_domain = True return None default_domain, default_port = split_domain_port(settings.SITE_NETLOC) if domain == default_domain: return None if settings.DEBUG or domain in LOCAL_HOST_NAMES: return None if request.path.startswith("/orga"): # pragma: no cover if default_port not in (80, 443): default_domain = f"{default_domain}:{default_port}" return redirect(urljoin(default_domain, request.get_full_path())) # If this domain is used as custom domain, redirect to most recent event event_settings = Event_SettingsStore.objects.filter( Q(value=f"{request.scheme}://{domain}") | Q(value=f"{request.scheme}://{host}"), key="custom_domain", ) if event_settings: events = [s.object for s in event_settings if s.object.is_public] if events: events.sort(key=lambda x: x.date_from, reverse=True) return redirect(events[0].urls.base.full()) else: raise Http404() raise DisallowedHost(f"Unknown host: {host}")
def get_host(self): """Return the HTTP host using the environment or request headers.""" host = self._get_raw_host() # There is no hostname validation when DEBUG=True if settings.DEBUG: return host domain, port = split_domain_port(host) if domain and validate_host(domain, settings.ALLOWED_HOSTS): return host else: msg = "Invalid HTTP_HOST header: %r." % host if domain: msg += " You may need to add %r to ALLOWED_HOSTS." % domain else: msg += " The domain name provided is not valid according to RFC 1034/1035." raise DisallowedHost(msg)
def get_host(self): """Return the HTTP host using the environment or request headers.""" host = self._get_raw_host() # Allow variants of localhost if ALLOWED_HOSTS is empty and DEBUG=True. allowed_hosts = settings.ALLOWED_HOSTS if settings.DEBUG and not allowed_hosts: allowed_hosts = ['localhost', '127.0.0.1', '[::1]'] domain, port = split_domain_port(host) if domain and validate_host(domain, allowed_hosts): return host else: msg = "Invalid HTTP_HOST header: %r." % host if domain: msg += " You may need to add %r to ALLOWED_HOSTS." % domain else: msg += " The domain name provided is not valid according to RFC 1034/1035." raise DisallowedHost(msg)
def limit_by_origin(self, request): """ True if the inbound request comes from an allowed origin We're using `netaddr` here to turn our configuredCIDR notation strings into python objects so that we can easily test for membership """ # We're allowing all if explicitly configured if settings.TMS_WEBHOOK_ALLOWED_CIDR_NETS == ['*']: return True allowed_cidr_nets = [ IPNetwork(net) for net in settings.TMS_WEBHOOK_ALLOWED_CIDR_NETS ] ip = get_client_ip(request) for net in allowed_cidr_nets: if ip in net: return True raise DisallowedHost("Invalid HTTP_HOST header")
def suspicious_spec(request): raise DisallowedHost("dubious")
Http404(), ]) def test_rest_framework_exception(exception): """Ensure response returned by our and rest_framework handler are equal.""" rest_framework_response = rest_exception_handler(exception, {}) response = exception_handler(exception, {}) assert rest_framework_response assert response assert response.status_code == rest_framework_response.status_code assert set(response.items()) == set(rest_framework_response.items()) assert response.data == rest_framework_response.data @pytest.mark.parametrize( 'exception', [ Exception(), ValueError(), TypeError(), AssertionError(), # `django` exceptions DisallowedHost(), SuspiciousOperation(), ]) def test_other_exception(exception): """Ensure response returned by our and rest_framework handler are equal.""" assert (exception_handler(exception, {}) == rest_exception_handler(exception, {}))
def check_subdomain(self, request): global allowed_paths global account_login_url # Use a different set of routes depending on whether the request # is for q.govready.com (the special landing domain) or an # organization subdomain. # Get the hostname in the UA's original HTTP request. It may be # a HOST:PORT --- just take the HOST portion. request_host = request.get_host().split(":")[0] # When debugging, the Django runserver server uses this host. # But we can't do subdomains on that hostname. As a convenience, # redirect to "localhost". if settings.DEBUG and request_host == "127.0.0.1": return HttpResponseRedirect("http://localhost:" + request.get_port() + request.path) # What is our main landing domain? s = urlsplit(settings.SITE_ROOT_URL) main_landing_domain = s[1].split(":")[0] # Is this a request for our main landing domain? The main landing domain is not # used when the "single-organization" mode is used. if request_host == main_landing_domain and not settings.SINGLE_ORGANIZATION_KEY: # This is one of our recognized main domain names. We serve # a special set of URLs for our main domain landing pages. request.urlconf = 'siteapp.urls_landing' return None # continue with normal request processing elif request.path.startswith( "/api/") and settings.SINGLE_ORGANIZATION_KEY: # This is an API interaction. In multi-org configurations, the API # is served from the landing domain (and would be handled by this block's # first if conditional). In single-org configurations the URLconfs are # merged, that is OK becasue we then check the user # auth on even the landing pages. We have to skip that because API # auth is handled by the view. return None # continue with normal request processing elif request.path.startswith( "/admin/") and settings.SINGLE_ORGANIZATION_KEY: # In multi-org configurations, the Django admin is served from the landing domain # (and would be handled by this block's first if conditional). In single-org # configurations the URLconfs are merged. We can skip our authorization logic # for this pages because Django will handle it. return None # continue with normal request processing # Is this a request for an organization subdomain? elif request_host.endswith('.' + settings.ORGANIZATION_PARENT_DOMAIN ) or settings.SINGLE_ORGANIZATION_KEY: if not settings.SINGLE_ORGANIZATION_KEY: # Get the subdomain from the request host. subdomain = request_host[:-len(settings. ORGANIZATION_PARENT_DOMAIN) - 1] else: # The subdomain is fixed as the value of the setting. subdomain = settings.SINGLE_ORGANIZATION_KEY # Does this subdomain correspond with a known organization? org = Organization.objects.filter(subdomain=subdomain).first() if org: request.unauthenticated_organization_subdomain = org if request.user.is_authenticated and org.can_read( request.user): # This request is from an authenticated user who is # authorized to participate in the organization. # Set the Organiation on the request object. request.organization = org # Pre-load the user's settings task if the user is logged in, # so that we have global access to it. request.user.localize_to_org(request.organization) # Continue with normal request processing. return None # The user isn't a participant in the organization but we may # still reveal which org this is if... # The invitation acceptance URL must be accessible while logged in # but not yet a member of the organization. elif request.path.startswith("/invitation/accept/"): # Allow this through, revealing which org this is. request.organization = org return None # The HTTP host did not match a domain we can serve. else: from django.core.exceptions import DisallowedHost import json parent_domain = ".".join(request_host.split( ".")[1:]) or "<not applicable, domain has no parent>" raise DisallowedHost(( "You've requested a page at %s but this instance has been configured to only serve pages at '%s' and '*.%s'. " + "To serve pages on this domain, edit your local/environment.json and set the 'host' key to %s or set the 'organization-parent-domain' " + "key to %s.") % (request_host, main_landing_domain, settings.ORGANIZATION_PARENT_DOMAIN, json.dumps(request.get_host()), json.dumps(parent_domain))) # The user is not authenticated to see the organization subdomain page they requested. # Log the user out. Otherwise the login page redirects to the home page, and then we # get back here and redirect to the login page, infinitely. if request.user.is_authenticated: import logging logger = logging.getLogger(__name__) logger.error( "invalidorg subdomain={subdomain} ip={ip} username={username}". format(subdomain=subdomain, ip=request.META.get("REMOTE_ADDR"), username=request.POST.get("username"))) from django.contrib.auth import logout from django.contrib import messages logout(request) if settings.SINGLE_ORGANIZATION_KEY: messages.add_message( request, messages.ERROR, 'You have not been granted access to this site.') else: messages.add_message( request, messages.ERROR, 'You are not a member of this organization.') # The user isn't authenticated to see inside the organization subdomain, but # we have to allow them to log in, sign up, and reset their password (both # submitting the form and then hitting the email confirmation link). Build # a white list of allowed URL patterns by reversing the known URL names # from allauth/account/urls.py. Because account_reset_password_from_key has # URL parameters, turn the reverse'd URLs into regular expressions to match # against. if allowed_paths == None: import re allowed_paths = [reverse("homepage")] if 'django.contrib.auth.backends.ModelBackend' in settings.AUTHENTICATION_BACKENDS: allowed_paths += [ reverse("account_login"), reverse("account_signup"), reverse("account_reset_password"), reverse("account_reset_password_done"), reverse("account_reset_password_from_key", kwargs={ "uidb36": "aaaaaaaa", "key": "aaaaaaaa" }), reverse("account_reset_password_from_key_done") ] allowed_paths = re.compile("|".join( ("^" + re.escape(path).replace("aaaaaaaa", ".+") + "$") for path in allowed_paths)) if allowed_paths.match(request.path): # Don't leak any organization information, unless this deployment # allows leaking on login pages. if org and settings.REVEAL_ORGS_TO_ANON_USERS: request.organization = org # Render the page --- including the POST routes. return None # Do the reverse once. if account_login_url is None: account_login_url = reverse("homepage") # The user is not authenticated on this domain, is logged out, and is requesting # a path besides login/signup. Redirect to the login route. qs = "" if request.path not in (account_login_url, settings.LOGIN_REDIRECT_URL): qs = "?" + urlencode({"next": request.path}) return HttpResponseRedirect(account_login_url + qs)