base_crypt: improve. close cursors, use hashlib, update login date

bzr revid: p_christ@hol.gr-20101228132637-oe86bgxujv17tiz2
This commit is contained in:
P. Christeas 2010-12-28 15:26:37 +02:00
parent 6eb0e8e8aa
commit 6fa81844d2
1 changed files with 50 additions and 29 deletions

View File

@ -66,11 +66,14 @@ def gen_salt( length=8, symbols=ascii_letters + digits ):
# * Poul-Henning Kamp
#TODO: py>=2.6: from hashlib import md5
import md5
import hashlib
def encrypt_md5( raw_pw, salt, magic=magic_md5 ):
hash = md5.new( raw_pw + magic + salt )
stretch = md5.new( raw_pw + salt + raw_pw).digest()
hash = hashlib.md5()
hash.update( raw_pw + magic + salt )
st = hashlib.md5()
st.update( raw_pw + salt + raw_pw)
stretch = st.digest()
for i in range( 0, len( raw_pw ) ):
hash.update( stretch[i % 16] )
@ -87,7 +90,7 @@ def encrypt_md5( raw_pw, salt, magic=magic_md5 ):
saltedmd5 = hash.digest()
for i in range( 1000 ):
hash = md5.new()
hash = hashlib.md5()
if i & 1:
hash.update( raw_pw )
@ -174,10 +177,12 @@ class users(osv.osv):
cr = pooler.get_db(db).cursor()
return self._login(cr, db, login, password)
except Exception:
if cr: cr.close()
import logging
logging.getLogger('netsvc').exception('Could not authenticate')
return Exception('Access Denied')
finally:
if cr is not None:
cr.close()
def _login(self, cr, db, login, password):
cr.execute( 'SELECT password, id FROM res_users WHERE login=%s',
@ -190,6 +195,10 @@ class users(osv.osv):
return False
stored_pw = self.maybe_encrypt(cr, stored_pw, id)
if not stored_pw:
# means couldn't encrypt or user is not active!
return False
# Calculate an encrypted password from the user-provided
# password.
@ -198,10 +207,11 @@ class users(osv.osv):
encrypted_pw = encrypt_md5(password, salt)
# Check if the encrypted password matches against the one in the db.
cr.execute('select id from res_users where id=%s and password=%s and active',
cr.execute('UPDATE res_users SET date=now() ' \
'WHERE id=%s AND password=%s AND active RETURNING id',
(int(id), encrypted_pw.encode('utf-8')))
res = cr.fetchone()
cr.close()
cr.commit()
if res:
return res[0]
@ -220,20 +230,26 @@ class users(osv.osv):
return True
cr = pooler.get_db(db).cursor()
if uid not in self._salt_cache.get(db, {}):
cr.execute( 'SELECT login FROM res_users WHERE id=%s', (uid,) )
stored_login = cr.fetchone()
if stored_login:
stored_login = stored_login[0]
if not self.login(db,stored_login,passwd):
raise security.ExceptionNoTb('AccessDenied')
try:
if uid not in self._salt_cache.get(db, {}):
# If we don't have cache, we have to repeat the procedure
# through the login function.
cr.execute( 'SELECT login FROM res_users WHERE id=%s', (uid,) )
stored_login = cr.fetchone()
if stored_login:
stored_login = stored_login[0]
res = self._login(cr, db, stored_login, passwd)
if not res:
raise security.ExceptionNoTb('AccessDenied')
else:
salt = self._salt_cache[db][uid]
cr.execute('SELECT COUNT(*) FROM res_users WHERE id=%s AND password=%s',
(int(uid), encrypt_md5(passwd, salt)))
res = cr.fetchone()[0]
finally:
cr.close()
salt = self._salt_cache[db][uid]
cr.execute('SELECT COUNT(*) FROM res_users WHERE id=%s AND password=%s',
(int(uid), encrypt_md5(passwd, salt)))
res = cr.fetchone()[0]
cr.close()
if not bool(res):
raise security.ExceptionNoTb('AccessDenied')
@ -246,18 +262,23 @@ class users(osv.osv):
return bool(res)
def maybe_encrypt(self, cr, pw, id):
# If the password 'pw' is not encrypted, then encrypt all passwords
# in the db. Returns the (possibly newly) encrypted password for 'id'.
""" Return the password 'pw', making sure it is encrypted.
If the password 'pw' is not encrypted, then encrypt all active passwords
in the db. Returns the (possibly newly) encrypted password for 'id'.
"""
if pw[0:len(magic_md5)] != magic_md5:
cr.execute('select id, password from res_users')
if not pw.startswith(magic_md5):
encrypted_res = False
cr.execute("SELECT id, password FROM res_users " \
"WHERE active=true AND password NOT LIKE '$%'")
# Note that we skip all passwords like $.., in anticipation for
# more than md5 magic prefixes.
res = cr.fetchall()
for i, p in res:
encrypted = p
if p[0:len(magic_md5)] != magic_md5:
encrypted = encrypt_md5(p, gen_salt())
cr.execute('update res_users set password=%s where id=%s',
(encrypted.encode('utf-8'), int(i)))
encrypted = encrypt_md5(p, gen_salt())
cr.execute('UPDATE res_users SET password=%s where id=%s',
(encrypted, i))
if i == id:
encrypted_res = encrypted
cr.commit()