-#!/usr/bin/python2.6
-# -*- coding: iso-8859-15 -*-
+#!/usr/bin/python3.4
# $Id$
-"MediaWiki communication functions"
+"""MediaWiki communication functions"""
import datetime
import re
log = logging.getLogger(__name__)
import wradmin.model as model
-import wradmin.model.validators
# User management
con.close()
log.info("%d users loaded from the MediaWiki database" % len(self.usernames))
-
+ @staticmethod
+ def password_is_correct(password_plain, password_db):
+ """Returns true if a plain text password corresponds to the hash of the password as stored in the MediaWiki db.
+
+ :param password_plain: plain text password, e.g. 'abc'
+ :param password_db: complete password line as stored in the database, e.g. ':pbkdf2:sha256:10000:128:EXgVGhc2mAs710feKvkiaw==:J5fYth9pg/R2d0F8bSsYfTR8SBpTBNIcdv/DgJ0tOPC1rtajl2Dr0RLqOozLb8O0XpDhtv4a3JJd/M0b58WebfNWAcdJBJI9nNeC0EYYD7OCYZGVAaRhiYtK4m53KZBBL6x/k2j4RjHPT1NmgV8Fr1DPqBNOlOHxUIh5z5oslM4='
+ """
+ if not password_db.startswith(':'):
+ raise AuthKitError("Password entry in the database does have an unexpected format (does not start with ':').")
+ pwd_parts = password_db[1:].split(':')
+ pwd_type = pwd_parts[0]
+ if pwd_type == 'B':
+ # legacy
+ # example: password_db == ':B:d25b2886:41e46c952790b1b442aac4f24f7ea7a8'
+ # pwd_parts == ['B', 'd25b2886', '41e46c952790b1b442aac4f24f7ea7a8']
+ if len(pwd_parts) != 3:
+ raise AuthKitError("Password entry in the database does have an unexpected format (too few ':').")
+ salt, pwd_md5 = tuple(pwd_parts[1:3]) # salt = 'd25b2886'; pwd_md5 = '41e46c952790b1b442aac4f24f7ea7a8'
+ # log.info("user: '%s'; md5 of salt+' '+entered_pwd: '%s'; md5-part of DB-pwd: %s" % (username, md5(salt + '-' + md5(password)), pwd_md5))
+ return md5(salt + '-' + md5(password_plain)) == pwd_md5
+ elif pwd_type == 'pbkdf2':
+ if len(pwd_parts) != 6:
+ raise AuthKitError("Password entry in the database does have an unexpected format (too few ':').")
+ _, algorithm, rounds, num_bit, salt, pwd_hash = pwd_parts
+ from base64 import b64decode, b64encode
+ from hashlib import pbkdf2_hmac
+ salt = b64decode(salt)
+ hash = pbkdf2_hmac(algorithm, password_plain, salt, int(rounds), int(num_bit))
+ hash = b64encode(hash)
+ return hash == pwd_hash
+
+
def user_has_password(self, username, password):
"""
Passwords are case sensitive.
- Returns ``True`` if the user has the password specified, ``False`` otherwise.
+ Returns ``True`` if the user has the password specified, ``False`` otherwise.
Raises an exception if the user doesn't exist.
-
+
See http://www.winterrodeln.org/trac/wiki/MediaWikiAuthorization
"""
- pwd = self.user_password(username)
- # Example: pwd = ':B:d25b2886:41e46c952790b1b442aac4f24f7ea7a8'
- pwd_parts = pwd.split(':') # password_parts = ['', 'B', 'd25b2886', '41e46c952790b1b442aac4f24f7ea7a8']
- if len(pwd_parts) == 4 and pwd_parts[1] == 'B':
- salt, pwd_md5 = tuple(pwd_parts[2:4]) # salt = 'd25b2886'; pwd_md5 = '41e46c952790b1b442aac4f24f7ea7a8'
- else:
- raise AuthKitError("Password in the MediaWiki database format has an unexpected format ('%s' instead of e.g. ':B:d25b2886:41e46c952790b1b442aac4f24f7ea7a8')" % pwd)
- # log.info("user: '%s'; md5 of salt+' '+entered_pwd: '%s'; md5-part of DB-pwd: %s" % (username, md5(salt + '-' + md5(password)), pwd_md5))
- return md5(salt + '-' + md5(password)) == pwd_md5
+ password_db = self.user_password(username)
+ return self.password_is_correct(password, password_db)