Removed Django 1.1 fallback for CSRF checks.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@15948 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Luke Plant 2011-03-30 17:34:14 +00:00
parent 4550f95f29
commit 21ef64e34c
2 changed files with 26 additions and 99 deletions

View File

@ -34,7 +34,6 @@ _MAX_CSRF_KEY = 18446744073709551616L # 2 << 63
REASON_NO_REFERER = "Referer checking failed - no Referer."
REASON_BAD_REFERER = "Referer checking failed - %s does not match %s."
REASON_NO_COOKIE = "No CSRF or session cookie."
REASON_NO_CSRF_COOKIE = "CSRF cookie not set."
REASON_BAD_TOKEN = "CSRF token missing or incorrect."
@ -105,22 +104,14 @@ class CsrfViewMiddleware(object):
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
csrf_token = _sanitize_token(request.COOKIES[settings.CSRF_COOKIE_NAME])
# Use same token next time
request.META['CSRF_COOKIE'] = csrf_token
except KeyError:
# No cookie, so create one. This will be sent with the next
# response.
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()
# 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
@ -173,27 +164,17 @@ class CsrfViewMiddleware(object):
)
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"]
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', '')
@ -202,23 +183,13 @@ class CsrfViewMiddleware(object):
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)
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)

View File

@ -6,8 +6,6 @@ from django.http import HttpRequest, HttpResponse
from django.middleware.csrf import CsrfMiddleware, CsrfViewMiddleware
from django.views.decorators.csrf import csrf_exempt, csrf_view_exempt, requires_csrf_token
from django.core.context_processors import csrf
from django.contrib.sessions.middleware import SessionMiddleware
from django.utils.importlib import import_module
from django.conf import settings
from django.template import RequestContext, Template
@ -62,14 +60,6 @@ class CsrfMiddlewareTest(TestCase):
_csrf_id_cookie = "<1>\xc2\xa1"
_csrf_id = "1"
# This is a valid session token for this ID and secret key. This was generated using
# the old code that we're to be backwards-compatible with. Don't use the CSRF code
# to generate this hash, or we're merely testing the code against itself and not
# checking backwards-compatibility. This is also the output of (echo -n test1 | md5sum).
_session_token = "5a105e8b9d40e1329780d62ea2265d8a"
_session_id = "1"
_secret_key_for_session_test= "test"
def setUp(self):
self.save_warnings_state()
warnings.filterwarnings('ignore', category=DeprecationWarning,
@ -101,17 +91,6 @@ class CsrfMiddlewareTest(TestCase):
req.POST['csrfmiddlewaretoken'] = self._csrf_id
return req
def _get_POST_session_request_with_token(self):
req = self._get_POST_no_csrf_cookie_request()
req.COOKIES[settings.SESSION_COOKIE_NAME] = self._session_id
req.POST['csrfmiddlewaretoken'] = self._session_token
return req
def _get_POST_session_request_no_token(self):
req = self._get_POST_no_csrf_cookie_request()
req.COOKIES[settings.SESSION_COOKIE_NAME] = self._session_id
return req
def _check_token_present(self, response, csrf_id=None):
self.assertContains(response, "name='csrfmiddlewaretoken' value='%s'" % (csrf_id or self._csrf_id))
@ -226,10 +205,10 @@ class CsrfMiddlewareTest(TestCase):
self.assertEqual(resp_content, resp2.content)
# Check the request processing
def test_process_request_no_session_no_csrf_cookie(self):
def test_process_request_no_csrf_cookie(self):
"""
Check that if neither a CSRF cookie nor a session cookie are present,
the middleware rejects the incoming request. This will stop login CSRF.
Check that if no CSRF cookies is present, the middleware rejects the
incoming request. This will stop login CSRF.
"""
req = self._get_POST_no_csrf_cookie_request()
req2 = CsrfMiddleware().process_view(req, post_form_view, (), {})
@ -252,29 +231,6 @@ class CsrfMiddlewareTest(TestCase):
req2 = CsrfMiddleware().process_view(req, post_form_view, (), {})
self.assertEqual(None, req2)
def test_process_request_session_cookie_no_csrf_cookie_token(self):
"""
When no CSRF cookie exists, but the user has a session, check that a token
using the session cookie as a legacy CSRF cookie is accepted.
"""
orig_secret_key = settings.SECRET_KEY
settings.SECRET_KEY = self._secret_key_for_session_test
try:
req = self._get_POST_session_request_with_token()
req2 = CsrfMiddleware().process_view(req, post_form_view, (), {})
self.assertEqual(None, req2)
finally:
settings.SECRET_KEY = orig_secret_key
def test_process_request_session_cookie_no_csrf_cookie_no_token(self):
"""
Check that if a session cookie is present but no token and no CSRF cookie,
the request is rejected.
"""
req = self._get_POST_session_request_no_token()
req2 = CsrfMiddleware().process_view(req, post_form_view, (), {})
self.assertEqual(403, req2.status_code)
def test_process_request_csrf_cookie_no_token_exempt_view(self):
"""
Check that if a CSRF cookie is present and no token, but the csrf_exempt