diff options
Diffstat (limited to 'django')
| -rw-r--r-- | django/contrib/auth/handlers/modwsgi.py | 37 |
1 files changed, 30 insertions, 7 deletions
diff --git a/django/contrib/auth/handlers/modwsgi.py b/django/contrib/auth/handlers/modwsgi.py index 591ec72cb4..086db89fc8 100644 --- a/django/contrib/auth/handlers/modwsgi.py +++ b/django/contrib/auth/handlers/modwsgi.py @@ -4,24 +4,47 @@ from django.contrib import auth UserModel = auth.get_user_model() +def _get_user(username): + """ + Return the UserModel instance for `username`. + + If no matching user exists, or if the user is inactive, return None, in + which case the default password hasher is run to mitigate timing attacks. + """ + try: + user = UserModel._default_manager.get_by_natural_key(username) + except UserModel.DoesNotExist: + user = None + else: + if not user.is_active: + user = None + + if user is None: + # Run the default password hasher once to reduce the timing difference + # between existing/active and nonexistent/inactive users (#20760). + UserModel().set_password("") + + return user + + def check_password(environ, username, password): """ Authenticate against Django's auth database. mod_wsgi docs specify None, True, False as return value depending on whether the user exists and authenticates. + + Return None if the user does not exist, return False if the user exists but + password is not correct, and return True otherwise. + """ # db connection state is managed similarly to the wsgi handler # as mod_wsgi may call these functions outside of a request/response cycle db.reset_queries() try: - try: - user = UserModel._default_manager.get_by_natural_key(username) - except UserModel.DoesNotExist: - return None - if not user.is_active: - return None - return user.check_password(password) + user = _get_user(username) + if user: + return user.check_password(password) finally: db.close_old_connections() |
