Merge lp:~camptocamp/openobject-addons/improve_auth_crypt_3_please_launchpad_work-nbi into lp:openobject-addons/7.0

Proposed by Nicolas Bessi - Camptocamp
Status: Merged
Merge reported by: Olivier Dony (Odoo)
Merged at revision: not available
Proposed branch: lp:~camptocamp/openobject-addons/improve_auth_crypt_3_please_launchpad_work-nbi
Merge into: lp:openobject-addons/7.0
Diff against target: 67 lines (+30/-6)
1 file modified
auth_crypt/auth_crypt.py (+30/-6)
To merge this branch: bzr merge lp:~camptocamp/openobject-addons/improve_auth_crypt_3_please_launchpad_work-nbi
Reviewer Review Type Date Requested Status
Olivier Dony (Odoo) Needs Fixing
Review via email: mp+206476@code.launchpad.net

Commit message

[IMP] Add an init function on res.users to encrypt all passwords when installing module and avoid plain passwords for deactivated users.

Description of the change

([IMP] module auth_crypt use sha256 by default to encrypt password. The modification keeps retro compatibility.) REMOVED as disscussed with Olivier

[IMP] Add an init function on res.users to encrypt all passwords when installing module and avoid plain password for deactivated users.

To post a comment you must log in.
Revision history for this message
Olivier Dony (Odoo) (odo-openerp) wrote :

Hi,

As discussed in bug 1280152 comments, we should consider these as 2 separate issues, so this MP could start by dealing with the first one (the lazy password encryption issue).

For this part, your init() method looks fine, but there are already multiple instances of the salting+hashing dance. As you're adding one more, it seems a good opportunity to refactor a bit and extract that pattern into a private method, something like:

def _set_user_password(self, cr, uid, user_id, password, context=None):
     password_hash = md5_crypt(password, gen_salt()) # TODO: update default algo in trunk
     cr.execute("UPDATE res_users SET password='', password_crypt=%s WHERE id=%s",
                (password_hash, user_id))

Thanks!

review: Needs Fixing
Revision history for this message
Nicolas Bessi - Camptocamp (nbessi-c2c-deactivatedaccount) wrote :

Hello,

I have made the modification as required only the init function is in the MP

Revision history for this message
Nicolas Bessi - Camptocamp (nbessi-c2c-deactivatedaccount) wrote :

Hello Olivier,

Any news on this one

Regards

Nicolas

Revision history for this message
Olivier Dony (Odoo) (odo-openerp) wrote :

Thanks for the update! Moved to github for merge (added guard for NULL passwords): https://github.com/odoo/odoo/pull/628

Revision history for this message
Olivier Dony (Odoo) (odo-openerp) wrote :

Merged in 7.0 at https://github.com/odoo-dev/odoo/commit/f29ff5ef, so closing it.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'auth_crypt/auth_crypt.py'
2--- auth_crypt/auth_crypt.py 2013-08-01 16:27:04 +0000
3+++ auth_crypt/auth_crypt.py 2014-03-19 14:52:30 +0000
4@@ -105,6 +105,7 @@
5
6 return magic + salt + '$' + rearranged
7
8+
9 def sh256crypt(cls, password, salt, magic=magic_sha256):
10 iterations = 1000
11 # see http://en.wikipedia.org/wiki/PBKDF2
12@@ -114,16 +115,41 @@
13 result = result.encode('base64') # doesnt seem to be crypt(3) compatible
14 return '%s%s$%s' % (magic_sha256, salt, result)
15
16+
17 class res_users(osv.osv):
18 _inherit = "res.users"
19
20+ def init(self, cr):
21+ """Encrypt all passwords at module installation"""
22+ cr.execute("SELECT id, password FROM res_users WHERE password != ''",)
23+ to_encrypt = cr.fetchall()
24+ if to_encrypt:
25+ for user in to_encrypt:
26+ self._set_encrypted_password(cr, user[0], user[1])
27+ return True
28+
29+ def _set_encrypted_password(self, cr, user_id, plain_password):
30+ """Set an encrypted password for a given user
31+
32+ :param cr: database cursor
33+ :param user_id: user_id
34+ :param plain_password: plain password to encrypt
35+
36+ :returns: user id
37+
38+ """
39+ salt = gen_salt()
40+ stored_password_crypt = md5crypt(plain_password, salt)
41+ cr.execute("UPDATE res_users SET password='', password_crypt=%s WHERE id=%s",
42+ (stored_password_crypt, user_id))
43+ return user_id
44+
45 def set_pw(self, cr, uid, id, name, value, args, context):
46 if value:
47- encrypted = md5crypt(value, gen_salt())
48- cr.execute("update res_users set password='', password_crypt=%s where id=%s", (encrypted, id))
49+ self._set_encrypted_password(cr, id, value)
50 del value
51
52- def get_pw( self, cr, uid, ids, name, args, context ):
53+ def get_pw(self, cr, uid, ids, name, args, context):
54 cr.execute('select id, password from res_users where id in %s', (tuple(map(int, ids)),))
55 stored_pws = cr.fetchall()
56 res = {}
57@@ -144,9 +170,7 @@
58 if cr.rowcount:
59 stored_password, stored_password_crypt = cr.fetchone()
60 if stored_password and not stored_password_crypt:
61- salt = gen_salt()
62- stored_password_crypt = md5crypt(stored_password, salt)
63- cr.execute("UPDATE res_users SET password='', password_crypt=%s WHERE id=%s", (stored_password_crypt, uid))
64+ self._set_encrypted_password(cr, uid, stored_password)
65 try:
66 return super(res_users, self).check_credentials(cr, uid, password)
67 except openerp.exceptions.AccessDenied: