Beispiel #1
0
    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}')
Beispiel #2
0
    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)
Beispiel #3
0
    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)
Beispiel #4
0
    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}")
Beispiel #5
0
    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)
Beispiel #6
0
 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)
Beispiel #7
0
    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
Beispiel #8
0
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)
Beispiel #9
0
 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)
Beispiel #10
0
    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
Beispiel #11
0
    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)
Beispiel #12
0
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()
Beispiel #13
0
    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}")
Beispiel #14
0
    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)
Beispiel #15
0
    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)
Beispiel #16
0
    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")
Beispiel #17
0
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, {}))
Beispiel #19
0
    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)