"""
import MySQLdb
-import md5
+# Password encryption module. Python port of the method used by phpbb3.
+import phpass
from MoinMoin import user
from MoinMoin.auth import BaseAuth, ContinueLogin
from MoinMoin.datastruct.backends import LazyGroupsBackend, LazyGroup
Return a list of group names.
"""
return self.list_query("SELECT group_name \
- FROM `%sgroups` \
- WHERE group_single_user = 0"
+ FROM `%sgroups`"
% self.dbconfig['phpbb_prefix'])
def __contains__(self, group_name):
return self.single_query("SELECT EXISTS ( \
SELECT * \
FROM `%sgroups` \
- WHERE group_single_user = 0 \
- AND group_name=%%s)" % self.dbconfig['phpbb_prefix'],
+ WHERE group_name=%%s)" % self.dbconfig['phpbb_prefix'],
group_name)
def __getitem__(self, group_name):
return self.list_query ("SELECT username \
FROM `%susers` as u, `%suser_group` as ug, `%sgroups` as g \
WHERE u.user_id = ug.user_id AND ug.group_id = g.group_id \
- AND ug.user_pending = 0 AND g.group_single_user = 0 \
- AND g.group_name = %%s"
+ AND ug.user_pending = 0 AND g.group_name = %%s"
% (self.dbconfig['phpbb_prefix'], self.dbconfig['phpbb_prefix'], self.dbconfig['phpbb_prefix']),
group_name)
SELECT * \
FROM `%susers` as u, `%suser_group` as ug, `%sgroups` as g \
WHERE u.user_id = ug.user_id AND ug.group_id = g.group_id \
- AND ug.user_pending = 0 AND g.group_single_user = 0 \
+ AND ug.user_pending = 0 \
AND g.group_name = %%s AND u.username = %%s)"
% (self.dbconfig['phpbb_prefix'], self.dbconfig['phpbb_prefix'], self.dbconfig['phpbb_prefix']),
(group_name, member))
return self.list_query ("SELECT g.group_name \
FROM `%susers` as u, `%suser_group` as ug, `%sgroups` as g \
WHERE u.user_id = ug.user_id AND ug.group_id = g.group_id \
- AND ug.user_pending = 0 AND g.group_single_user = 0 \
- AND u.username = %%s"
+ AND ug.user_pending = 0 AND u.username = %%s"
% (self.dbconfig['phpbb_prefix'], self.dbconfig['phpbb_prefix'], self.dbconfig['phpbb_prefix']),
member)
self.dbconfig = kwargs
self.name = name
self.hint = hint
+ self.hash = phpass.PasswordHash()
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)
# 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 LOWER(username)=LOWER(%%s)" % self.dbconfig['phpbb_prefix'], username)
# No data? No login.
if (cursor.rowcount == 0):
row = cursor.fetchone()
conn.close()
- if (md5.new(password).hexdigest() == row[0]):
- return row[1]
+ if self.hash.check_password(password, row[0]):
+ return (row[1], row[2])
else:
- return False
+ return (False, False)
def login(self, request, user_obj, **kw):
"""
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)