From: Matthijs Kooijman Date: Mon, 26 Jul 2010 14:21:52 +0000 (+0200) Subject: phpbb: Properly handle case (in)sensitivity in usernames. X-Git-Url: https://git.stderr.nl/gitweb?a=commitdiff_plain;h=32ee0419a78537ec95b1d71e0335c48446f62051;p=matthijs%2Fprojects%2Fwipi.git 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. --- 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)