1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
|
commit c9e3b9949cd55f090591fbdc4a114fcb8368b6d9
Author: Preston Holmes <preston@ptone.com>
Date: Mon Aug 11 12:04:53 2014 -0400
[1.4.x] Fixed #23066 -- Modified RemoteUserMiddleware to logout on REMOTE_USE change.
This is a security fix. Disclosure following shortly.
Index: python-django-1.2.3/django/contrib/auth/middleware.py
===================================================================
--- python-django-1.2.3.orig/django/contrib/auth/middleware.py 2014-08-29 19:49:28.000000000 +0200
+++ python-django-1.2.3/django/contrib/auth/middleware.py 2014-08-29 19:49:28.000000000 +0200
@@ -1,4 +1,5 @@
from django.contrib import auth
+from django.contrib.auth.backends import RemoteUserBackend
from django.core.exceptions import ImproperlyConfigured
@@ -48,9 +49,11 @@
try:
username = request.META[self.header]
except KeyError:
- # If specified header doesn't exist then return (leaving
- # request.user set to AnonymousUser by the
- # AuthenticationMiddleware).
+ # If specified header doesn't exist then remove any existing
+ # authenticated remote-user, or return (leaving request.user set to
+ # AnonymousUser by the AuthenticationMiddleware).
+ if request.user.is_authenticated():
+ self._remove_invalid_user(request)
return
# If the user is already authenticated and that user is the user we are
# getting passed in the headers, then the correct user is already
@@ -58,6 +61,11 @@
if request.user.is_authenticated():
if request.user.username == self.clean_username(username, request):
return
+ else:
+ # An authenticated user is associated with the request, but
+ # it does not match the authorized user in the header.
+ self._remove_invalid_user(request)
+
# We are seeing this user for the first time in this session, attempt
# to authenticate the user.
user = auth.authenticate(remote_user=username)
@@ -79,3 +87,17 @@
except AttributeError: # Backend has no clean_username method.
pass
return username
+
+ def _remove_invalid_user(self, request):
+ """
+ Removes the current authenticated user in the request which is invalid
+ but only if the user is authenticated via the RemoteUserBackend.
+ """
+ try:
+ stored_backend = auth.load_backend(request.session.get(auth.BACKEND_SESSION_KEY, ''))
+ except ImproperlyConfigured:
+ # backend failed to load
+ auth.logout(request)
+ else:
+ if isinstance(stored_backend, RemoteUserBackend):
+ auth.logout(request)
Index: python-django-1.2.3/django/contrib/auth/tests/remote_user.py
===================================================================
--- python-django-1.2.3.orig/django/contrib/auth/tests/remote_user.py 2014-08-29 19:49:28.000000000 +0200
+++ python-django-1.2.3/django/contrib/auth/tests/remote_user.py 2014-08-29 19:49:28.000000000 +0200
@@ -92,6 +92,24 @@
response = self.client.get('/remote_user/', REMOTE_USER=self.known_user)
self.assertEqual(default_login, response.context['user'].last_login)
+ def test_user_switch_forces_new_login(self):
+ """
+ Tests that if the username in the header changes between requests
+ that the original user is logged out
+ """
+ User.objects.create(username='knownuser')
+ # Known user authenticates
+ response = self.client.get('/remote_user/',
+ **{'REMOTE_USER': self.known_user})
+ self.assertEqual(response.context['user'].username, 'knownuser')
+ # During the session, the REMOTE_USER changes to a different user.
+ response = self.client.get('/remote_user/',
+ **{'REMOTE_USER': "newnewuser"})
+ # Ensure that the current user is not the prior remote_user
+ # In backends that create a new user, username is "newnewuser"
+ # In backends that do not create new users, it is '' (anonymous user)
+ self.assertNotEqual(response.context['user'].username, 'knownuser')
+
def tearDown(self):
"""Restores settings to avoid breaking other tests."""
settings.MIDDLEWARE_CLASSES = self.curr_middleware
|