# HG changeset patch # User Pascal Volk # Date 1353797292 0 # Node ID 6937cb38db718a34ad5108e150ca1154d19020bb # Parent 429ba58bc302d1bd45886e9c219e5dd2e426aaa3 VMM/password: Post-2to3 fixes. Replaced ….encode('hex') and ….encode('base64') by b64encode(…) and b2a_hex(…). Added some necessary encode() and decode() calls. Fixed NTLM hash generating with non ASCII characters. diff -r 429ba58bc302 -r 6937cb38db71 VirtualMailManager/password.py --- a/VirtualMailManager/password.py Thu Nov 22 18:31:55 2012 +0000 +++ b/VirtualMailManager/password.py Sat Nov 24 22:48:12 2012 +0000 @@ -17,6 +17,8 @@ import hashlib +from base64 import b64encode +from binascii import b2a_hex from crypt import crypt from random import SystemRandom from subprocess import Popen, PIPE @@ -67,8 +69,8 @@ process = Popen(cmd_args, stdout=PIPE, stderr=PIPE) stdout, stderr = process.communicate() if process.returncode: - raise VMMError(stderr.strip(), VMM_ERROR) - hashed = stdout.strip() + raise VMMError(stderr.strip().decode(ENCODING), VMM_ERROR) + hashed = stdout.strip().decode(ENCODING) if not hashed.startswith('{%s}' % scheme): raise VMMError('Unexpected result from %s: %s' % (cfg_dget('bin.dovecotpw'), hashed), VMM_ERROR) @@ -101,13 +103,14 @@ def _clear_hash(password, scheme, encoding): """Generates a (encoded) CLEARTEXT/PLAIN 'hash'.""" + password = password.decode(ENCODING) if encoding: if encoding == 'HEX': - password = password.encode('hex') + password = b2a_hex(password.encode()).decode() else: - password = password.encode('base64').replace('\n', '') + password = b64encode(password.encode()).decode() return _format_digest(password, scheme, encoding) - return get_unicode('{%s}%s' % (scheme, password)) + return '{%s}%s' % (scheme, password) def _get_crypt_blowfish_salt(): @@ -154,12 +157,12 @@ salt = _get_crypt_sha2_salt(CRYPT_ID_SHA256) else: salt = _get_crypt_sha2_salt(CRYPT_ID_SHA512) - encrypted = crypt(password, salt) + encrypted = crypt(password.decode(ENCODING), salt) if encoding: if encoding == 'HEX': - encrypted = encrypted.encode('hex') + encrypted = b2a_hex(encrypted.encode()).decode() else: - encrypted = encrypted.encode('base64').replace('\n', '') + encrypted = b64encode(encrypted.encode()).decode() if scheme in ('BLF-CRYPT', 'SHA256-CRYPT', 'SHA512-CRYPT') and \ cfg_dget('misc.dovecot_version') < 0x20000b06: scheme = 'CRYPT' @@ -174,7 +177,7 @@ if encoding in DEFAULT_HEX: digest = md4.hexdigest() else: - digest = md4.digest().encode('base64').rstrip() + digest = b64encode(md4.digest()).decode() return _format_digest(digest, scheme, encoding) return _dovecotpw(password, scheme, encoding) @@ -190,7 +193,8 @@ # http://dovecot.org/list/dovecot-news/2009-March/000103.html # http://hg.dovecot.org/dovecot-1.1/rev/2b0043ba89ae if cfg_dget('misc.dovecot_version') >= 0x1010cf00: - md5.update('%s:%s:' % (user.localpart, user.domainname)) + md5.update(user.localpart.encode() + b':' + + user.domainname.encode() + b':') else: md5.update('%s::' % user) md5.update(password) @@ -198,7 +202,7 @@ (scheme == 'LDAP-MD5' and encoding == 'HEX'): digest = md5.hexdigest() else: - digest = md5.digest().encode('base64').rstrip() + digest = b64encode(md5.digest()).decode() return _format_digest(digest, scheme, encoding) @@ -206,12 +210,13 @@ """Generates NTLM hashes.""" md4 = _md4_new() if md4: - password = ''.join('%s\x00' % c for c in password) + password = b''.join(bytes(x) + for x in zip(password, bytes(len(password)))) md4.update(password) if encoding in DEFAULT_HEX: digest = md4.hexdigest() else: - digest = md4.digest().encode('base64').rstrip() + digest = b64encode(md4.digest()).decode() return _format_digest(digest, scheme, encoding) return _dovecotpw(password, scheme, encoding) @@ -220,7 +225,7 @@ """Generates SHA1 aka SHA hashes.""" sha1 = hashlib.sha1(password) if encoding in DEFAULT_B64: - digest = sha1.digest().encode('base64').rstrip() + digest = b64encode(sha1.digest()).decode() else: digest = sha1.hexdigest() return _format_digest(digest, scheme, encoding) @@ -230,7 +235,7 @@ """Generates SHA256 hashes.""" sha256 = hashlib.sha256(password) if encoding in DEFAULT_B64: - digest = sha256.digest().encode('base64').rstrip() + digest = b64encode(sha256.digest()).decode() else: digest = sha256.hexdigest() return _format_digest(digest, scheme, encoding) @@ -240,7 +245,7 @@ """Generates SHA512 hashes.""" sha512 = hashlib.sha512(password) if encoding in DEFAULT_B64: - digest = sha512.digest().encode('base64').replace('\n', '') + digest = b64encode(sha512.digest()).decode() else: digest = sha512.hexdigest() return _format_digest(digest, scheme, encoding) @@ -249,47 +254,47 @@ def _smd5_hash(password, scheme, encoding): """Generates SMD5 (salted PLAIN-MD5) hashes.""" md5 = hashlib.md5(password) - salt = _get_salt(SALTED_ALGO_SALT_LEN) + salt = _get_salt(SALTED_ALGO_SALT_LEN).encode() md5.update(salt) if encoding in DEFAULT_B64: - digest = (md5.digest() + salt).encode('base64').rstrip() + digest = b64encode(md5.digest() + salt).decode() else: - digest = md5.hexdigest() + salt.encode('hex') + digest = md5.hexdigest() + b2a_hex(salt).decode() return _format_digest(digest, scheme, encoding) def _ssha1_hash(password, scheme, encoding): """Generates SSHA (salted SHA/SHA1) hashes.""" sha1 = hashlib.sha1(password) - salt = _get_salt(SALTED_ALGO_SALT_LEN) + salt = _get_salt(SALTED_ALGO_SALT_LEN).encode() sha1.update(salt) if encoding in DEFAULT_B64: - digest = (sha1.digest() + salt).encode('base64').rstrip() + digest = b64encode(sha1.digest() + salt).decode() else: - digest = sha1.hexdigest() + salt.encode('hex') + digest = sha1.hexdigest() + b2a_hex(salt).decode() return _format_digest(digest, scheme, encoding) def _ssha256_hash(password, scheme, encoding): """Generates SSHA256 (salted SHA256) hashes.""" sha256 = hashlib.sha256(password) - salt = _get_salt(SALTED_ALGO_SALT_LEN) + salt = _get_salt(SALTED_ALGO_SALT_LEN).encode() sha256.update(salt) if encoding in DEFAULT_B64: - digest = (sha256.digest() + salt).encode('base64').rstrip() + digest = b64encode(sha256.digest() + salt).decode() else: - digest = sha256.hexdigest() + salt.encode('hex') + digest = sha256.hexdigest() + b2a_hex(salt).decode() return _format_digest(digest, scheme, encoding) def _ssha512_hash(password, scheme, encoding): """Generates SSHA512 (salted SHA512) hashes.""" - salt = _get_salt(SALTED_ALGO_SALT_LEN) + salt = _get_salt(SALTED_ALGO_SALT_LEN).encode() sha512 = hashlib.sha512(password + salt) if encoding in DEFAULT_B64: - digest = (sha512.digest() + salt).encode('base64').replace('\n', '') + digest = b64encode(sha512.digest() + salt).decode() else: - digest = sha512.hexdigest() + salt.encode('hex') + digest = sha512.hexdigest() + b2a_hex(salt).decode() return _format_digest(digest, scheme, encoding) _scheme_info = {