Package entropy :: Package services :: Module auth_interfaces

Source Code for Module entropy.services.auth_interfaces

  1  # -*- coding: utf-8 -*- 
  2  ''' 
  3      # DESCRIPTION: 
  4      # Entropy Object Oriented Interface 
  5   
  6      Copyright (C) 2007-2009 Fabio Erculiani 
  7   
  8      This program is free software; you can redistribute it and/or modify 
  9      it under the terms of the GNU General Public License as published by 
 10      the Free Software Foundation; either version 2 of the License, or 
 11      (at your option) any later version. 
 12   
 13      This program is distributed in the hope that it will be useful, 
 14      but WITHOUT ANY WARRANTY; without even the implied warranty of 
 15      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 16      GNU General Public License for more details. 
 17   
 18      You should have received a copy of the GNU General Public License 
 19      along with this program; if not, write to the Free Software 
 20      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 21  ''' 
 22   
 23  from __future__ import with_statement 
 24  import os 
 25  import time 
 26  import random 
 27  from entropy.services.skel import Authenticator, RemoteDatabase 
 28  from entropy.exceptions import * 
 29  from entropy.const import etpConst 
 30  from entropy.i18n import _ 
 31   
32 -class phpBB3Auth(Authenticator,RemoteDatabase):
33 34 from entropy import tools as entropyTools
35 - def __init__(self):
36 Authenticator.__init__(self) 37 RemoteDatabase.__init__(self) 38 39 self.itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' 40 self.USER_NORMAL = 0 41 self.USER_INACTIVE = 1 42 self.USER_IGNORE = 2 43 self.USER_FOUNDER = 3 44 self.REGISTERED_USERS_GROUP = 7895 45 self.ADMIN_GROUPS = [7893, 7898] 46 self.MODERATOR_GROUPS = [484] 47 self.DEVELOPER_GROUPS = [7900] 48 self.USERNAME_LENGTH_RANGE = range(3,21) 49 self.PASSWORD_LENGTH_RANGE = range(6,31) 50 self.PRIVMSGS_NO_BOX = -3 51 self.NOTIFY_EMAIL = 0 52 self.FAKE_USERNAME = 'already_authed' 53 self.USER_AGENT = "Entropy/%s (compatible; %s; %s: %s %s %s)" % ( 54 etpConst['entropyversion'], 55 "Entropy", 56 "UGC", 57 os.uname()[0], 58 os.uname()[4], 59 os.uname()[2], 60 ) 61 self.TABLE_PREFIX = 'phpbb_' 62 self.do_update_session_table = True
63
64 - def validate_username_regex(self, username):
65 allow_name_chars = self._get_config_value("allow_name_chars") 66 if allow_name_chars == "USERNAME_CHARS_ANY": 67 regex = '.+' 68 elif allow_name_chars == "USERNAME_ALPHA_ONLY": 69 regex = '[A-Za-z0-9]+' 70 elif allow_name_chars == "USERNAME_ALPHA_SPACERS": 71 regex = '[A-Za-z0-9-[\]_+ ]+' 72 elif allow_name_chars == "USERNAME_LETTER_NUM": 73 regex = '[a-zA-Z0-9]+' 74 elif allow_name_chars == "USERNAME_LETTER_NUM_SPACERS": 75 regex = '[-\]_+ [a-zA-Z0-9]+' 76 else: # USERNAME_ASCII 77 regex = '[\x01-\x7F]+' 78 regex = "^%s$" % (regex,) 79 import re 80 myreg = re.compile(regex) 81 if myreg.match(username): 82 del myreg 83 return True 84 return False
85
86 - def does_username_exist(self, username, username_clean):
87 self.check_connection() 88 self.cursor.execute('SELECT user_id FROM '+self.TABLE_PREFIX+'users WHERE `username_clean` = %s OR LOWER(`username`) = %s', (username_clean,username.lower(),)) 89 data = self.cursor.fetchone() 90 if not data: return False 91 if not isinstance(data,dict): return False 92 if not data.has_key('user_id'): return False 93 return True
94
95 - def does_email_exist(self, email):
96 self.check_connection() 97 self.cursor.execute('SELECT user_id FROM '+self.TABLE_PREFIX+'users WHERE `user_email` = %s', (email,)) 98 data = self.cursor.fetchone() 99 if not data: return False 100 if not isinstance(data,dict): return False 101 if not data.has_key('user_id'): return False 102 return True
103
104 - def is_username_allowed(self, username):
105 self.check_connection() 106 self.cursor.execute('SELECT disallow_id FROM '+self.TABLE_PREFIX+'disallow WHERE `disallow_username` = %s', (username,)) 107 data = self.cursor.fetchone() 108 if not data: return True 109 if not isinstance(data,dict): return True 110 if not data.has_key('disallow_id'): return True 111 return False
112
113 - def validate_username_string(self, username, username_clean):
114 115 try: 116 x = unicode(username.encode('utf-8'),'raw_unicode_escape') 117 del x 118 except (UnicodeDecodeError,UnicodeEncodeError,): 119 return False,'Invalid username' 120 if (""" in username) or ("'" in username) or ('"' in username) or \ 121 (" " in username): 122 return False,'Invalid username' 123 124 try: 125 valid = self.validate_username_regex(username) 126 except: 127 return False,'Username contains bad characters' 128 if not valid: 129 return False,'Invalid username' 130 131 exists = self.does_username_exist(username, username_clean) 132 if exists: return False,'Username already taken' 133 134 allowed = self.is_username_allowed(username) 135 if not allowed: return False,'Username not allowed' 136 137 return True,'All fine'
138
139 - def _generate_email_hash(self, email):
140 import binascii 141 return str(binascii.crc32(email.lower())) + str(len(email))
142
143 - def activate_user(self, user_id):
144 self.check_connection() 145 self.cursor.execute('UPDATE '+self.TABLE_PREFIX+'users SET user_type = %s WHERE `user_id` = %s', (self.USER_NORMAL,user_id,)) 146 return True, user_id
147
148 - def generate_username_clean(self, username):
149 import re 150 username_clean = username.lower() 151 username_clean = re.sub(r'(?:[\x00-\x1F\x7F]+|(?:\xC2[\x80-\x9F])+)', '', username_clean) 152 username_clean = re.sub(r' {2,}',' ',username_clean) 153 username_clean = username_clean.strip() 154 return username_clean
155
156 - def register_user(self, username, password, email, activate = False):
157 158 if len(username) not in self.USERNAME_LENGTH_RANGE: 159 return False,'Username not in range' 160 if len(password) not in self.PASSWORD_LENGTH_RANGE: 161 return False,'Password not in range' 162 valid = self.entropyTools.is_valid_email(email) 163 if not valid: 164 return False,'Invalid email' 165 166 # create the clean one 167 username_clean = self.generate_username_clean(username) 168 169 # check username validity 170 status, err_msg = self.validate_username_string(username, username_clean) 171 if not status: return False,err_msg 172 173 # check email 174 exists = self.does_email_exist(email) 175 if exists: return False,'Email already in use' 176 177 # now cross fingers 178 user_id = self.__register(username, username_clean, password, email, activate) 179 180 return True, user_id
181 182
183 - def __register(self, username, username_clean, password, email, activate):
184 185 email_hash = self._generate_email_hash(email) 186 password_hash = self._get_password_hash(password.encode('utf-8')) 187 time_now = int(time.time()) 188 189 user_type = self.USER_INACTIVE 190 if activate: user_type = self.USER_NORMAL 191 192 registration_data = { 193 'username': username, 194 'username_clean': username_clean, 195 'user_password': password_hash, 196 'user_pass_convert': 0, 197 'user_email': email.lower(), 198 'user_email_hash': email_hash, 199 'group_id': self.REGISTERED_USERS_GROUP, 200 'user_type': user_type, 201 'user_permissions': '', 202 'user_timezone': self._get_config_value('board_timezone'), 203 'user_dateformat': self._get_config_value('default_dateformat'), 204 'user_lang': self._get_config_value('default_lang'), 205 'user_style': self._get_config_value('default_style'), 206 'user_actkey': '', 207 'user_ip': '', 208 'user_regdate': time_now, 209 'user_passchg': time_now, 210 'user_options': 895, # ? don't ask me 211 'user_inactive_reason': 0, 212 'user_inactive_time': 0, 213 'user_lastmark': time_now, 214 'user_lastvisit': 0, 215 'user_lastpost_time': 0, 216 'user_lastpage': '', 217 'user_posts': 0, 218 'user_dst': self._get_config_value('board_dst'), 219 'user_colour': '', 220 'user_occ': '', 221 'user_interests': '', 222 'user_avatar': '', 223 'user_avatar_type': 0, 224 'user_avatar_width': 0, 225 'user_avatar_height': 0, 226 'user_new_privmsg': 0, 227 'user_unread_privmsg': 0, 228 'user_last_privmsg': 0, 229 'user_message_rules': 0, 230 'user_full_folder': self.PRIVMSGS_NO_BOX, 231 'user_emailtime': 0, 232 'user_notify': 0, 233 'user_notify_pm': 1, 234 'user_notify_type': self.NOTIFY_EMAIL, 235 'user_allow_pm': 1, 236 'user_allow_viewonline': 1, 237 'user_allow_viewemail': 1, 238 'user_allow_massemail': 1, 239 'user_sig': '', 240 'user_sig_bbcode_uid': '', 241 'user_sig_bbcode_bitfield': '', 242 'user_form_salt': self._get_unique_id(), 243 } 244 245 sql = self._generate_sql('insert', self.TABLE_PREFIX+'users', registration_data) 246 self.cursor.execute(sql) 247 user_id = self.cursor.lastrowid 248 249 # now insert into the default group 250 group_data = { 251 'user_id': user_id, 252 'group_id': self.REGISTERED_USERS_GROUP, 253 'user_pending': 0, 254 } 255 sql = self._generate_sql('insert', self.TABLE_PREFIX+'user_group', group_data) 256 self.cursor.execute(sql) 257 258 # set some misc config shit 259 self._set_config_value('newest_user_id',user_id) 260 self._set_config_value('newest_username',username) 261 self._set_config_value('num_users',int(self._get_config_value('num_users'))+1) 262 self.cursor.execute('SELECT group_colour FROM '+self.TABLE_PREFIX+'groups WHERE group_id = %s', (group_data['group_id'],)) 263 data = self.cursor.fetchone() 264 gcolor = None 265 if isinstance(data,dict): 266 if data.has_key('group_colour'): 267 gcolor = data['group_colour'] 268 if gcolor: self._set_config_value('newest_user_colour',gcolor) 269 270 return user_id
271 272
273 - def login(self):
274 self.check_connection() 275 self.check_login_data() 276 277 if not self.login_data.has_key('username'): 278 raise PermissionDenied('PermissionDenied: %s' % (_('no username specified'),)) 279 elif not self.login_data.has_key('password'): 280 raise PermissionDenied('PermissionDenied: %s' % (_('no password specified'),)) 281 282 if not self.login_data['password']: 283 raise PermissionDenied('PermissionDenied: %s' % (_('empty password'),)) 284 elif not self.login_data['username']: 285 raise PermissionDenied('PermissionDenied: %s' % (_('empty username'),)) 286 287 self.cursor.execute('SELECT * FROM '+self.TABLE_PREFIX+'users WHERE username = %s', (self.login_data['username'],)) 288 data = self.cursor.fetchone() 289 if not data: 290 raise PermissionDenied('PermissionDenied: %s' % (_('user not found'),)) 291 292 if data['user_pass_convert']: 293 raise PermissionDenied('PermissionDenied: %s' % ( 294 _('you need to login on the website to update your password format'), 295 ) 296 ) 297 298 valid = self._phpbb3_check_hash(self.login_data['password'], data['user_password']) 299 if not valid: 300 raise PermissionDenied('PermissionDenied: %s' % (_('wrong password'),)) 301 302 user_type = data['user_type'] 303 if (user_type == self.USER_INACTIVE) or (user_type == self.USER_IGNORE): 304 raise PermissionDenied('PermissionDenied: %s' % (_('user inactive'),)) 305 306 banned = self.is_user_banned(data['user_id']) 307 if banned: 308 raise PermissionDenied('PermissionDenied: %s' % (_('user banned'),)) 309 310 self.login_data.update(data) 311 self.logged_in = True 312 return self.logged_in
313
314 - def disconnect(self):
315 if self.is_logged_in(): 316 self.logout() 317 RemoteDatabase.disconnect(self)
318
319 - def logout(self):
320 self.check_connection() 321 self.check_login_data() 322 self.logged_in = False 323 self.login_data.clear() 324 return True
325
326 - def get_user_data(self):
327 self.check_connection() 328 self.check_login_data() 329 self.check_logged_in() 330 331 self.cursor.execute('SELECT * FROM '+self.TABLE_PREFIX+'users WHERE user_id = %s', (self.login_data['user_id'],)) 332 return self.cursor.fetchone()
333
334 - def get_user_birthday(self):
335 self.check_connection() 336 self.check_login_data() 337 self.check_logged_in() 338 339 self.cursor.execute('SELECT user_birthday FROM '+self.TABLE_PREFIX+'users WHERE user_id = %s', (self.login_data['user_id'],)) 340 bday = self.cursor.fetchone() 341 if not bday: 342 return None 343 elif not bday.has_key('user_birthday'): 344 return None 345 return bday['user_birthday']
346
347 - def get_username(self):
348 self.check_connection() 349 self.check_login_data() 350 self.check_logged_in() 351 352 self.cursor.execute('SELECT username_clean FROM '+self.TABLE_PREFIX+'users WHERE user_id = %s', (self.login_data['user_id'],)) 353 data = self.cursor.fetchone() 354 if not data: 355 return '' 356 elif not data.has_key('username_clean'): 357 return '' 358 return data['username_clean']
359
360 - def is_developer(self):
361 self.check_connection() 362 self.check_login_data() 363 self.check_logged_in() 364 365 # search into phpbb_groups 366 groups = self.get_user_groups() 367 for group in groups: 368 if group in self.DEVELOPER_GROUPS: 369 return True 370 371 return False
372
373 - def is_administrator(self):
374 self.check_connection() 375 self.check_login_data() 376 self.check_logged_in() 377 378 self.cursor.execute('SELECT user_type FROM '+self.TABLE_PREFIX+'users WHERE user_id = %s', (self.login_data['user_id'],)) 379 data = self.cursor.fetchone() 380 if data: 381 if data['user_type'] == self.USER_FOUNDER: 382 return True 383 384 # search into phpbb_groups 385 groups = self.get_user_groups() 386 for group in groups: 387 if group in self.ADMIN_GROUPS: 388 return True 389 390 return False
391
392 - def is_moderator(self):
393 self.check_connection() 394 self.check_login_data() 395 self.check_logged_in() 396 397 # search into phpbb_groups 398 groups = self.get_user_groups() 399 for group in groups: 400 if group in self.MODERATOR_GROUPS: 401 return True 402 403 return False
404
405 - def is_user(self):
406 self.check_connection() 407 self.check_login_data() 408 self.check_logged_in() 409 410 if self.is_moderator(): 411 return False 412 elif self.is_administrator(): 413 return False 414 elif self.is_developer(): 415 return False 416 417 self.cursor.execute('SELECT user_type,user_id FROM '+self.TABLE_PREFIX+'users WHERE user_id = %s', (self.login_data['user_id'],)) 418 data = self.cursor.fetchone() 419 if not data: 420 return False 421 if self.is_user_banned(data['user_id']): 422 return False 423 elif data['user_type'] in [self.USER_NORMAL]: 424 return True 425 426 return False
427 428 # user == user_id
429 - def is_user_banned(self, user):
430 self.check_connection() 431 self.cursor.execute('SELECT ban_userid FROM '+self.TABLE_PREFIX+'banlist WHERE ban_userid = %s', (user,)) 432 data = self.cursor.fetchone() 433 if data: 434 return True 435 return False
436
437 - def is_in_group(self, group):
438 self.check_connection() 439 self.check_login_data() 440 self.check_logged_in() 441 groups = self.get_user_groups() 442 if isinstance(group,int): 443 if group in groups: 444 return True 445 elif isinstance(group,basestring): 446 self.cursor.execute('SELECT group_id FROM '+self.TABLE_PREFIX+'groups WHERE group_name = %s', (group,)) 447 data = self.cursor.fetchone() 448 if not data: 449 return False 450 elif data['group_id'] in groups: 451 return True 452 453 return False
454
455 - def get_user_groups(self):
456 self.check_connection() 457 self.check_login_data() 458 self.check_logged_in() 459 460 self.cursor.execute('SELECT '+self.TABLE_PREFIX+'user_group.group_id,'+self.TABLE_PREFIX+'groups.group_name FROM '+self.TABLE_PREFIX+'user_group,'+self.TABLE_PREFIX+'users,'+self.TABLE_PREFIX+'groups WHERE '+self.TABLE_PREFIX+'users.user_id = %s and '+self.TABLE_PREFIX+'users.user_id = '+self.TABLE_PREFIX+'user_group.user_id and '+self.TABLE_PREFIX+'user_group.group_id = '+self.TABLE_PREFIX+'groups.group_id', (self.login_data['user_id'],)) 461 data = self.cursor.fetchall() 462 mydata = {} 463 for mydict in data: 464 mydata[mydict['group_id']] = mydict['group_name'] 465 466 return mydata
467
468 - def get_user_group(self):
469 self.check_connection() 470 self.check_login_data() 471 self.check_logged_in() 472 473 self.cursor.execute('SELECT group_id FROM '+self.TABLE_PREFIX+'users WHERE user_id = %s', (self.login_data['user_id'],)) 474 data = self.cursor.fetchone() 475 if data: 476 if data.has_key('group_id'): 477 return data['group_id'] 478 479 return -1
480
481 - def get_user_id(self):
482 self.check_connection() 483 self.check_login_data() 484 self.check_logged_in() 485 return self.login_data['user_id']
486
487 - def get_permission_data(self):
488 self.check_connection() 489 self.check_login_data() 490 self.check_logged_in() 491 self.cursor.execute('SELECT user_permissions FROM '+self.TABLE_PREFIX+'users WHERE user_id = %s', (self.login_data['user_id'],)) 492 return self.cursor.fetchone()
493
494 - def update_email(self, email):
495 self.check_connection() 496 self.check_login_data() 497 self.check_logged_in() 498 499 email_hash = self._generate_email_hash(email) 500 mydata = { 501 'user_email_hash': email_hash, 502 'user_email': email.lower(), 503 } 504 505 try: 506 sql = self._generate_sql("update",self.TABLE_PREFIX+'users', mydata, 'user_id = %s' % (self.login_data['user_id'],)) 507 self.cursor.execute(sql) 508 return True 509 except Exception: 510 return False
511
512 - def update_password_hash(self, password_hash):
513 self.check_connection() 514 self.check_login_data() 515 self.check_logged_in() 516 517 mydata = { 518 'user_password': password_hash, 519 } 520 521 try: 522 sql = self._generate_sql("update",self.TABLE_PREFIX+'users', mydata, 'user_id = %s' % (self.login_data['user_id'],)) 523 self.cursor.execute(sql) 524 return True 525 except Exception: 526 return False
527
528 - def get_email(self):
529 self.check_connection() 530 self.check_login_data() 531 self.check_logged_in() 532 self.cursor.execute('SELECT user_email FROM '+self.TABLE_PREFIX+'users WHERE user_id = %s', (self.login_data['user_id'],)) 533 data = self.cursor.fetchone() 534 if not data: 535 return '' 536 elif not data.has_key('user_email'): 537 return '' 538 return data['user_email']
539
540 - def update_user_id_profile(self, profile_data):
541 self.check_connection() 542 self.check_login_data() 543 self.check_logged_in() 544 545 # filter valid params 546 valid_params = [ 547 "user_icq","user_yim","user_msnm", 548 "user_jabber","user_website","user_from", 549 "user_interests","user_occ","user_birthday", 550 "user_sig" 551 ] 552 553 my_params = {} 554 for param in valid_params: 555 d = profile_data.get(param) 556 if d == None: continue 557 my_params[param] = d 558 559 if not my_params: 560 return False,'no parameters' 561 562 563 # validate parameters 564 b_day = my_params.get('user_birthday') 565 if isinstance(b_day,basestring): 566 import re 567 myre = re.compile("(0[1-9]|[12][0-9]|3[01])[-](0[1-9]|1[012])[-](19|20)\d\d") 568 if not myre.match(b_day): 569 del my_params['user_birthday'] 570 571 try: 572 sql = self._generate_sql("update",self.TABLE_PREFIX+'users', my_params, 'user_id = %s' % (self.login_data['user_id'],)) 573 self.cursor.execute(sql) 574 return True, None 575 except Exception, e: 576 return False, unicode(e)
577 578
579 - def _set_config_value(self, config_name, data):
580 self.cursor.execute('UPDATE '+self.TABLE_PREFIX+'config SET config_value = %s WHERE config_name = %s',(data,config_name,))
581
582 - def _get_config_value(self, config_name):
583 self.check_connection() 584 self.cursor.execute('SELECT config_value FROM '+self.TABLE_PREFIX+'config WHERE config_name = %s',(config_name,)) 585 myconfig = self.cursor.fetchone() 586 if isinstance(myconfig,dict): 587 if myconfig.has_key('config_value'): 588 return myconfig['config_value'] 589 return None
590
591 - def _update_session_table(self, user_id, ip_address):
592 self.check_connection() 593 time_now = int(time.time()) 594 autologin = self._get_config_value("allow_autologin") 595 self.cursor.execute('SELECT user_allow_viewonline FROM '+self.TABLE_PREFIX+'users WHERE user_id = %s', (user_id,)) 596 myuserprefs = self.cursor.fetchone() 597 session_admin = 0 598 session_data = { 599 'session_id': None, 600 'session_user_id': user_id, 601 'session_last_visit': time_now, 602 'session_start': time_now, 603 'session_time': time_now, 604 'session_ip': ip_address, 605 'session_browser': self.USER_AGENT, 606 'session_forwarded_for': '', 607 'session_page': 'index.php', 608 'session_viewonline': myuserprefs['user_allow_viewonline'], 609 'session_autologin': autologin, 610 'session_admin': session_admin, 611 'session_forum_id': 0, 612 } 613 import hashlib 614 m = hashlib.md5() 615 m.update(str(user_id)+str(time_now)+str(self.USER_AGENT)+str(ip_address)+str(autologin)+str(myuserprefs['user_allow_viewonline'])) 616 session_data['session_id'] = m.hexdigest() 617 618 self.cursor.execute('SELECT * FROM '+self.TABLE_PREFIX+'sessions WHERE session_user_id = %s', (user_id,)) 619 mydata = self.cursor.fetchone() 620 do_update = False 621 if mydata: 622 do_update = True 623 # update 624 session_data['session_id'] = mydata['session_id'] 625 session_data['session_viewonline'] = mydata['session_viewonline'] 626 session_data['session_autologin'] = mydata['session_autologin'] 627 session_data['session_forwarded_for'] = mydata['session_forwarded_for'] 628 session_data['session_forum_id'] = mydata['session_forum_id'] 629 session_data['session_page'] = mydata['session_page'] 630 session_data['session_browser'] = mydata['session_browser'] 631 session_data['session_admin'] = mydata['session_admin'] 632 633 if do_update: 634 where = "session_id = '%s'" % (session_data['session_id'],) 635 del session_data['session_id'] 636 sql = self._generate_sql('update', self.TABLE_PREFIX+'sessions', session_data, where) 637 else: 638 sql = self._generate_sql('insert', self.TABLE_PREFIX+'sessions', session_data) 639 if sql: 640 self.cursor.execute(sql) 641 self.dbconn.commit()
642 643
644 - def _is_ip_banned(self, ip):
645 self.check_connection() 646 self.cursor.execute('SELECT ban_ip FROM '+self.TABLE_PREFIX+'banlist WHERE ban_ip = %s', (ip,)) 647 data = self.cursor.fetchone() 648 if data: 649 return True 650 return False
651
652 - def _get_unique_id(self):
653 import hashlib 654 m = hashlib.md5() 655 rnd = str(abs(hash(os.urandom(1)))) 656 m.update(rnd) 657 x = m.hexdigest()[:-16] 658 del m 659 return x
660
661 - def _get_random_number(self):
662 myrand = 0 663 low_n = 100000 664 high_n = 999999 665 while (myrand < low_n) or (myrand > high_n): 666 try: 667 myrand = hash(os.urandom(1))%high_n 668 except NotImplementedError: 669 random.seed() 670 myrand = random.randint(low_n,high_n) 671 return myrand
672
673 - def _get_password_hash(self, password):
674 675 #random_state = self._get_unique_id() 676 myrandom = str(self._get_random_number()) 677 678 myhash = self._hash_crypt_private(password, self._hash_gensalt_private(myrandom)) 679 680 if len(myhash) == 34: 681 return myhash 682 683 import hashlib 684 m = hashlib.md5() 685 m.update(myhash) 686 return m.hexdigest()
687 688
689 - def _hash_gensalt_private(self, myinput, iteration_count_log2 = 6):
690 691 if (iteration_count_log2 < 4) or (iteration_count_log2 > 31): 692 iteration_count_log2 = 8 693 694 myoutput = '$H$' 695 myoutput += self.itoa64[min(iteration_count_log2 + 5,30)] 696 myoutput += self._hash_encode64(myinput, 6) 697 698 return myoutput
699
700 - def _hash_crypt_private(self, password, setting):
701 702 myoutput = '*' 703 # Check for correct hash 704 if setting[:3] != '$H$': 705 return myoutput 706 707 count_log2 = self.itoa64.find(setting[3]) 708 if count_log2 == -1: count_log2 = 0 709 710 if (count_log2 < 7) or (count_log2 > 30): 711 return myoutput 712 713 count = 1 << count_log2 714 salt = setting[4:12] 715 716 if len(salt) != 8: 717 return myoutput 718 719 import hashlib 720 m = hashlib.md5() 721 m.update(salt+password) 722 myhash = m.digest() 723 while count: 724 m = hashlib.md5() 725 m.update(myhash+password) 726 myhash = m.digest() 727 count -= 1 728 729 myoutput = setting[:12] 730 myoutput += self._hash_encode64(myhash, 16) 731 732 return myoutput
733
734 - def _hash_encode64(self, myinput, count):
735 736 output = '' 737 i = 0 738 while i < count: 739 740 value = ord(myinput[i]) 741 i += 1 742 output += self.itoa64[value & 0x3f] 743 if i < count: 744 value |= ord(myinput[i]) << 8 745 746 output += self.itoa64[(value >> 6) & 0x3f] 747 748 if i >= count: 749 break 750 i += 1 751 752 if i < count: 753 value |= ord(myinput[i]) << 16 754 755 output += self.itoa64[(value >> 12) & 0x3f] 756 757 if (i >= count): 758 break 759 i += 1 760 761 output += self.itoa64[(value >> 18) & 0x3f] 762 763 return output
764
765 - def _phpbb3_check_hash(self, password, myhash):
766 767 if len(myhash) == 34: 768 return self._hash_crypt_private(password, myhash) == myhash 769 770 import hashlib 771 m = hashlib.md5() 772 m.update(password) 773 rhash = m.hexdigest() 774 return rhash == myhash
775