Пример #1
0
 def test_same_origin_true(self):
     # Identical
     self.assertTrue(http.same_origin('http://foo.com/', 'http://foo.com/'))
     # One with trailing slash - see #15617
     self.assertTrue(http.same_origin('http://foo.com', 'http://foo.com/'))
     self.assertTrue(http.same_origin('http://foo.com/', 'http://foo.com'))
     # With port
     self.assertTrue(http.same_origin('https://foo.com:8000', 'https://foo.com:8000/'))
Пример #2
0
 def test_same_origin_true(self):
     # Identical
     self.assertTrue(http.same_origin('http://foo.com/', 'http://foo.com/'))
     # One with trailing slash - see #15617
     self.assertTrue(http.same_origin('http://foo.com', 'http://foo.com/'))
     self.assertTrue(http.same_origin('http://foo.com/', 'http://foo.com'))
     # With port
     self.assertTrue(http.same_origin('https://foo.com:8000', 'https://foo.com:8000/'))
Пример #3
0
 def test_same_origin_false(self):
     # Different scheme
     self.assertFalse(http.same_origin('http://foo.com', 'https://foo.com'))
     # Different host
     self.assertFalse(http.same_origin('http://foo.com', 'http://goo.com'))
     # Different host again
     self.assertFalse(http.same_origin('http://foo.com', 'http://foo.com.evil.com'))
     # Different port
     self.assertFalse(http.same_origin('http://foo.com:8000', 'http://foo.com:8001'))
Пример #4
0
 def test_same_origin_false(self):
     # Different scheme
     self.assertFalse(http.same_origin('http://foo.com', 'https://foo.com'))
     # Different host
     self.assertFalse(http.same_origin('http://foo.com', 'http://goo.com'))
     # Different host again
     self.assertFalse(http.same_origin('http://foo.com', 'http://foo.com.evil.com'))
     # Different port
     self.assertFalse(http.same_origin('http://foo.com:8000', 'http://foo.com:8001'))
Пример #5
0
    def is_authenticated(self, request, **kwargs):
        """
        """

        # this is the line i have to override in order to get
        # POST request to successfully authenticate ##
        if request.method in ("GET", "POST", "DELETE"):
            return request.user.is_authenticated()

        if getattr(request, "_dont_enforce_csrf_checks", False):
            return request.user.is_authenticated()

        csrf_token = _sanitize_token(request.COOKIES.get(settings.CSRF_COOKIE_NAME, ""))

        if request.is_secure():
            referer = request.META.get("HTTP_REFERER")

            if referer is None:
                return False

            good_referer = "https://%s/" % request.get_host()

            if not same_origin(referer, good_referer):
                return False

        request_csrf_token = request.META.get("HTTP_X_CSRFTOKEN", "")

        if not constant_time_compare(request_csrf_token, csrf_token):
            return False

        return request.user.is_authenticated()
Пример #6
0
def get_audience(request):
    """
    Determine the audience to use for verification from the given request.

    Relies on the BROWSERID_AUDIENCES setting, which is an explicit list of acceptable
    audiences for your site.

    :returns:
        The first audience in BROWSERID_AUDIENCES that has the same origin as the request's
        URL.

    :raises:
        :class:`django.core.exceptions.ImproperlyConfigured`: If BROWSERID_AUDIENCES isn't
        defined, or if no matching audience could be found.
    """
    try:
        audiences = settings.BROWSERID_AUDIENCES
    except AttributeError:
        raise ImproperlyConfigured(
            'Required setting BROWSERID_AUDIENCES not found!')

    protocol = 'https' if request.is_secure() else 'http'
    host = '{0}://{1}'.format(protocol, request.get_host())
    for audience in audiences:
        if same_origin(host, audience):
            return audience

    # No audience found? We must not be configured properly, otherwise why are we getting this
    # request?
    raise ImproperlyConfigured(
        'No audience could be found in BROWSERID_AUDIENCES for host `{0}`.'.
        format(host))
Пример #7
0
    def process_view(self, request, callback, callback_args, callback_kwargs):
        """
        Taken from django.middleware.csrf
        """
        if request.is_secure():
            # Suppose user visits http://example.com/
            # An active network attacker (man-in-the-middle, MITM) sends a
            # POST form that targets https://example.com/detonate-bomb/ and
            # submits it via JavaScript.
            #
            # The attacker will need to provide a CSRF cookie and token, but
            # that's no problem for a MITM and the session-independent
            # nonce we're using. So the MITM can circumvent the CSRF
            # protection. This is true for any HTTP connection, but anyone
            # using HTTPS expects better! For this reason, for
            # https://example.com/ we need additional protection that treats
            # http://example.com/ as completely untrusted. Under HTTPS,
            # Barth et al. found that the Referer header is missing for
            # same-domain requests in only about 0.2% of cases or less, so
            # we can use strict Referer checking.
            referer = force_text(
                request.META.get('HTTP_REFERER'),
                strings_only=True,
                errors='replace'
            )
            if referer is None:
                return self._reject(request, REASON_NO_REFERER)

            # Note that request.get_host() includes the port.
            good_referer = 'https://%s/' % request.get_host()
            if not same_origin(referer, good_referer):
                reason = REASON_BAD_REFERER % (referer, good_referer)
                return self._reject(request, reason)

        return self._accept(request)
Пример #8
0
    def try_sessions(self, request, **kwargs):
        """
        Attempt to authenticate with sessions.

        Cribbed from a newer version of Tastypie than we're using.
        """
        csrf_token = _sanitize_token(request.COOKIES.get(settings.CSRF_COOKIE_NAME, ""))

        if request.is_secure():
            referer = request.META.get("HTTP_REFERER")

            if referer is None:
                return False

            good_referer = "https://%s/" % request.get_host()

            if not same_origin(referer, good_referer):
                return False

        # Tastypie docstring says accessing POST here isn't safe, but so far it's not causing any problems...
        # This is necessary for downloads that post the csrf token from an iframe
        request_csrf_token = request.META.get("HTTP_X_CSRFTOKEN", "") or request.POST.get("csrfmiddlewaretoken", "")

        if not constant_time_compare(request_csrf_token, csrf_token):
            return False

        return request.user.is_authenticated()
Пример #9
0
    def is_authenticated(self, request, **kwargs):
        """
        Checks to make sure the user is logged in & has a Django session.
        """
        # Cargo-culted from Django 1.3/1.4's ``django/middleware/csrf.py``.
        # We can't just use what's there, since the return values will be
        # wrong.
        # We also can't risk accessing ``request.POST``, which will break with
        # the serialized bodies.
        if request.method in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
            return request.user.is_authenticated()

        if getattr(request, '_dont_enforce_csrf_checks', False):
            return request.user.is_authenticated()

        csrf_token = _sanitize_token(request.COOKIES.get(settings.CSRF_COOKIE_NAME, ''))

        if request.is_secure():
            referer = request.META.get('HTTP_REFERER')

            if referer is None:
                return False

            good_referer = 'https://%s/' % request.get_host()

            if not same_origin(referer, good_referer):
                return False

        request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

        if not constant_time_compare(request_csrf_token, csrf_token):
            return False

        return request.user.is_authenticated()
Пример #10
0
    def is_authenticated(self, request, **kwargs):
        """
        """

        # this is the line i have to override in order to get
        # POST request to successfully authenticate ##
        if request.method in ('GET', 'POST', 'DELETE'):
            return request.user.is_authenticated()

        if getattr(request, '_dont_enforce_csrf_checks', False):
            return request.user.is_authenticated()

        csrf_token = _sanitize_token(request.COOKIES.get(settings.CSRF_COOKIE_NAME, ''))

        if request.is_secure():
            referer = request.META.get('HTTP_REFERER')

            if referer is None:
                return False

            good_referer = 'https://%s/' % request.get_host()

            if not same_origin(referer, good_referer):
                return False

        request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

        if not constant_time_compare(request_csrf_token, csrf_token):
            return False

        return request.user.is_authenticated()
Пример #11
0
def get_audience(request):
    """
    Determine the audience to use for verification from the given request.

    Relies on the BROWSERID_AUDIENCES setting, which is an explicit list of acceptable
    audiences for your site.

    :returns:
        The first audience in BROWSERID_AUDIENCES that has the same origin as the request's
        URL.

    :raises:
        :class:`django.core.exceptions.ImproperlyConfigured`: If BROWSERID_AUDIENCES isn't
        defined, or if no matching audience could be found.
    """
    try:
        audiences = settings.BROWSERID_AUDIENCES
    except AttributeError:
        raise ImproperlyConfigured('Required setting BROWSERID_AUDIENCES not found!')

    protocol = 'https' if request.is_secure() else 'http'
    host = '{0}://{1}'.format(protocol, request.get_host())
    for audience in audiences:
        if same_origin(host, audience):
            return audience

    # No audience found? We must not be configured properly, otherwise why are we getting this
    # request?
    raise ImproperlyConfigured('No audience could be found in BROWSERID_AUDIENCES for host `{0}`.'
                               .format(host))
    def is_authenticated(self, request, **kwargs):

        # this is the line i have to override in order to get
        # POST request to successfully authenticate ##
        if request.method in ['GET', 'POST', 'PATCH', 'DELETE']:
            return request.user.is_authenticated()

        if getattr(request, '_dont_enforce_csrf_checks', False):
            return request.user.is_authenticated()

        csrf_token = _sanitize_token(
            request.COOKIES.get(settings.CSRF_COOKIE_NAME, ''))

        if request.is_secure():
            referer = request.META.get('HTTP_REFERER')

            if referer is None:
                return False

            good_referer = 'https://%s/' % request.get_host()

            if not same_origin(referer, good_referer):
                return False

        request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

        if not constant_time_compare(request_csrf_token, csrf_token):
            return False

        return request.user.is_authenticated()
Пример #13
0
    def is_authenticated(self, request, **kwargs):
        """
        Checks to make sure the user is logged in & has a Django session.
        """
        # Cargo-culted from Django 1.3/1.4's ``django/middleware/csrf.py``.
        # We can't just use what's there, since the return values will be
        # wrong.
        # We also can't risk accessing ``request.POST``, which will break with
        # the serialized bodies.
        if request.method in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
            return request.user.is_authenticated()

        if getattr(request, '_dont_enforce_csrf_checks', False):
            return request.user.is_authenticated()

        csrf_token = _sanitize_token(request.COOKIES.get(settings.CSRF_COOKIE_NAME, ''))

        if request.is_secure():
            referer = request.META.get('HTTP_REFERER')

            if referer is None:
                return False

            good_referer = 'https://%s/' % request.get_host()

            if not same_origin(referer, good_referer):
                return False

        request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

        if not constant_time_compare(request_csrf_token, csrf_token):
            return False

        return request.user.is_authenticated()
Пример #14
0
    def try_sessions(self, request, **kwargs):
        """
        Attempt to authenticate with sessions.

        Cribbed from a newer version of Tastypie than we're using.
        """
        csrf_token = _sanitize_token(
            request.COOKIES.get(settings.CSRF_COOKIE_NAME, ''))

        if request.is_secure():
            referer = request.META.get('HTTP_REFERER')

            if referer is None:
                return False

            good_referer = 'https://%s/' % request.get_host()

            if not same_origin(referer, good_referer):
                return False

        # Tastypie docstring says accessing POST here isn't safe, but so far it's not causing any problems...
        # This is necessary for downloads that post the csrf token from an iframe
        request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN',
                                              '') or request.POST.get(
                                                  'csrfmiddlewaretoken', '')

        if not constant_time_compare(request_csrf_token, csrf_token):
            return False

        return request.user.is_authenticated()
Пример #15
0
    def validate_ticket(self, ticket, service, renew=False, require_https=False):
        """
        Given a ticket string and service identifier, validate the
        corresponding ``Ticket``. If validation succeeds, return the
        ``Ticket``. If validation fails, raise an appropriate error.

        If ``renew`` is ``True``, ``ServiceTicket`` validation will
        only succeed if the ticket was issued from the presentation
        of the user's primary credentials.

        If ``require_https`` is ``True``, ``ServiceTicket`` validation
        will only succeed if the service URL scheme is HTTPS.
        """
        if not ticket:
            raise InvalidRequest("No ticket string provided")

        if not self.model.TICKET_RE.match(ticket):
            raise InvalidTicket("Ticket string %s is invalid" % ticket)

        try:
            t = self.get(ticket=ticket)
        except self.model.DoesNotExist:
            raise InvalidTicket("Ticket %s does not exist" % ticket)

        if t.is_consumed():
            raise InvalidTicket("%s %s has already been used" %
                                (t.name, ticket))
        if t.is_expired():
            raise InvalidTicket("%s %s has expired" % (t.name, ticket))

        if not service:
            raise InvalidRequest("No service identifier provided")

        if require_https and not is_scheme_https(service):
            raise InvalidService("Service %s is not HTTPS" % service)

        if not is_valid_service_url(service):
            raise InvalidService("Service %s is not a valid %s URL" %
                                 (service, t.name))

        try:
            if not same_origin(t.service, service):
                raise InvalidService("%s %s for service %s is invalid for "
                        "service %s" % (t.name, ticket, t.service, service))
        except AttributeError:
            pass

        try:
            if renew and not t.is_primary():
                raise InvalidTicket("%s %s was not issued via primary "
                                    "credentials" % (t.name, ticket))
        except AttributeError:
            pass

        logger.debug("Validated %s %s" % (t.name, ticket))
        return t
Пример #16
0
    def validate_ticket(self, ticket, service, renew=False, require_https=False):
        """
        Given a ticket string and service identifier, validate the
        corresponding ``Ticket``. If validation succeeds, return the
        ``Ticket``. If validation fails, raise an appropriate error.

        If ``renew`` is ``True``, ``ServiceTicket`` validation will
        only succeed if the ticket was issued from the presentation
        of the user's primary credentials.

        If ``require_https`` is ``True``, ``ServiceTicket`` validation
        will only succeed if the service URL scheme is HTTPS.
        """
        if not ticket:
            raise InvalidRequest("No ticket string provided")

        if not self.model.TICKET_RE.match(ticket):
            raise InvalidTicket("Ticket string %s is invalid" % ticket)

        try:
            t = self.get(ticket=ticket)
        except self.model.DoesNotExist:
            raise InvalidTicket("Ticket %s does not exist" % ticket)

        if t.is_consumed():
            raise InvalidTicket("%s %s has already been used" %
                                (t.name, ticket))
        if t.is_expired():
            raise InvalidTicket("%s %s has expired" % (t.name, ticket))

        if not service:
            raise InvalidRequest("No service identifier provided")

        if require_https and not is_scheme_https(service):
            raise InvalidService("Service %s is not HTTPS" % service)

        if not is_valid_service_url(service):
            raise InvalidService("Service %s is not a valid %s URL" %
                                 (service, t.name))

        try:
            if not same_origin(t.service, service):
                raise InvalidService("%s %s for service %s is invalid for "
                        "service %s" % (t.name, ticket, t.service, service))
        except AttributeError:
            pass

        try:
            if renew and not t.is_primary():
                raise InvalidTicket("%s %s was not issued via primary "
                                    "credentials" % (t.name, ticket))
        except AttributeError:
            pass

        logger.debug("Validated %s %s" % (t.name, ticket))
        return t
Пример #17
0
def check_referer(request, skip_post=True):
    '''Check that the current referer match current origin.

       Post requests are usually ignored as they are already check by the
       CSRF middleware.
    '''
    if skip_post and request.method == 'POST':
        return True
    referer = request.META.get('HTTP_REFERER')
    return referer and http.same_origin(request.build_absolute_uri(),
            referer)
Пример #18
0
    def validate_ticket(self, ticket, service=None, renew=False):
        """
        Given a ticket string, validate the corresponding ``Ticket`` returning
        the ``Ticket`` if valid. If validation fails, return ``False``.

        If ``service`` is provided and the ticket has a service attribute,
        the origin of the two services will be compared. Validation will only
        succeed if the service origins match.

        if ``renew`` is provided, the validation will only succeed if the
        ticket was issued from the presentation of the user's primary
        credentials.
        """
        if not ticket:
            raise InvalidRequestError("No ticket string provided")

        if not self.model.TICKET_RE.match(ticket):
            raise InvalidTicketError("Ticket string %s is invalid" % ticket)

        title = self.model._meta.verbose_name.title()

        try:
            t = self.get(ticket=ticket)
        except self.model.DoesNotExist:
            raise InvalidTicketError("%s %s does not exist" % (title, ticket))

        if t.is_consumed():
            raise InvalidTicketError("%s %s has already been used" %
                                     (title, ticket))
        t.consume()

        if t.is_expired():
            raise InvalidTicketError("%s %s has expired" % (title, ticket))

        if not service:
            raise InvalidRequestError("No service identifier provided")

        if not is_valid_service_url(service):
            raise InvalidServiceError("Service %s is not a valid %s URL" %
                                      (service, title))

        if not same_origin(t.service, service):
            raise InvalidServiceError("%s %s for service %s is invalid for service %s" %
                                      (title, ticket, t.service, service))

        if renew and not t.is_primary():
            raise InvalidTicketError("%s %s was not issued via primary credentials" %
                                     (title, ticket))

        logger.debug("Validated %s %s" % (title, ticket))
        return t
Пример #19
0
def get_audience(request):
    try:
        audiences = settings.BROWSERID_AUDIENCES
    except AttributeError:
        raise ImproperlyConfigured('Required setting BROWSERID_AUDIENCES not found!')

    protocol = 'https' if request.is_secure() else 'http'
    host = '%s://%s' % (protocol, request.get_host())
    for audience in audiences:
        if same_origin(host, audience):
            return audience

    raise ImproperlyConfigured('No audience could be found in BROWSERID_AUDIENCES for host `{0}`.'
                               .format(host))
def get_audience(request):
    try:
        audiences = settings.BROWSERID_AUDIENCES
    except AttributeError:
        raise ImproperlyConfigured(
            'Required setting BROWSERID_AUDIENCES not found!')

    protocol = 'https' if request.is_secure() else 'http'
    host = '%s://%s' % (protocol, request.get_host())
    for audience in audiences:
        if same_origin(host, audience):
            return audience

    raise ImproperlyConfigured(
        'No audience could be found in BROWSERID_AUDIENCES for host `{0}`.'.
        format(host))
Пример #21
0
 def test_same_origin_true(self):
     # Identical
     self.assertTrue(http.same_origin('http://foo.com/', 'http://foo.com/'))
     # One with trailing slash - see #15617
     self.assertTrue(http.same_origin('http://foo.com', 'http://foo.com/'))
     self.assertTrue(http.same_origin('http://foo.com/', 'http://foo.com'))
     # With port
     self.assertTrue(http.same_origin('https://foo.com:8000', 'https://foo.com:8000/'))
     # No port given but according to RFC6454 still the same origin
     self.assertTrue(http.same_origin('http://foo.com', 'http://foo.com:80/'))
     self.assertTrue(http.same_origin('https://foo.com', 'https://foo.com:443/'))
Пример #22
0
 def test_same_origin_true(self):
     # Identical
     self.assertTrue(http.same_origin('http://foo.com/', 'http://foo.com/'))
     # One with trailing slash - see #15617
     self.assertTrue(http.same_origin('http://foo.com', 'http://foo.com/'))
     self.assertTrue(http.same_origin('http://foo.com/', 'http://foo.com'))
     # With port
     self.assertTrue(http.same_origin('https://foo.com:8000', 'https://foo.com:8000/'))
     # No port given but according to RFC6454 still the same origin
     self.assertTrue(http.same_origin('http://foo.com', 'http://foo.com:80/'))
     self.assertTrue(http.same_origin('https://foo.com', 'https://foo.com:443/'))
Пример #23
0
def _is_good_request(request):
    """
    Temporarily sanitizing check. Look at https://github.com/django/django/blob/master/django/middleware/csrf.py
    TODO: remove this when we move the widget to django and let django's middleware handles this.
    @param request: http request
    @return: true or false
    """
    is_good_request = True
    referer = request.META.get('HTTP_REFERER')
    if referer is None:
        is_good_request = False
        logger.warning(REASON_NO_REFERER)

    # Note that request.get_host() includes the port.
    good_referer = 'http://%s/' % request.get_host()
    if referer:
        if not same_origin(referer, good_referer):
            is_good_request = False
            logger.warning(REASON_BAD_REFERER.format(referer, good_referer))

    return is_good_request
Пример #24
0
def manual_csrf_check(request):
    """
    Performs a CSRF check for a specific request.

    Useful for in-view CSRF checks.

    Returns an HTTP response in case of CSRF failure.
    """
    try:
        csrf_token = _sanitize_token(
            request.COOKIES[settings.CSRF_COOKIE_NAME]
        )
        request.META['CSRF_COOKIE'] = csrf_token
    except KeyError:
        csrf_token = None
        request.META["CSRF_COOKIE"] = _get_new_csrf_key()

    if request.method not in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
        if request.is_secure():
            referer = request.META.get('HTTP_REFERER')
            if referer is None:
                return middleware._reject(request, REASON_NO_REFERER)

            good_referer = 'https://%s/' % request.get_host()
            if not same_origin(referer, good_referer):
                reason = REASON_BAD_REFERER % (referer, good_referer)
                return middleware._reject(request, reason)

        if csrf_token is None:
            return middleware._reject(request, REASON_NO_CSRF_COOKIE)

        request_csrf_token = ""
        if request.method == "POST":
            request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')

        if request_csrf_token == "":
            request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

        if not constant_time_compare(request_csrf_token, csrf_token):
            return middleware._reject(request, REASON_BAD_TOKEN)
Пример #25
0
    def process_view(self, request, callback, callback_args, callback_kwargs):
        if getattr(request, 'csrf_processing_done', False):
            return None

        try:
            cookie_token = request.COOKIES[settings.CSRF_COOKIE_NAME]
        except KeyError:
            csrf_token = None
        else:
            csrf_token = _sanitize_token(cookie_token)
            if csrf_token != cookie_token:
                # Cookie token needed to be replaced;
                # the cookie needs to be reset.
                request.csrf_cookie_needs_reset = True
            # Use same token next time.
            request.META['CSRF_COOKIE'] = csrf_token

        # Wait until request.META["CSRF_COOKIE"] has been manipulated before
        # bailing out, so that get_token still works
        if getattr(callback, 'csrf_exempt', False):
            return None

        # Assume that anything not defined as 'safe' by RFC7231 needs protection
        if request.method not in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
            if getattr(request, '_dont_enforce_csrf_checks', False):
                # Mechanism to turn off CSRF checks for test suite.
                # It comes after the creation of CSRF cookies, so that
                # everything else continues to work exactly the same
                # (e.g. cookies are sent, etc.), but before any
                # branches that call reject().
                return self._accept(request)

            if request.is_secure():
                # Suppose user visits http://example.com/
                # An active network attacker (man-in-the-middle, MITM) sends a
                # POST form that targets https://example.com/detonate-bomb/ and
                # submits it via JavaScript.
                #
                # The attacker will need to provide a CSRF cookie and token, but
                # that's no problem for a MITM and the session-independent
                # secret we're using. So the MITM can circumvent the CSRF
                # protection. This is true for any HTTP connection, but anyone
                # using HTTPS expects better! For this reason, for
                # https://example.com/ we need additional protection that treats
                # http://example.com/ as completely untrusted. Under HTTPS,
                # Barth et al. found that the Referer header is missing for
                # same-domain requests in only about 0.2% of cases or less, so
                # we can use strict Referer checking.
                referer = base_referer = force_text(
                    request.META.get('HTTP_REFERER'),
                    strings_only=True,
                    errors='replace'
                )
                if referer is None:
                    return self._reject(request, REASON_NO_REFERER)

                referer = urlparse(referer)

                # Make sure we have a valid URL for Referer.
                if '' in (referer.scheme, referer.netloc):
                    return self._reject(request, REASON_MALFORMED_REFERER)

                # Ensure that our Referer is also secure.
                if referer.scheme != 'https':
                    return self._reject(request, REASON_INSECURE_REFERER)

                # If there isn't a CSRF_COOKIE_DOMAIN, assume we need an exact
                # match on host:port. If not, obey the cookie rules.
                if settings.CSRF_COOKIE_DOMAIN is None:
                    # request.get_host() includes the port.
                    good_referer = request.get_host()
                else:
                    good_referer = settings.CSRF_COOKIE_DOMAIN
                    server_port = request.get_port()
                    if server_port not in ('443', '80'):
                        good_referer = '%s:%s' % (good_referer, server_port)

                # if not any(is_same_domain(referer.netloc, host) for host in good_hosts):
                #     reason = REASON_BAD_REFERER % referer.geturl()
                    
                good_referer = 'https://%s/' % request.get_host()
                if not same_origin(base_referer, good_referer):
                    reason = REASON_BAD_REFERER % (base_referer, good_referer)
                    return self._reject(request, reason)

            if csrf_token is None:
                # No CSRF cookie. For POST requests, we insist on a CSRF cookie,
                # and in this way we can avoid all CSRF attacks, including login
                # CSRF.
                return self._reject(request, REASON_NO_CSRF_COOKIE)

            # Check non-cookie token for match.
            request_csrf_token = ""
            if request.method == "POST":
                try:
                    request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
                except IOError:
                    # Handle a broken connection before we've completed reading
                    # the POST data. process_view shouldn't raise any
                    # exceptions, so we'll ignore and serve the user a 403
                    # (assuming they're still listening, which they probably
                    # aren't because of the error).
                    pass

            if request_csrf_token == "":
                # Fall back to X-CSRFToken, to make things easier for AJAX,
                # and possible for PUT/DELETE.
                request_csrf_token = request.META.get(settings.CSRF_HEADER_NAME, '')

            request_csrf_token = _sanitize_token(request_csrf_token)
            if not _compare_salted_tokens(request_csrf_token, csrf_token):
                return self._reject(request, REASON_BAD_TOKEN)

        return self._accept(request)
Пример #26
0
    def process_view(self, request, callback, callback_args, callback_kwargs):
        # 如果请求里面设置了csrf_done,则没有任何处理,一旦这个设置了,那么整个中间件都
        # 不会产生作用
        if getattr(request, 'csrf_processing_done', False):
            return None

        try:
            # 从cookie里面拿出之前设置的cookie,将其净化
            csrf_token = _sanitize_token(
                request.COOKIES[settings.CSRF_COOKIE_NAME])
            # Use same token next time
            request.META['CSRF_COOKIE'] = csrf_token
        # 没有设置过,则在request中设置一个CSRF_COOKIE,这次请求必须是一个GET请求.
        # 如果开发的网站使用GET,HEAD等请求更新数据库(不符合规范),那么CSRF中间层不会
        # 正确的验证,因此绝对不要这样.
        except KeyError:
            csrf_token = None
            # Generate token and store it in the request, so it's
            # available to the view.
            request.META["CSRF_COOKIE"] = _get_new_csrf_key()

        # TODO:设置了就跳过这里的处理,下面的注释的意思
        # Wait until request.META["CSRF_COOKIE"] has been manipulated before
        # bailing out, so that get_token still works
        if getattr(callback, 'csrf_exempt', False):
            return None

        # Assume that anything not defined as 'safe' by RFC2616 needs protection
        if request.method not in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
            # 如果请求中设置了不要开启csrf检查则直接ok,应该是其他中间件可以控制的,如
            # 果这个设置了,中间件只是处理response验证.以及设置个Cookie
            if getattr(request, '_dont_enforce_csrf_checks', False):
                # Mechanism to turn off CSRF checks for test suite.
                # It comes after the creation of CSRF cookies, so that
                # everything else continues to work exactly the same
                # (e.g. cookies are sent, etc.), but before any
                # branches that call reject().
                return self._accept(request)

            # 如果使用HTTPS,那么必须设置了refer并且和目标HOST一致.
            if request.is_secure():
                # Suppose user visits http://example.com/
                # An active network attacker (man-in-the-middle, MITM) sends a
                # POST form that targets https://example.com/detonate-bomb/ and
                # submits it via JavaScript.
                #
                # The attacker will need to provide a CSRF cookie and token, but
                # that's no problem for a MITM and the session-independent
                # nonce we're using. So the MITM can circumvent the CSRF
                # protection. This is true for any HTTP connection, but anyone
                # using HTTPS expects better! For this reason, for
                # https://example.com/ we need additional protection that treats
                # http://example.com/ as completely untrusted. Under HTTPS,
                # Barth et al. found that the Referer header is missing for
                # same-domain requests in only about 0.2% of cases or less, so
                # we can use strict Referer checking.
                referer = force_text(request.META.get('HTTP_REFERER'),
                                     strings_only=True,
                                     errors='replace')
                if referer is None:
                    return self._reject(request, REASON_NO_REFERER)

                # Note that request.get_host() includes the port.
                good_referer = 'https://%s/' % request.get_host()
                if not same_origin(referer, good_referer):
                    reason = REASON_BAD_REFERER % (referer, good_referer)
                    return self._reject(request, reason)

            # 没有csrf_token则拒绝,也就是说对网站的第一个请求必须是get,因为之后会设置csrf.
            if csrf_token is None:
                # No CSRF cookie. For POST requests, we insist on a CSRF cookie,
                # and in this way we can avoid all CSRF attacks, including login
                # CSRF.
                return self._reject(request, REASON_NO_CSRF_COOKIE)

            # Check non-cookie token for match.
            # 拿到其中的另一个csrf设置,对于POST,是csrfmt,对于其他,是HTTP_X_CSRFTOKEN
            # 判断这两个和POST中的是否一致.  可以POST.因为存在cookie中,而其他程序拿不到cookie值
            # 能发送但是不能拿到,然后在加上另外的值其他程序就没办法了
            request_csrf_token = ""
            if request.method == "POST":
                try:
                    # 是Django模板系统设置的.
                    request_csrf_token = request.POST.get(
                        'csrfmiddlewaretoken', '')
                except IOError:
                    # Handle a broken connection before we've completed reading
                    # the POST data. process_view shouldn't raise any
                    # exceptions, so we'll ignore and serve the user a 403
                    # (assuming they're still listening, which they probably
                    # aren't because of the error).
                    pass

            if request_csrf_token == "":
                # Fall back to X-CSRFToken, to make things easier for AJAX,
                # and possible for PUT/DELETE.
                # TODO: 是哪里设置的?:视图,模板等设置的.
                request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')
            if not constant_time_compare(request_csrf_token, csrf_token):
                return self._reject(request, REASON_BAD_TOKEN)

        return self._accept(request)
Пример #27
0
    def process_view(self, request, callback, callback_args, callback_kwargs):

        if getattr(request, "csrf_processing_done", False):
            return None

        try:
            csrf_token = _sanitize_token(request.COOKIES[settings.CSRF_COOKIE_NAME])
            # Use same token next time
            request.META["CSRF_COOKIE"] = csrf_token
        except KeyError:
            print "Key Error and Reset the token now!Maybe you need set the cookie of client!"  # ,request.COOKIES,request.META
            csrf_token = None
            # Generate token and store it in the request, so it's
            # available to the view.
            request.META["CSRF_COOKIE"] = _get_new_csrf_key()

        # Wait until request.META["CSRF_COOKIE"] has been manipulated before
        # bailing out, so that get_token still works
        if getattr(callback, "csrf_exempt", False):
            return None

        # Assume that anything not defined as 'safe' by RFC2616 needs protection
        if request.method not in ("GET", "HEAD", "OPTIONS", "TRACE"):

            if getattr(request, "_dont_enforce_csrf_checks", False):
                # Mechanism to turn off CSRF checks for test suite.
                # It comes after the creation of CSRF cookies, so that
                # everything else continues to work exactly the same
                # (e.g. cookies are sent, etc.), but before any
                # branches that call reject().
                return self._accept(request)

            if request.is_secure():
                # Suppose user visits http://example.com/
                # An active network attacker (man-in-the-middle, MITM) sends a
                # POST form that targets https://example.com/detonate-bomb/ and
                # submits it via JavaScript.
                #
                # The attacker will need to provide a CSRF cookie and token, but
                # that's no problem for a MITM and the session-independent
                # nonce we're using. So the MITM can circumvent the CSRF
                # protection. This is true for any HTTP connection, but anyone
                # using HTTPS expects better! For this reason, for
                # https://example.com/ we need additional protection that treats
                # http://example.com/ as completely untrusted. Under HTTPS,
                # Barth et al. found that the Referer header is missing for
                # same-domain requests in only about 0.2% of cases or less, so
                # we can use strict Referer checking.
                referer = force_text(request.META.get("HTTP_REFERER"), strings_only=True, errors="replace")
                if referer is None:
                    return self._reject(request, REASON_NO_REFERER)

                # Note that request.get_host() includes the port.
                good_referer = "https://%s/" % request.get_host()
                if not same_origin(referer, good_referer):
                    reason = REASON_BAD_REFERER % (referer, good_referer)
                    return self._reject(request, reason)

            """
            !!!!!!
            When qiniu send the call back to server. the csrf can miss
            """
            if "qiniu-callback" in request.META.get("HTTP_USER_AGENT", ""):
                return self._accept(request)

            if csrf_token is None:
                # No CSRF cookie. For POST requests, we insist on a CSRF cookie,
                # and in this way we can avoid all CSRF attacks, including login
                # CSRF.
                return self._reject(request, REASON_NO_CSRF_COOKIE)

            # Check non-cookie token for match.
            request_csrf_token = ""
            if request.method == "POST":
                try:
                    request_csrf_token = request.POST.get("csrfmiddlewaretoken", "")
                except IOError:
                    # Handle a broken connection before we've completed reading
                    # the POST data. process_view shouldn't raise any
                    # exceptions, so we'll ignore and serve the user a 403
                    # (assuming they're still listening, which they probably
                    # aren't because of the error).
                    pass

            if request_csrf_token == "":
                # Fall back to X-CSRFToken, to make things easier for AJAX,
                # and possible for PUT/DELETE.
                request_csrf_token = request.META.get("HTTP_X_CSRFTOKEN", "")
                # print request.META

            """
            When the Android send the token in the HTTP_COOKIE
            """
            if request_csrf_token == "":

                request_csrf_token = request.META.get("HTTP_COOKIE", "")
                regToken = re.compile(r"csrftoken=(.*)")
                tokenResult = regToken.findall(request_csrf_token)
                print 1, tokenResult
                if len(tokenResult) != 1:
                    request_csrf_token = ""
                else:
                    request_csrf_token = tokenResult[0]

                    # When Ajax send the cookie csrftoken=JZ4U3CGWouhRu8TYDVBCXqggqVc9LAgY; request-use-base64=false
                    # find the ';' and record the token before it.
                    iSubTemp = request_csrf_token.find(";")
                    if iSubTemp > 0:
                        request_csrf_token = request_csrf_token[:iSubTemp]
            """
            Get the token from Json's data
            """
            if request_csrf_token == "" and "application/json" in request.META.get("CONTENT_TYPE", ""):
                # When the Token sent by client in the JSON body
                jsondata = simplejson.loads(request.body)

                if isinstance(jsondata, dict):
                    request_csrf_token = simplejson.loads(request.body).get("csrfmiddlewaretoken", "")
                elif isinstance(jsondata, list):
                    request_csrf_token = simplejson.loads(request.body)[0].get("csrfmiddlewaretoken", "")
                else:
                    pass

            print 10, request_csrf_token, 11, csrf_token
            if not constant_time_compare(request_csrf_token, csrf_token):
                return self._reject(request, REASON_BAD_TOKEN)

        return self._accept(request)
Пример #28
0
    def process_view(self, request, callback, callback_args, callback_kwargs):

        if getattr(request, 'csrf_processing_done', False):
            return None

        try:
            csrf_token = django_csrf._sanitize_token(
                request.COOKIES[settings.CSRF_COOKIE_NAME])
            # Use same token next time
            request.META['CSRF_COOKIE'] = csrf_token
        except KeyError:
            csrf_token = None
            # Generate token and store it in the request, so it's
            # available to the view.
            request.META["CSRF_COOKIE"] = django_csrf._get_new_csrf_key()

        # Wait until request.META["CSRF_COOKIE"] has been manipulated before
        # bailing out, so that get_token still works
        if getattr(callback, 'csrf_exempt', False):
            return None

        # Assume that anything not defined as 'safe' by RFC2616 needs protection
        if request.method not in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
            if getattr(request, '_dont_enforce_csrf_checks', False):
                # Mechanism to turn off CSRF checks for test suite.
                # It comes after the creation of CSRF cookies, so that
                # everything else continues to work exactly the same
                # (e.g. cookies are sent, etc.), but before any
                # branches that call reject().
                return self._accept(request)

            if request.is_secure():
                # Suppose user visits http://example.com/
                # An active network attacker (man-in-the-middle, MITM) sends a
                # POST form that targets https://example.com/detonate-bomb/ and
                # submits it via JavaScript.
                #
                # The attacker will need to provide a CSRF cookie and token, but
                # that's no problem for a MITM and the session-independent
                # nonce we're using. So the MITM can circumvent the CSRF
                # protection. This is true for any HTTP connection, but anyone
                # using HTTPS expects better! For this reason, for
                # https://example.com/ we need additional protection that treats
                # http://example.com/ as completely untrusted. Under HTTPS,
                # Barth et al. found that the Referer header is missing for
                # same-domain requests in only about 0.2% of cases or less, so
                # we can use strict Referer checking.
                referer = force_text(request.META.get('HTTP_REFERER'),
                                     strings_only=True,
                                     errors='replace')
                if referer is None:
                    return self._reject(request, django_csrf.REASON_NO_REFERER)

                # Here we generate a list of all acceptable HTTP referers,
                # including the current host since that has been validated
                # upstream.
                good_hosts = list(settings.CSRF_TRUSTED_ORIGINS)
                # Note that request.get_host() includes the port.
                good_hosts.append(request.get_host())
                good_referers = [
                    'https://{0}/'.format(host) for host in good_hosts
                ]
                if not any(
                        same_origin(referer, host) for host in good_referers):
                    reason = REASON_BAD_REFERER % referer
                    return self._reject(request, reason)

            if csrf_token is None:
                # No CSRF cookie. For POST requests, we insist on a CSRF cookie,
                # and in this way we can avoid all CSRF attacks, including login
                # CSRF.
                return self._reject(request, django_csrf.REASON_NO_CSRF_COOKIE)

            # Check non-cookie token for match.
            request_csrf_token = ""
            if request.method == "POST":
                try:
                    request_csrf_token = request.POST.get(
                        'csrfmiddlewaretoken', '')
                except IOError:
                    # Handle a broken connection before we've completed reading
                    # the POST data. process_view shouldn't raise any
                    # exceptions, so we'll ignore and serve the user a 403
                    # (assuming they're still listening, which they probably
                    # aren't because of the error).
                    pass

            if request_csrf_token == "":
                # Fall back to X-CSRFToken, to make things easier for AJAX,
                # and possible for PUT/DELETE.
                request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

            if not constant_time_compare(request_csrf_token, csrf_token):
                return self._reject(request, django_csrf.REASON_BAD_TOKEN)

        return self._accept(request)
Пример #29
0
    def process_view(self, request, callback, callback_args, callback_kwargs):

        if getattr(request, 'csrf_processing_done', False):
            return None

        try:
            csrf_token = _sanitize_token(
                request.COOKIES[settings.CSRF_COOKIE_NAME])
            # Use same token next time
            request.META['CSRF_COOKIE'] = csrf_token
        except KeyError:
            csrf_token = None

        # Wait until request.META["CSRF_COOKIE"] has been manipulated before
        # bailing out, so that get_token still works
        if getattr(callback, 'csrf_exempt', False):
            return None

        # Assume that anything not defined as 'safe' by RFC2616 needs protection
        if request.method not in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
            if getattr(request, '_dont_enforce_csrf_checks', False):
                # Mechanism to turn off CSRF checks for test suite.
                # It comes after the creation of CSRF cookies, so that
                # everything else continues to work exactly the same
                # (e.g. cookies are sent, etc.), but before any
                # branches that call reject().
                return self._accept(request)

            if request.is_secure():
                # Suppose user visits http://example.com/
                # An active network attacker (man-in-the-middle, MITM) sends a
                # POST form that targets https://example.com/detonate-bomb/ and
                # submits it via JavaScript.
                #
                # The attacker will need to provide a CSRF cookie and token, but
                # that's no problem for a MITM and the session-independent
                # nonce we're using. So the MITM can circumvent the CSRF
                # protection. This is true for any HTTP connection, but anyone
                # using HTTPS expects better! For this reason, for
                # https://example.com/ we need additional protection that treats
                # http://example.com/ as completely untrusted. Under HTTPS,
                # Barth et al. found that the Referer header is missing for
                # same-domain requests in only about 0.2% of cases or less, so
                # we can use strict Referer checking.
                referer = force_text(
                    request.META.get('HTTP_REFERER'),
                    strings_only=True,
                    errors='replace'
                )
                if referer is None:
                    return self._reject(request, REASON_NO_REFERER)

                # Here we generate a list of all acceptable HTTP referers,
                # including the current host since that has been validated
                # upstream.
                good_hosts = list(settings.CSRF_TRUSTED_ORIGINS)
                # Note that request.get_host() includes the port.
                good_hosts.append(request.get_host())
                good_referers = ['https://{0}/'.format(host) for host in good_hosts]
                if not any(same_origin(referer, host) for host in good_referers):
                    reason = REASON_BAD_REFERER % referer
                    return self._reject(request, reason)

            if csrf_token is None:
                # No CSRF cookie. For POST requests, we insist on a CSRF cookie,
                # and in this way we can avoid all CSRF attacks, including login
                # CSRF.
                return self._reject(request, REASON_NO_CSRF_COOKIE)

            # Check non-cookie token for match.
            request_csrf_token = ""
            if request.method == "POST":
                try:
                    request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
                except IOError:
                    # Handle a broken connection before we've completed reading
                    # the POST data. process_view shouldn't raise any
                    # exceptions, so we'll ignore and serve the user a 403
                    # (assuming they're still listening, which they probably
                    # aren't because of the error).
                    pass

            if request_csrf_token == "":
                # Fall back to X-CSRFToken, to make things easier for AJAX,
                # and possible for PUT/DELETE.
                request_csrf_token = request.META.get(settings.CSRF_HEADER_NAME, '')

            if not constant_time_compare(request_csrf_token, csrf_token):
                return self._reject(request, REASON_BAD_TOKEN)

        return self._accept(request)
Пример #30
0
Файл: csrf.py Проект: mcr/ietfdb
    def process_view(self, request, callback, callback_args, callback_kwargs):

        if getattr(request, 'csrf_processing_done', False):
            return None

        # If the user doesn't have a CSRF cookie, generate one and store it in the
        # request, so it's available to the view.  We'll store it in a cookie when
        # we reach the response.
        try:
            # In case of cookies from untrusted sources, we strip anything
            # dangerous at this point, so that the cookie + token will have the
            # same, sanitized value.
            request.META["CSRF_COOKIE"] = _sanitize_token(request.COOKIES[settings.CSRF_COOKIE_NAME])
            cookie_is_new = False
        except KeyError:
            # No cookie, so create one.  This will be sent with the next
            # response.
            request.META["CSRF_COOKIE"] = _get_new_csrf_key()
            # Set a flag to allow us to fall back and allow the session id in
            # place of a CSRF cookie for this request only.
            cookie_is_new = True

        # Wait until request.META["CSRF_COOKIE"] has been manipulated before
        # bailing out, so that get_token still works
        if getattr(callback, 'csrf_exempt', False):
            return None

        if request.method == 'POST':
            if getattr(request, '_dont_enforce_csrf_checks', False):
                # Mechanism to turn off CSRF checks for test suite.  It comes after
                # the creation of CSRF cookies, so that everything else continues to
                # work exactly the same (e.g. cookies are sent etc), but before the
                # any branches that call reject()
                return self._accept(request)

            if request.is_secure():
                # Strict referer checking for HTTPS
                referer = request.META.get('HTTP_REFERER')
                if referer is None:
                    return self._reject(request, REASON_NO_REFERER)

                # Note that request.get_host() includes the port
                good_referer = 'https://%s/' % request.get_host()
                if not same_origin(referer, good_referer):
                    return self._reject(request, REASON_BAD_REFERER %
                                        (referer, good_referer))

            # If the user didn't already have a CSRF cookie, then fall back to
            # the Django 1.1 method (hash of session ID), so a request is not
            # rejected if the form was sent to the user before upgrading to the
            # Django 1.2 method (session independent nonce)
            if cookie_is_new:
                try:
                    session_id = request.COOKIES[settings.SESSION_COOKIE_NAME]
                    csrf_token = _make_legacy_session_token(session_id)
                except KeyError:
                    # No CSRF cookie and no session cookie. For POST requests,
                    # we insist on a CSRF cookie, and in this way we can avoid
                    # all CSRF attacks, including login CSRF.
                    return self._reject(request, REASON_NO_COOKIE)
            else:
                csrf_token = request.META["CSRF_COOKIE"]

            # check incoming token
            request_csrf_token = request.POST.get('csrfmiddlewaretoken', "")
            if request_csrf_token == "":
                # Fall back to X-CSRFToken, to make things easier for AJAX
                request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

            if request_csrf_token != csrf_token:
                if cookie_is_new:
                    # probably a problem setting the CSRF cookie
                    return self._reject(request, REASON_NO_CSRF_COOKIE)
                else:
                    return self._reject(request, REASON_BAD_TOKEN)

        return self._accept(request)
Пример #31
0
    def handle(self, request, data):
        if 'user_name' in request.session:
            if request.session['user_name'] != data['username']:
                # To avoid reusing another user's session, create a
                # new, empty session if the existing session
                # corresponds to a different authenticated user.
                request.session.flush()
        # Always cycle the session key when viewing the login form to
        # prevent session fixation
        request.session.cycle_key()

        # For now we'll allow fallback to OPENSTACK_KEYSTONE_URL if the
        # form post doesn't include a region.
        # jt
        default_region = (settings.OPENSTACK_KEYSTONE_URL, "Default Region") 
        regions = getattr(settings, 'AVAILABLE_REGIONS', [default_region])
        #endpoint = data.get('region', None) or settings.OPENSTACK_KEYSTONE_URL
        #region_name = dict(self.fields['region'].choices)[endpoint]
        region_name = data.get('region', None) or "Default Region"
        endpoint = [r[0] for r in regions if r[1] == region_name][0]
        request.session['region_endpoint'] = endpoint
        request.session['region_name'] = region_name

        redirect_to = request.REQUEST.get(REDIRECT_FIELD_NAME, None)
        # Make sure the requested redirect matches the protocol,
        # domain, and port of this request
        if redirect_to and not same_origin(
                request.build_absolute_uri(redirect_to),
                request.build_absolute_uri()):
            redirect_to = None

        if data.get('tenant', None):
            try:
                token = api.token_create(request,
                                         data.get('tenant'),
                                         data['username'],
                                         data['password'])
                tenants = api.tenant_list_for_token(request, token.id)
            except:
                msg = _('Unable to authenticate for that project.')
                exceptions.handle(request,
                                  message=msg,
                                  escalate=True)
            _set_session_data(request, token)
            user = users.get_user_from_request(request)
            redirect = redirect_to or base.Horizon.get_user_home(user)
            return shortcuts.redirect(redirect)

        elif data.get('username', None):
            try:
                unscoped_token = api.token_create(request,
                                                  '',
                                                  data['username'],
                                                  data['password'])
            except keystone_exceptions.Unauthorized:
                exceptions.handle(request,
                                  _('Invalid user name or password.'))
            except:
                # If we get here we don't want to show a stack trace to the
                # user. However, if we fail here, there may be bad session
                # data that's been cached already.
                request.user_logout()
                exceptions.handle(request,
                                  message=_("An error occurred authenticating."
                                            " Please try again later."),
                                  escalate=True)

            # Unscoped token
            request.session['unscoped_token'] = unscoped_token.id
            request.user.username = data['username']

            # Get the tenant list, and log in using first tenant
            # FIXME (anthony): add tenant chooser here?
            try:
                tenants = api.tenant_list_for_token(request, unscoped_token.id)
            except:
                exceptions.handle(request)
                tenants = []

            # Abort if there are no valid tenants for this user
            if not tenants:
                messages.error(request,
                               _('You are not authorized for any projects.') %
                                {"user": data['username']},
                               extra_tags="login")
                return

            # Create a token.
            # NOTE(gabriel): Keystone can return tenants that you're
            # authorized to administer but not to log into as a user, so in
            # the case of an Unauthorized error we should iterate through
            # the tenants until one succeeds or we've failed them all.
            while tenants:
                tenant = tenants.pop()
                try:
                    token = api.token_create_scoped(request,
                                                    tenant.id,
                                                    unscoped_token.id)
                    break
                except:
                    # This will continue for recognized Unauthorized
                    # exceptions from keystoneclient.
                    exceptions.handle(request, ignore=True)
                    token = None
            if token is None:
                raise exceptions.NotAuthorized(
                    _("You are not authorized for any available projects."))

            _set_session_data(request, token)
            user = users.get_user_from_request(request)
        redirect = redirect_to or base.Horizon.get_user_home(user)
        return shortcuts.redirect(redirect)
Пример #32
0
    def process_view(self, request, callback, callback_args, callback_kwargs):

        if getattr(request, 'csrf_processing_done', False):
            return None

        # If the user doesn't have a CSRF cookie, generate one and store it in the
        # request, so it's available to the view.  We'll store it in a cookie when
        # we reach the response.
        try:
            # In case of cookies from untrusted sources, we strip anything
            # dangerous at this point, so that the cookie + token will have the
            # same, sanitized value.
            request.META["CSRF_COOKIE"] = _sanitize_token(
                request.COOKIES[settings.CSRF_COOKIE_NAME])
            cookie_is_new = False
        except KeyError:
            # No cookie, so create one.  This will be sent with the next
            # response.
            request.META["CSRF_COOKIE"] = _get_new_csrf_key()
            # Set a flag to allow us to fall back and allow the session id in
            # place of a CSRF cookie for this request only.
            cookie_is_new = True

        # Wait until request.META["CSRF_COOKIE"] has been manipulated before
        # bailing out, so that get_token still works
        if getattr(callback, 'csrf_exempt', False):
            return None

        if request.method == 'POST':
            if getattr(request, '_dont_enforce_csrf_checks', False):
                # Mechanism to turn off CSRF checks for test suite.  It comes after
                # the creation of CSRF cookies, so that everything else continues to
                # work exactly the same (e.g. cookies are sent etc), but before the
                # any branches that call reject()
                return self._accept(request)

            if request.is_secure():
                # Strict referer checking for HTTPS
                referer = request.META.get('HTTP_REFERER')
                if referer is None:
                    return self._reject(request, REASON_NO_REFERER)

                # Note that request.get_host() includes the port
                good_referer = 'https://%s/' % request.get_host()
                if not same_origin(referer, good_referer):
                    return self._reject(
                        request, REASON_BAD_REFERER % (referer, good_referer))

            # If the user didn't already have a CSRF cookie, then fall back to
            # the Django 1.1 method (hash of session ID), so a request is not
            # rejected if the form was sent to the user before upgrading to the
            # Django 1.2 method (session independent nonce)
            if cookie_is_new:
                try:
                    session_id = request.COOKIES[settings.SESSION_COOKIE_NAME]
                    csrf_token = _make_legacy_session_token(session_id)
                except KeyError:
                    # No CSRF cookie and no session cookie. For POST requests,
                    # we insist on a CSRF cookie, and in this way we can avoid
                    # all CSRF attacks, including login CSRF.
                    return self._reject(request, REASON_NO_COOKIE)
            else:
                csrf_token = request.META["CSRF_COOKIE"]

            # check incoming token
            request_csrf_token = request.POST.get('csrfmiddlewaretoken', "")
            if request_csrf_token == "":
                # Fall back to X-CSRFToken, to make things easier for AJAX
                request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

            if request_csrf_token != csrf_token:
                if cookie_is_new:
                    # probably a problem setting the CSRF cookie
                    return self._reject(request, REASON_NO_CSRF_COOKIE)
                else:
                    return self._reject(request, REASON_BAD_TOKEN)

        return self._accept(request)
Пример #33
0
    def process_view(self, request, callback, callback_args, callback_kwargs):
        if getattr(request, 'csrf_processing_done', False):
            return None

        try:
            request.META["CSRF_COOKIE"] = _sanitize_token(
                request.COOKIES[settings.CSRF_COOKIE_NAME])
            cookie_is_new = False
        except KeyError:
            request.META["CSRF_COOKIE"] = _get_new_csrf_key()
            cookie_is_new = True

        if getattr(callback, 'csrf_exempt', False):
            return None

        if request.method == 'POST':
            if getattr(request, '_dont_enforce_csrf_checks', False):
                return self._accept(request)
            # let initial signed requests pass
            if 'signed_request' in request.POST:
                post = request.POST.copy()
                post.pop('signed_request')
                if len(post) == 0:
                    return self._accept(request)

            if request.is_secure() and getattr(settings,
                                               'HTTPS_REFERER_REQUIRED', True):
                referer = request.META.get('HTTP_REFERER')
                if referer is None:
                    logger.warning('Forbidden (%s): %s' %
                                   (REASON_NO_REFERER, request.path),
                                   extra={
                                       'status_code': 403,
                                       'request': request,
                                   })
                    return self._reject(request, REASON_NO_REFERER)

                # Note that request.get_host() includes the port
                good_referer = 'https://%s/' % request.get_host()
                if not same_origin(referer, good_referer):
                    reason = REASON_BAD_REFERER % (referer, good_referer)
                    logger.warning('Forbidden (%s): %s' %
                                   (reason, request.path),
                                   extra={
                                       'status_code': 403,
                                       'request': request,
                                   })
                    return self._reject(request, reason)

            if cookie_is_new:
                try:
                    session_id = request.COOKIES[settings.SESSION_COOKIE_NAME]
                    csrf_token = _make_legacy_session_token(session_id)
                except KeyError:
                    logger.warning('Forbidden (%s): %s' %
                                   (REASON_NO_COOKIE, request.path),
                                   extra={
                                       'status_code': 403,
                                       'request': request,
                                   })
                    return self._reject(request, REASON_NO_COOKIE)
            else:
                csrf_token = request.META["CSRF_COOKIE"]

            # check incoming token
            request_csrf_token = request.POST.get('csrfmiddlewaretoken', None)
            if not request_csrf_token:
                request_csrf_token = request.POST.get('state', '')
            if request_csrf_token == "":
                # Fall back to X-CSRFToken, to make things easier for AJAX
                request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

            if not constant_time_compare(request_csrf_token, csrf_token):
                if cookie_is_new:
                    # probably a problem setting the CSRF cookie
                    logger.warning('Forbidden (%s): %s' %
                                   (REASON_NO_CSRF_COOKIE, request.path),
                                   extra={
                                       'status_code': 403,
                                       'request': request,
                                   })
                    return self._reject(request, REASON_NO_CSRF_COOKIE)
                else:
                    logger.warning('Forbidden (%s): %s' %
                                   (REASON_BAD_TOKEN, request.path),
                                   extra={
                                       'status_code': 403,
                                       'request': request,
                                   })
                    return self._reject(request, REASON_BAD_TOKEN)

        return self._accept(request)
Пример #34
0
    def process_view(self, request, callback, callback_args, callback_kwargs):

        if getattr(request, 'csrf_processing_done', False):
            return None

        # If the user doesn't have a CSRF cookie, generate one and store it in the
        # request, so it's available to the view.  We'll store it in a cookie when
        # we reach the response.
        try:
            # In case of cookies from untrusted sources, we strip anything
            # dangerous at this point, so that the cookie + token will have the
            # same, sanitized value.
            request.META["CSRF_COOKIE"] = _sanitize_token(request.COOKIES[settings.CSRF_COOKIE_NAME])
            cookie_is_new = False
        except KeyError:
            # No cookie, so create one.  This will be sent with the next
            # response.
            request.META["CSRF_COOKIE"] = _get_new_csrf_key()
            # Set a flag to allow us to fall back and allow the session id in
            # place of a CSRF cookie for this request only.
            cookie_is_new = True

        # Wait until request.META["CSRF_COOKIE"] has been manipulated before
        # bailing out, so that get_token still works
        if getattr(callback, 'csrf_exempt', False):
            return None

        if request.method == 'POST':
            if getattr(request, '_dont_enforce_csrf_checks', False):
                # Mechanism to turn off CSRF checks for test suite.  It comes after
                # the creation of CSRF cookies, so that everything else continues to
                # work exactly the same (e.g. cookies are sent etc), but before the
                # any branches that call reject()
                return self._accept(request)

            if request.is_secure():
                # Suppose user visits http://example.com/
                # An active network attacker,(man-in-the-middle, MITM) sends a
                # POST form which targets https://example.com/detonate-bomb/ and
                # submits it via javascript.
                #
                # The attacker will need to provide a CSRF cookie and token, but
                # that is no problem for a MITM and the session independent
                # nonce we are using. So the MITM can circumvent the CSRF
                # protection. This is true for any HTTP connection, but anyone
                # using HTTPS expects better!  For this reason, for
                # https://example.com/ we need additional protection that treats
                # http://example.com/ as completely untrusted.  Under HTTPS,
                # Barth et al. found that the Referer header is missing for
                # same-domain requests in only about 0.2% of cases or less, so
                # we can use strict Referer checking.
                referer = request.META.get('HTTP_REFERER')
                if referer is None:
                    logger.warning('Forbidden (%s): %s' % (REASON_NO_REFERER, request.path),
                        extra={
                            'status_code': 403,
                            'request': request,
                        }
                    )
                    return self._reject(request, REASON_NO_REFERER)

                # Note that request.get_host() includes the port
                good_referer = 'https://%s/' % request.get_host()
                if not same_origin(referer, good_referer):
                    reason = REASON_BAD_REFERER % (referer, good_referer)
                    logger.warning('Forbidden (%s): %s' % (reason, request.path),
                        extra={
                            'status_code': 403,
                            'request': request,
                        }
                    )
                    return self._reject(request, reason)

            # If the user didn't already have a CSRF cookie, then fall back to
            # the Django 1.1 method (hash of session ID), so a request is not
            # rejected if the form was sent to the user before upgrading to the
            # Django 1.2 method (session independent nonce)
            if cookie_is_new:
                try:
                    session_id = request.COOKIES[settings.SESSION_COOKIE_NAME]
                    csrf_token = _make_legacy_session_token(session_id)
                except KeyError:
                    # No CSRF cookie and no session cookie. For POST requests,
                    # we insist on a CSRF cookie, and in this way we can avoid
                    # all CSRF attacks, including login CSRF.
                    logger.warning('Forbidden (%s): %s' % (REASON_NO_COOKIE, request.path),
                        extra={
                            'status_code': 403,
                            'request': request,
                        }
                    )
                    return self._reject(request, REASON_NO_COOKIE)
            else:
                csrf_token = request.META["CSRF_COOKIE"]

            # check incoming token
            request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
            if request_csrf_token == "":
                # Fall back to X-CSRFToken, to make things easier for AJAX
                request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

            if not constant_time_compare(request_csrf_token, csrf_token):
                if cookie_is_new:
                    # probably a problem setting the CSRF cookie
                    logger.warning('Forbidden (%s): %s' % (REASON_NO_CSRF_COOKIE, request.path),
                        extra={
                            'status_code': 403,
                            'request': request,
                        }
                    )
                    return self._reject(request, REASON_NO_CSRF_COOKIE)
                else:
                    logger.warning('Forbidden (%s): %s' % (REASON_BAD_TOKEN, request.path),
                        extra={
                            'status_code': 403,
                            'request': request,
                        }
                    )
                    return self._reject(request, REASON_BAD_TOKEN)

        return self._accept(request)
Пример #35
0
    def process_view(self, request, callback, callback_args, callback_kwargs):

        if getattr(request, 'csrf_processing_done', False):
            return None

        # If the user doesn't have a CSRF cookie, generate one and store it in the
        # request, so it's available to the view.  We'll store it in a cookie when
        # we reach the response.
        try:
            # In case of cookies from untrusted sources, we strip anything
            # dangerous at this point, so that the cookie + token will have the
            # same, sanitized value.
            request.META["CSRF_COOKIE"] = _sanitize_token(
                request.COOKIES[settings.CSRF_COOKIE_NAME])
            cookie_is_new = False
        except KeyError:
            # No cookie, so create one.  This will be sent with the next
            # response.
            request.META["CSRF_COOKIE"] = _get_new_csrf_key()
            # Set a flag to allow us to fall back and allow the session id in
            # place of a CSRF cookie for this request only.
            cookie_is_new = True

        # Wait until request.META["CSRF_COOKIE"] has been manipulated before
        # bailing out, so that get_token still works
        if getattr(callback, 'csrf_exempt', False):
            return None

        if request.method == 'POST':
            if getattr(request, '_dont_enforce_csrf_checks', False):
                # Mechanism to turn off CSRF checks for test suite.  It comes after
                # the creation of CSRF cookies, so that everything else continues to
                # work exactly the same (e.g. cookies are sent etc), but before the
                # any branches that call reject()
                return self._accept(request)

            if request.is_secure():
                # Suppose user visits http://example.com/
                # An active network attacker,(man-in-the-middle, MITM) sends a
                # POST form which targets https://example.com/detonate-bomb/ and
                # submits it via javascript.
                #
                # The attacker will need to provide a CSRF cookie and token, but
                # that is no problem for a MITM and the session independent
                # nonce we are using. So the MITM can circumvent the CSRF
                # protection. This is true for any HTTP connection, but anyone
                # using HTTPS expects better!  For this reason, for
                # https://example.com/ we need additional protection that treats
                # http://example.com/ as completely untrusted.  Under HTTPS,
                # Barth et al. found that the Referer header is missing for
                # same-domain requests in only about 0.2% of cases or less, so
                # we can use strict Referer checking.
                referer = request.META.get('HTTP_REFERER')
                if referer is None:
                    logger.warning('Forbidden (%s): %s' %
                                   (REASON_NO_REFERER, request.path),
                                   extra={
                                       'status_code': 403,
                                       'request': request,
                                   })
                    return self._reject(request, REASON_NO_REFERER)

                # Note that request.get_host() includes the port
                good_referer = 'https://%s/' % request.get_host()
                if not same_origin(referer, good_referer):
                    reason = REASON_BAD_REFERER % (referer, good_referer)
                    logger.warning('Forbidden (%s): %s' %
                                   (reason, request.path),
                                   extra={
                                       'status_code': 403,
                                       'request': request,
                                   })
                    return self._reject(request, reason)

            # If the user didn't already have a CSRF cookie, then fall back to
            # the Django 1.1 method (hash of session ID), so a request is not
            # rejected if the form was sent to the user before upgrading to the
            # Django 1.2 method (session independent nonce)
            if cookie_is_new:
                try:
                    session_id = request.COOKIES[settings.SESSION_COOKIE_NAME]
                    csrf_token = _make_legacy_session_token(session_id)
                except KeyError:
                    # No CSRF cookie and no session cookie. For POST requests,
                    # we insist on a CSRF cookie, and in this way we can avoid
                    # all CSRF attacks, including login CSRF.
                    logger.warning('Forbidden (%s): %s' %
                                   (REASON_NO_COOKIE, request.path),
                                   extra={
                                       'status_code': 403,
                                       'request': request,
                                   })
                    return self._reject(request, REASON_NO_COOKIE)
            else:
                csrf_token = request.META["CSRF_COOKIE"]

            # check incoming token
            request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
            if request_csrf_token == "":
                # Fall back to X-CSRFToken, to make things easier for AJAX
                request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

            if not constant_time_compare(request_csrf_token, csrf_token):
                if cookie_is_new:
                    # probably a problem setting the CSRF cookie
                    logger.warning('Forbidden (%s): %s' %
                                   (REASON_NO_CSRF_COOKIE, request.path),
                                   extra={
                                       'status_code': 403,
                                       'request': request,
                                   })
                    return self._reject(request, REASON_NO_CSRF_COOKIE)
                else:
                    logger.warning('Forbidden (%s): %s' %
                                   (REASON_BAD_TOKEN, request.path),
                                   extra={
                                       'status_code': 403,
                                       'request': request,
                                   })
                    return self._reject(request, REASON_BAD_TOKEN)

        return self._accept(request)
Пример #36
0
    def process_view(self, request, callback, callback_args, callback_kwargs):

        if getattr(request, 'csrf_processing_done', False):
            return None

        try:
            csrf_token = _sanitize_token(
                request.COOKIES[settings.CSRF_COOKIE_NAME])
            # Use same token next time
            request.META['CSRF_COOKIE'] = csrf_token
        except KeyError:
            csrf_token = None
            # Generate token and store it in the request, so it's
            # available to the view.
            request.META["CSRF_COOKIE"] = _get_new_csrf_key()

        # Wait until request.META["CSRF_COOKIE"] has been manipulated before
        # bailing out, so that get_token still works
        if getattr(callback, 'csrf_exempt', False):
            return None

        # Assume that anything not defined as 'safe' by RFC2616 needs protection
        if request.method not in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
            if getattr(request, '_dont_enforce_csrf_checks', False):
                # Mechanism to turn off CSRF checks for test suite.
                # It comes after the creation of CSRF cookies, so that
                # everything else continues to work exactly the same
                # (e.g. cookies are sent, etc.), but before any
                # branches that call reject().
                return self._accept(request)

            if request.is_secure():
                # Suppose user visits http://example.com/
                # An active network attacker (man-in-the-middle, MITM) sends a
                # POST form that targets https://example.com/detonate-bomb/ and
                # submits it via JavaScript.
                #
                # The attacker will need to provide a CSRF cookie and token, but
                # that's no problem for a MITM and the session-independent
                # nonce we're using. So the MITM can circumvent the CSRF
                # protection. This is true for any HTTP connection, but anyone
                # using HTTPS expects better! For this reason, for
                # https://example.com/ we need additional protection that treats
                # http://example.com/ as completely untrusted. Under HTTPS,
                # Barth et al. found that the Referer header is missing for
                # same-domain requests in only about 0.2% of cases or less, so
                # we can use strict Referer checking.
                referer = request.META.get('HTTP_REFERER')
                if referer is None:
                    return self._reject(request, REASON_NO_REFERER)

                # Note that request.get_host() includes the port.
                good_referer = 'https://%s/' % request.get_host()
                if not same_origin(referer, good_referer):
                    reason = REASON_BAD_REFERER % (referer, good_referer)
                    return self._reject(request, reason)

            if csrf_token is None:
                # No CSRF cookie. For POST requests, we insist on a CSRF cookie,
                # and in this way we can avoid all CSRF attacks, including login
                # CSRF.
                return self._reject(request, REASON_NO_CSRF_COOKIE)

            # Check non-cookie token for match.
            request_csrf_token = ""
            if request.method == "POST":
                request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')

            if request_csrf_token == "":
                # Fall back to X-CSRFToken, to make things easier for AJAX,
                # and possible for PUT/DELETE.
                request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

            if not constant_time_compare(request_csrf_token, csrf_token):
                return self._reject(request, REASON_BAD_TOKEN)

        return self._accept(request)
Пример #37
0
    def process_view(self, request, callback, callback_args, callback_kwargs):

        if getattr(request, 'csrf_processing_done', False):
            return None

        try:
            csrf_token = _sanitize_token(
                request.COOKIES[settings.CSRF_COOKIE_NAME])
            # Use same token next time
            request.META['CSRF_COOKIE'] = csrf_token
        except KeyError:
            csrf_token = None
            # Generate token and store it in the request, so it's available to the view.
            request.META["CSRF_COOKIE"] = _get_new_csrf_key()

        # Wait until request.META["CSRF_COOKIE"] has been manipulated before
        # bailing out, so that get_token still works
        if getattr(callback, 'csrf_exempt', False):
            return None

        if request.method == 'POST':
            if getattr(request, '_dont_enforce_csrf_checks', False):
                # Mechanism to turn off CSRF checks for test suite.  It comes after
                # the creation of CSRF cookies, so that everything else continues to
                # work exactly the same (e.g. cookies are sent etc), but before the
                # any branches that call reject()
                return self._accept(request)

            if request.is_secure():
                # Suppose user visits http://example.com/
                # An active network attacker,(man-in-the-middle, MITM) sends a
                # POST form which targets https://example.com/detonate-bomb/ and
                # submits it via javascript.
                #
                # The attacker will need to provide a CSRF cookie and token, but
                # that is no problem for a MITM and the session independent
                # nonce we are using. So the MITM can circumvent the CSRF
                # protection. This is true for any HTTP connection, but anyone
                # using HTTPS expects better!  For this reason, for
                # https://example.com/ we need additional protection that treats
                # http://example.com/ as completely untrusted.  Under HTTPS,
                # Barth et al. found that the Referer header is missing for
                # same-domain requests in only about 0.2% of cases or less, so
                # we can use strict Referer checking.
                referer = request.META.get('HTTP_REFERER')
                if referer is None:
                    logger.warning('Forbidden (%s): %s' %
                                   (REASON_NO_REFERER, request.path),
                                   extra={
                                       'status_code': 403,
                                       'request': request,
                                   })
                    return self._reject(request, REASON_NO_REFERER)

                # Note that request.get_host() includes the port
                good_referer = 'https://%s/' % request.get_host()
                if not same_origin(referer, good_referer):
                    reason = REASON_BAD_REFERER % (referer, good_referer)
                    logger.warning('Forbidden (%s): %s' %
                                   (reason, request.path),
                                   extra={
                                       'status_code': 403,
                                       'request': request,
                                   })
                    return self._reject(request, reason)

            if csrf_token is None:
                # No CSRF cookie. For POST requests, we insist on a CSRF cookie,
                # and in this way we can avoid all CSRF attacks, including login
                # CSRF.
                logger.warning('Forbidden (%s): %s' %
                               (REASON_NO_CSRF_COOKIE, request.path),
                               extra={
                                   'status_code': 403,
                                   'request': request,
                               })
                return self._reject(request, REASON_NO_CSRF_COOKIE)

            # check incoming token
            request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
            if request_csrf_token == "":
                # Fall back to X-CSRFToken, to make things easier for AJAX
                request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

            if not constant_time_compare(request_csrf_token, csrf_token):
                logger.warning('Forbidden (%s): %s' %
                               (REASON_BAD_TOKEN, request.path),
                               extra={
                                   'status_code': 403,
                                   'request': request,
                               })
                return self._reject(request, REASON_BAD_TOKEN)

        return self._accept(request)
Пример #38
0
    def process_view(self, request, callback, callback_args, callback_kwargs):

        if getattr(request, 'csrf_processing_done', False):
            return None

        try:
            csrf_token = _sanitize_token(
                request.COOKIES[settings.CSRF_COOKIE_NAME])
            request.META['CSRF_COOKIE'] = csrf_token
        except KeyError:
            csrf_token = None
            request.META["CSRF_COOKIE"] = get_random_string(CSRF_KEY_LENGTH)

        if getattr(callback, 'csrf_exempt', False):
            return None

        if request.method not in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
            if getattr(request, '_dont_enforce_csrf_checks', False):
                return self._accept(request)

            if request.is_secure():

                referer = request.META.get('HTTP_REFERER')
                if referer is None:
                    logger.warning('Forbidden (%s): %s',
                                   REASON_NO_REFERER, request.path,
                        extra={
                            'status_code': 403,
                            'request': request,
                        }
                    )
                    return self._reject(request, REASON_NO_REFERER)

                good_referer = 'https://%s/' % request.get_host()
                if not same_origin(referer, good_referer):
                    reason = REASON_BAD_REFERER % (referer, good_referer)
                    logger.warning('Forbidden (%s): %s', reason, request.path,
                        extra={
                            'status_code': 403,
                            'request': request,
                        }
                    )
                    return self._reject(request, reason)

            if csrf_token is None:
                logger.warning('Forbidden (%s): %s',
                               REASON_NO_CSRF_COOKIE, request.path,
                    extra={
                        'status_code': 403,
                        'request': request,
                    }
                )

                _send_email_about_cookies(request, REASON_NO_CSRF_COOKIE)

                return self._reject(request, REASON_NO_CSRF_COOKIE)

            request_csrf_token = ""
            if request.method == "POST":
                request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')

            if request_csrf_token == "":
                request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

            if not constant_time_compare(request_csrf_token, csrf_token):
                logger.warning('Forbidden (%s): %s',
                               REASON_BAD_TOKEN, request.path,
                    extra={
                        'status_code': 403,
                        'request': request,
                    }
                )
                return self._reject(request, REASON_BAD_TOKEN)

        return self._accept(request)
Пример #39
0
    def handle(self, request, data):
        if 'user_name' in request.session:
            if request.session['user_name'] != data['username']:
                # To avoid reusing another user's session, create a
                # new, empty session if the existing session
                # corresponds to a different authenticated user.
                request.session.flush()
        # Always cycle the session key when viewing the login form to
        # prevent session fixation
        request.session.cycle_key()

        # For now we'll allow fallback to OPENSTACK_KEYSTONE_URL if the
        # form post doesn't include a region.
        # jt
        default_region = (settings.OPENSTACK_KEYSTONE_URL, "Default Region")
        regions = getattr(settings, 'AVAILABLE_REGIONS', [default_region])
        #endpoint = data.get('region', None) or settings.OPENSTACK_KEYSTONE_URL
        #region_name = dict(self.fields['region'].choices)[endpoint]
        region_name = data.get('region', None) or "Default Region"
        endpoint = [r[0] for r in regions if r[1] == region_name][0]
        request.session['region_endpoint'] = endpoint
        request.session['region_name'] = region_name

        redirect_to = request.REQUEST.get(REDIRECT_FIELD_NAME, None)
        # Make sure the requested redirect matches the protocol,
        # domain, and port of this request
        if redirect_to and not same_origin(
                request.build_absolute_uri(redirect_to),
                request.build_absolute_uri()):
            redirect_to = None

        if data.get('tenant', None):
            try:
                token = api.token_create(request, data.get('tenant'),
                                         data['username'], data['password'])
                tenants = api.tenant_list_for_token(request, token.id)
            except:
                msg = _('Unable to authenticate for that project.')
                exceptions.handle(request, message=msg, escalate=True)
            _set_session_data(request, token)
            user = users.get_user_from_request(request)
            redirect = redirect_to or base.Horizon.get_user_home(user)
            return shortcuts.redirect(redirect)

        elif data.get('username', None):
            try:
                unscoped_token = api.token_create(request, '',
                                                  data['username'],
                                                  data['password'])
            except keystone_exceptions.Unauthorized:
                exceptions.handle(request, _('Invalid user name or password.'))
            except:
                # If we get here we don't want to show a stack trace to the
                # user. However, if we fail here, there may be bad session
                # data that's been cached already.
                request.user_logout()
                exceptions.handle(request,
                                  message=_("An error occurred authenticating."
                                            " Please try again later."),
                                  escalate=True)

            # Unscoped token
            request.session['unscoped_token'] = unscoped_token.id
            request.user.username = data['username']

            # Get the tenant list, and log in using first tenant
            # FIXME (anthony): add tenant chooser here?
            try:
                tenants = api.tenant_list_for_token(request, unscoped_token.id)
            except:
                exceptions.handle(request)
                tenants = []

            # Abort if there are no valid tenants for this user
            if not tenants:
                messages.error(request,
                               _('You are not authorized for any projects.') %
                               {"user": data['username']},
                               extra_tags="login")
                return

            # Create a token.
            # NOTE(gabriel): Keystone can return tenants that you're
            # authorized to administer but not to log into as a user, so in
            # the case of an Unauthorized error we should iterate through
            # the tenants until one succeeds or we've failed them all.
            while tenants:
                tenant = tenants.pop()
                try:
                    token = api.token_create_scoped(request, tenant.id,
                                                    unscoped_token.id)
                    break
                except:
                    # This will continue for recognized Unauthorized
                    # exceptions from keystoneclient.
                    exceptions.handle(request, ignore=True)
                    token = None
            if token is None:
                raise exceptions.NotAuthorized(
                    _("You are not authorized for any available projects."))

            _set_session_data(request, token)
            user = users.get_user_from_request(request)
        redirect = redirect_to or base.Horizon.get_user_home(user)
        return shortcuts.redirect(redirect)
Пример #40
0
    def process_view(self, request, callback, callback_args, callback_kwargs):
        if getattr(request, 'csrf_processing_done', False):
            return None

        try:
            request.META["CSRF_COOKIE"] = _sanitize_token(request.COOKIES[settings.CSRF_COOKIE_NAME])
            cookie_is_new = False
        except KeyError:
            request.META["CSRF_COOKIE"] = _get_new_csrf_key()
            cookie_is_new = True

        if getattr(callback, 'csrf_exempt', False):
            return None

        if request.method == 'POST':
            if getattr(request, '_dont_enforce_csrf_checks', False):
                return self._accept(request)

            if request.is_secure() and getattr(settings, 'HTTPS_REFERER_REQUIRED', True):
                referer = request.META.get('HTTP_REFERER')
                if referer is None :
                    logger.warning('Forbidden (%s): %s' % (REASON_NO_REFERER, request.path),
                        extra={
                            'status_code': 403,
                            'request': request,
                        }
                    )
                    return self._reject(request, REASON_NO_REFERER)

                # Note that request.get_host() includes the port
                good_referer = 'https://%s/' % request.get_host()
                if not same_origin(referer, good_referer):
                    reason = REASON_BAD_REFERER % (referer, good_referer)
                    logger.warning('Forbidden (%s): %s' % (reason, request.path),
                        extra={
                            'status_code': 403,
                            'request': request,
                        }
                    )
                    return self._reject(request, reason)

            if cookie_is_new:
                try:
                    session_id = request.COOKIES[settings.SESSION_COOKIE_NAME]
                    csrf_token = _make_legacy_session_token(session_id)
                except KeyError:
                    logger.warning('Forbidden (%s): %s' % (REASON_NO_COOKIE, request.path),
                        extra={
                            'status_code': 403,
                            'request': request,
                        }
                    )
                    return self._reject(request, REASON_NO_COOKIE)
            else:
                csrf_token = request.META["CSRF_COOKIE"]

            # check incoming token
            request_csrf_token = request.POST.get('csrfmiddlewaretoken', None) 
            if not request_csrf_token:
                request_csrf_token = request.POST.get('state', '')
            if request_csrf_token == "":
                # Fall back to X-CSRFToken, to make things easier for AJAX
                request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

            if not constant_time_compare(request_csrf_token, csrf_token):
                if cookie_is_new:
                    # probably a problem setting the CSRF cookie
                    logger.warning('Forbidden (%s): %s' % (REASON_NO_CSRF_COOKIE, request.path),
                        extra={
                            'status_code': 403,
                            'request': request,
                        }
                    )
                    return self._reject(request, REASON_NO_CSRF_COOKIE)
                else:
                    logger.warning('Forbidden (%s): %s' % (REASON_BAD_TOKEN, request.path),
                        extra={
                            'status_code': 403,
                            'request': request,
                        }
                    )
                    return self._reject(request, REASON_BAD_TOKEN)

        return self._accept(request)
Пример #41
0
    def process_view(self, request, callback, callback_args, callback_kwargs):

        if getattr(request, 'csrf_processing_done', False):
            return None

        try:
            csrf_token = _sanitize_token(request.COOKIES[settings.CSRF_COOKIE_NAME])
            # Use same token next time
            request.META['CSRF_COOKIE'] = csrf_token
        except KeyError:
            csrf_token = None
            # Generate token and store it in the request, so it's available to the view.
            request.META["CSRF_COOKIE"] = _get_new_csrf_key()

        # Wait until request.META["CSRF_COOKIE"] has been manipulated before
        # bailing out, so that get_token still works
        if getattr(callback, 'csrf_exempt', False):
            return None

        if request.method == 'POST':
            if getattr(request, '_dont_enforce_csrf_checks', False):
                # Mechanism to turn off CSRF checks for test suite.  It comes after
                # the creation of CSRF cookies, so that everything else continues to
                # work exactly the same (e.g. cookies are sent etc), but before the
                # any branches that call reject()
                return self._accept(request)

            if request.is_secure():
                # Suppose user visits http://example.com/
                # An active network attacker,(man-in-the-middle, MITM) sends a
                # POST form which targets https://example.com/detonate-bomb/ and
                # submits it via javascript.
                #
                # The attacker will need to provide a CSRF cookie and token, but
                # that is no problem for a MITM and the session independent
                # nonce we are using. So the MITM can circumvent the CSRF
                # protection. This is true for any HTTP connection, but anyone
                # using HTTPS expects better!  For this reason, for
                # https://example.com/ we need additional protection that treats
                # http://example.com/ as completely untrusted.  Under HTTPS,
                # Barth et al. found that the Referer header is missing for
                # same-domain requests in only about 0.2% of cases or less, so
                # we can use strict Referer checking.
                referer = request.META.get('HTTP_REFERER')
                if referer is None:
                    logger.warning('Forbidden (%s): %s' % (REASON_NO_REFERER, request.path),
                        extra={
                            'status_code': 403,
                            'request': request,
                        }
                    )
                    return self._reject(request, REASON_NO_REFERER)

                # Note that request.get_host() includes the port
                good_referer = 'https://%s/' % request.get_host()
                if not same_origin(referer, good_referer):
                    reason = REASON_BAD_REFERER % (referer, good_referer)
                    logger.warning('Forbidden (%s): %s' % (reason, request.path),
                        extra={
                            'status_code': 403,
                            'request': request,
                        }
                    )
                    return self._reject(request, reason)

            if csrf_token is None:
                # No CSRF cookie. For POST requests, we insist on a CSRF cookie,
                # and in this way we can avoid all CSRF attacks, including login
                # CSRF.
                logger.warning('Forbidden (%s): %s' % (REASON_NO_CSRF_COOKIE, request.path),
                    extra={
                        'status_code': 403,
                        'request': request,
                    }
                )
                return self._reject(request, REASON_NO_CSRF_COOKIE)

            # check incoming token
            request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
            if request_csrf_token == "":
                # Fall back to X-CSRFToken, to make things easier for AJAX
                request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

            if not constant_time_compare(request_csrf_token, csrf_token):
                logger.warning('Forbidden (%s): %s' % (REASON_BAD_TOKEN, request.path),
                    extra={
                        'status_code': 403,
                        'request': request,
                    }
                )
                return self._reject(request, REASON_BAD_TOKEN)

        return self._accept(request)