Fixed #32329 -- Made CsrfViewMiddleware catch more specific UnreadablePostError.

Thanks Chris Jerdonek for the review.
This commit is contained in:
Virtosu Bogdan 2021-07-23 12:26:22 +02:00 committed by Mariusz Felisiak
parent 852fa7617e
commit 00ea883ef5
2 changed files with 19 additions and 6 deletions

View File

@ -11,6 +11,7 @@ from urllib.parse import urlparse
from django.conf import settings
from django.core.exceptions import DisallowedHost, ImproperlyConfigured
from django.http import UnreadablePostError
from django.http.request import HttpHeaders
from django.urls import get_callable
from django.utils.cache import patch_vary_headers
@ -342,7 +343,7 @@ class CsrfViewMiddleware(MiddlewareMixin):
if request.method == 'POST':
try:
request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
except OSError:
except UnreadablePostError:
# 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

View File

@ -3,7 +3,7 @@ import re
from django.conf import settings
from django.contrib.sessions.backends.cache import SessionStore
from django.core.exceptions import ImproperlyConfigured
from django.http import HttpRequest, HttpResponse
from django.http import HttpRequest, HttpResponse, UnreadablePostError
from django.middleware.csrf import (
CSRF_ALLOWED_CHARS, CSRF_SESSION_KEY, CSRF_TOKEN_LENGTH, REASON_BAD_ORIGIN,
REASON_CSRF_TOKEN_MISSING, REASON_NO_CSRF_COOKIE, CsrfViewMiddleware,
@ -728,10 +728,10 @@ class CsrfViewMiddlewareTestMixin:
req = self._get_request()
ensure_csrf_cookie_view(req)
def test_post_data_read_failure(self):
def test_reading_post_data_raises_unreadable_post_error(self):
"""
OSErrors during POST data reading are caught and treated as if the
POST data wasn't there.
An UnreadablePostError raised while reading the POST data should be
handled by the middleware.
"""
req = self._get_POST_request_with_token()
mw = CsrfViewMiddleware(post_form_view)
@ -740,7 +740,7 @@ class CsrfViewMiddlewareTestMixin:
self.assertIsNone(resp)
req = self._get_POST_request_with_token(request_class=PostErrorRequest)
req.post_error = OSError('error reading input data')
req.post_error = UnreadablePostError('Error reading input data.')
mw.process_request(req)
with self.assertLogs('django.security.csrf', 'WARNING') as cm:
resp = mw.process_view(req, post_form_view, (), {})
@ -750,6 +750,18 @@ class CsrfViewMiddlewareTestMixin:
'Forbidden (%s): ' % REASON_CSRF_TOKEN_MISSING,
)
def test_reading_post_data_raises_os_error(self):
"""
An OSError raised while reading the POST data should not be handled by
the middleware.
"""
mw = CsrfViewMiddleware(post_form_view)
req = self._get_POST_request_with_token(request_class=PostErrorRequest)
req.post_error = OSError('Deleted directories/Missing permissions.')
mw.process_request(req)
with self.assertRaises(OSError):
mw.process_view(req, post_form_view, (), {})
@override_settings(ALLOWED_HOSTS=['www.example.com'])
def test_bad_origin_bad_domain(self):
"""A request with a bad origin is rejected."""