Package entropy :: Package services :: Module auth_interfaces

Source Code for Module entropy.services.auth_interfaces

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