[MERGE] Merge xrg branch for lp:700682

bzr revid: sbh@tinyerp.com-20110113114504-y7gqxiyd1g0um9xr
This commit is contained in:
Sbh (OpenERP) 2011-01-13 17:15:04 +05:30
commit 1f5d01d1ea
5 changed files with 124 additions and 51 deletions

125
addons/base_crypt/crypt.py Executable file → Normal file
View File

@ -37,14 +37,14 @@
# USA.
from random import seed, sample
from string import letters, digits
from string import ascii_letters, digits
from osv import fields,osv
import pooler
from tools.translate import _
magic_md5 = '$1$'
def gen_salt( length=8, symbols=letters + digits ):
def gen_salt( length=8, symbols=ascii_letters + digits ):
seed()
return ''.join( sample( symbols, length ) )
@ -64,15 +64,16 @@ def gen_salt( length=8, symbols=letters + digits ):
# *
# * Poul-Henning Kamp
from sys import version_info
if version_info < (2,5):
from md5 import md5
else:
from hashlib import md5
#TODO: py>=2.6: from hashlib import md5
import hashlib
def encrypt_md5( raw_pw, salt, magic=magic_md5 ):
hash = md5( raw_pw + magic + salt )
stretch = md5( 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] )
@ -89,7 +90,7 @@ def encrypt_md5( raw_pw, salt, magic=magic_md5 ):
saltedmd5 = hash.digest()
for i in range( 1000 ):
hash = md5()
hash = hashlib.md5()
if i & 1:
hash.update( raw_pw )
@ -166,19 +167,37 @@ class users(osv.osv):
}
def login(self, db, login, password):
cr = pooler.get_db(db).cursor()
cr.execute('select password, id from res_users where login=%s',
(login.encode('utf-8'),))
stored_pw = id = cr.fetchone()
if stored_pw:
stored_pw = stored_pw[0]
id = id[1]
else:
# Return early if there is no such login.
if not password:
return False
if db is False:
raise RuntimeError("Cannot authenticate to False db!")
cr = None
try:
cr = pooler.get_db(db).cursor()
return self._login(cr, db, login, password)
except Exception:
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',
(login.encode('utf-8'),))
if cr.rowcount:
stored_pw, id = cr.fetchone()
else:
# Return early if no one has a login name like that.
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.
@ -187,12 +206,14 @@ class users(osv.osv):
obj._salt_cache = {}
salt = obj._salt_cache[id] = stored_pw[len(magic_md5):11]
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', (int(id), encrypted_pw.encode('utf-8')))
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]
else:
@ -210,22 +231,28 @@ class users(osv.osv):
return True
cr = pooler.get_db(db).cursor()
if uid not in obj._salt_cache:
cr.execute('select login from res_users where id=%s', (int(uid),))
stored_login = cr.fetchone()
if stored_login:
stored_login = stored_login[0]
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()
if not self.login(db,stored_login,passwd):
return False
salt = obj._salt_cache[uid]
cr.execute('select count(id) 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 Exception('AccessDenied')
raise security.ExceptionNoTb('AccessDenied')
if res:
if self._uid_cache.has_key(db):
@ -234,20 +261,24 @@ class users(osv.osv):
else:
self._uid_cache[db] = {uid: passwd}
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 not pw.startswith(magic_md5):
cr.execute('select id, password from res_users')
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 and not p.startswith(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()

View File

@ -0,0 +1,27 @@
# Translation of OpenERP Server.
# This file contains the translation of the following modules:
# * base_crypt
#
# Copyright (C) 2008,2009 P. Christeas <p_christ@hol.gr>
# <> <>, 2009.
msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-05-30 15:14:08+0000\n"
"PO-Revision-Date: 2009-03-27 14:30+0200\n"
"Last-Translator: <> <>\n"
"Language-Team: <>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#~ msgid "Module for password encryption."
#~ msgstr "Άρθρωμα για κρυπτογράφηση κωδικών."
#~ msgid "Invalid XML for View Architecture!"
#~ msgstr "Άκυρο XML για αρχιτεκτονική προβολής!"
#~ msgid "Password"
#~ msgstr "Κωδικός"

View File

@ -45,9 +45,15 @@ class base_setup_config_choice(osv.osv_memory):
def get_users(self, cr, uid, context=None):
user_obj = self.pool.get('res.users')
user_ids = user_obj.search(cr, uid, [])
users = user_obj.browse(cr, uid, user_ids, context=context)
user_str = '\n'.join(map(lambda x: ' - %s :\n\t\tLogin : %s \n\t\tPassword : %s' % (x.name, x.login, x.password), users))
return _('The following users have been installed : \n')+ user_str
user_list = []
user_tmpl_nopass = _(' - %s :\n\t\tLogin : %s')
user_tmpl_pass = _(' - %s :\n\t\tLogin : %s \n\t\tPassword : %s')
for user in user_obj.browse(cr, uid, user_ids, context=context):
if user.password and not user.password.startswith('$'):
user_list.append(user_tmpl_pass % (user.name, user.login, user.password))
else:
user_list.append(user_tmpl_nopass % (user.name, user.login))
return _('The following users have been installed : \n')+ '\n'.join(user_list)
_columns = {
'installed_users':fields.text('Installed Users', readonly=True),

View File

@ -37,7 +37,12 @@ def get_plain_ftp(timeout=10.0):
def get_ftp_login(cr, uid, ormobj):
ftp = get_plain_ftp()
user = ormobj.pool.get('res.users').read(cr, uid, uid)
ftp.login(user.get('login',''), user.get('login',''))
passwd = user.get('password','')
if passwd.startswith("$1$"):
# md5 by base crypt. We cannot decode, wild guess
# that passwd = login
passwd = user.get('login', '')
ftp.login(user.get('login',''), passwd)
ftp.cwd("/" + cr.dbname)
return ftp

View File

@ -365,6 +365,10 @@ class DAVClient(object):
assert res, "uid %s not found" % uid
self.user = res[0]['login']
self.passwd = res[0]['password']
if self.passwd.startswith('$1$'):
# md5 by base crypt. We cannot decode, wild guess
# that passwd = login
self.passwd = self.user
return True
def set_useragent(self, uastr):