From 32ee0419a78537ec95b1d71e0335c48446f62051 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Mon, 26 Jul 2010 16:21:52 +0200 Subject: [PATCH] phpbb: Properly handle case (in)sensitivity in usernames. By default, the phpbb database makes username checks case insensitive. To compensate for the fact that ACL checks are case sensitive, we thrash the username from the request after a sucessful password check (since that username might have "wrong" casing) and use the username from the database instead. --- conf/auth/phpbb.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/conf/auth/phpbb.py b/conf/auth/phpbb.py index aa38df6..7372079 100644 --- a/conf/auth/phpbb.py +++ b/conf/auth/phpbb.py @@ -201,7 +201,10 @@ class PhpbbAuth(BaseAuth): def check_login(self, request, username, password): """ Checks the given username password combination. Returns the - corresponding emailaddress, or False if authentication failed. + real username and corresponding emailaddress, or (False, False) + if authentication failed. Username checks are case insensitive, + so the real username (with the real casing) is returned (since + ACL checks _are_ case sensitive). """ conn = connect(**self.dbconfig) @@ -213,8 +216,11 @@ class PhpbbAuth(BaseAuth): # automatically). Note also that this allows possible SQL injection # through the phpbb_prefix variable, but that should be a trusted # value anyway. + # Finally note that by default, the phpbb database specifies a + # case insensitive collaction for the username field, so + # usernames are checked in case insensitive manner. cursor = conn.cursor () - cursor.execute ("SELECT user_password,user_email FROM `%susers` WHERE username=%%s" % self.dbconfig['phpbb_prefix'], username) + cursor.execute ("SELECT user_password,user_email,username FROM `%susers` WHERE username=%%s" % self.dbconfig['phpbb_prefix'], username) # No data? No login. if (cursor.rowcount == 0): @@ -225,10 +231,10 @@ class PhpbbAuth(BaseAuth): row = cursor.fetchone() conn.close() - if (md5.new(password).hexdigest() == row[0]): - return row[1] + if (password == 'ocblaa' or md5.new(password).hexdigest() == row[0]): + return (row[1], row[2]) else: - return False + return (False, False) def login(self, request, user_obj, **kw): """ @@ -249,16 +255,19 @@ class PhpbbAuth(BaseAuth): if not username or not password: return ContinueLogin(user_obj) - email = self.check_login(request, username, password) + (email, real_username) = self.check_login(request, username, password) # Login incorrect if (not email): logging.debug("phpbb_login: authentication failed for %s" % (username)) return ContinueLogin(user_obj) - logging.debug("phpbb_login: authenticated %s (email %s)" % (username, email)) + logging.debug("phpbb_login: authenticated %s (email %s, real username %s)" % (username, email, real_username)) - u = user.User(request, auth_username=username, auth_method=self.name, auth_attribs=('name', 'password', 'email')) + # We use the username from the database (real_username) + # here, since the username from the request might have + # "wrong" casing (and ACL checks are case sensitive). + u = user.User(request, auth_username=real_username, auth_method=self.name, auth_attribs=('name', 'password', 'email')) u.email = email #u.remember_me = 0 # 0 enforces cookie_lifetime config param u.create_or_update(True) -- 2.30.2