13 random_password = randompw() |
13 random_password = randompw() |
14 scheme, encoding = verify_scheme(scheme) |
14 scheme, encoding = verify_scheme(scheme) |
15 schemes, encodings = list_schemes() |
15 schemes, encodings = list_schemes() |
16 """ |
16 """ |
17 |
17 |
|
18 import hashlib |
|
19 |
18 from crypt import crypt |
20 from crypt import crypt |
19 from random import SystemRandom |
21 from random import SystemRandom |
20 from subprocess import Popen, PIPE |
22 from subprocess import Popen, PIPE |
21 |
|
22 try: |
|
23 import hashlib |
|
24 except ImportError: |
|
25 from VirtualMailManager.pycompat import hashlib |
|
26 |
23 |
27 from VirtualMailManager import ENCODING |
24 from VirtualMailManager import ENCODING |
28 from VirtualMailManager.emailaddress import EmailAddress |
25 from VirtualMailManager.emailaddress import EmailAddress |
29 from VirtualMailManager.common import get_unicode, version_str |
26 from VirtualMailManager.common import get_unicode, version_str |
30 from VirtualMailManager.constants import VMM_ERROR |
27 from VirtualMailManager.constants import VMM_ERROR |
31 from VirtualMailManager.errors import VMMError |
28 from VirtualMailManager.errors import VMMError |
32 |
29 |
33 COMPAT = hasattr(hashlib, 'compat') |
|
34 SALTCHARS = './0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' |
30 SALTCHARS = './0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' |
35 PASSWDCHARS = '._-+#*23456789abcdefghikmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ' |
31 PASSWDCHARS = '._-+#*23456789abcdefghikmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ' |
36 DEFAULT_B64 = (None, 'B64', 'BASE64') |
32 DEFAULT_B64 = (None, 'B64', 'BASE64') |
37 DEFAULT_HEX = (None, 'HEX') |
33 DEFAULT_HEX = (None, 'HEX') |
38 CRYPT_ID_MD5 = 1 |
34 CRYPT_ID_MD5 = 1 |
79 return hashed |
75 return hashed |
80 |
76 |
81 |
77 |
82 def _md4_new(): |
78 def _md4_new(): |
83 """Returns an new MD4-hash object if supported by the hashlib or |
79 """Returns an new MD4-hash object if supported by the hashlib or |
84 provided by PyCrypto - other `None`. |
80 provided by PyCrypto - otherwise `None`. |
85 """ |
81 """ |
86 try: |
82 try: |
87 return hashlib.new('md4') |
83 return hashlib.new('md4') |
88 except ValueError, err: |
84 except ValueError, err: |
89 if str(err) == 'unsupported hash type': |
85 if str(err) == 'unsupported hash type': |
90 if not COMPAT: |
86 try: |
91 try: |
87 from Crypto.Hash import MD4 |
92 from Crypto.Hash import MD4 |
88 return MD4.new() |
93 return MD4.new() |
89 except ImportError: |
94 except ImportError: |
90 return None |
95 return None |
|
96 else: |
|
97 raise |
|
98 |
|
99 |
|
100 def _sha256_new(data=''): |
|
101 """Returns a new sha256 object from the hashlib. |
|
102 |
|
103 Returns `None` if the PyCrypto in pycompat.hashlib is too old.""" |
|
104 if not COMPAT: |
|
105 return hashlib.sha256(data) |
|
106 try: |
|
107 return hashlib.new('sha256', data) |
|
108 except ValueError, err: |
|
109 if str(err) == 'unsupported hash type': |
|
110 return None |
|
111 else: |
91 else: |
112 raise |
92 raise |
113 |
93 |
114 |
94 |
115 def _format_digest(digest, scheme, encoding): |
95 def _format_digest(digest, scheme, encoding): |
246 return _format_digest(digest, scheme, encoding) |
226 return _format_digest(digest, scheme, encoding) |
247 |
227 |
248 |
228 |
249 def _sha256_hash(password, scheme, encoding): |
229 def _sha256_hash(password, scheme, encoding): |
250 """Generates SHA256 hashes.""" |
230 """Generates SHA256 hashes.""" |
251 sha256 = _sha256_new(password) |
231 sha256 = hashlib.sha256(password) |
252 if sha256: |
232 if encoding in DEFAULT_B64: |
253 if encoding in DEFAULT_B64: |
233 digest = sha256.digest().encode('base64').rstrip() |
254 digest = sha256.digest().encode('base64').rstrip() |
234 else: |
255 else: |
235 digest = sha256.hexdigest() |
256 digest = sha256.hexdigest() |
236 return _format_digest(digest, scheme, encoding) |
257 return _format_digest(digest, scheme, encoding) |
|
258 return _dovecotpw(password, scheme, encoding) |
|
259 |
237 |
260 |
238 |
261 def _sha512_hash(password, scheme, encoding): |
239 def _sha512_hash(password, scheme, encoding): |
262 """Generates SHA512 hashes.""" |
240 """Generates SHA512 hashes.""" |
263 if not COMPAT: |
241 sha512 = hashlib.sha512(password) |
264 sha512 = hashlib.sha512(password) |
242 if encoding in DEFAULT_B64: |
265 if encoding in DEFAULT_B64: |
243 digest = sha512.digest().encode('base64').replace('\n', '') |
266 digest = sha512.digest().encode('base64').replace('\n', '') |
244 else: |
267 else: |
245 digest = sha512.hexdigest() |
268 digest = sha512.hexdigest() |
246 return _format_digest(digest, scheme, encoding) |
269 return _format_digest(digest, scheme, encoding) |
|
270 return _dovecotpw(password, scheme, encoding) |
|
271 |
247 |
272 |
248 |
273 def _smd5_hash(password, scheme, encoding): |
249 def _smd5_hash(password, scheme, encoding): |
274 """Generates SMD5 (salted PLAIN-MD5) hashes.""" |
250 """Generates SMD5 (salted PLAIN-MD5) hashes.""" |
275 md5 = hashlib.md5(password) |
251 md5 = hashlib.md5(password) |
294 return _format_digest(digest, scheme, encoding) |
270 return _format_digest(digest, scheme, encoding) |
295 |
271 |
296 |
272 |
297 def _ssha256_hash(password, scheme, encoding): |
273 def _ssha256_hash(password, scheme, encoding): |
298 """Generates SSHA256 (salted SHA256) hashes.""" |
274 """Generates SSHA256 (salted SHA256) hashes.""" |
299 sha256 = _sha256_new(password) |
275 sha256 = hashlib.sha256(password) |
300 if sha256: |
276 salt = _get_salt(SALTED_ALGO_SALT_LEN) |
301 salt = _get_salt(SALTED_ALGO_SALT_LEN) |
277 sha256.update(salt) |
302 sha256.update(salt) |
278 if encoding in DEFAULT_B64: |
303 if encoding in DEFAULT_B64: |
279 digest = (sha256.digest() + salt).encode('base64').rstrip() |
304 digest = (sha256.digest() + salt).encode('base64').rstrip() |
280 else: |
305 else: |
281 digest = sha256.hexdigest() + salt.encode('hex') |
306 digest = sha256.hexdigest() + salt.encode('hex') |
282 return _format_digest(digest, scheme, encoding) |
307 return _format_digest(digest, scheme, encoding) |
|
308 return _dovecotpw(password, scheme, encoding) |
|
309 |
283 |
310 |
284 |
311 def _ssha512_hash(password, scheme, encoding): |
285 def _ssha512_hash(password, scheme, encoding): |
312 """Generates SSHA512 (salted SHA512) hashes.""" |
286 """Generates SSHA512 (salted SHA512) hashes.""" |
313 if not COMPAT: |
287 salt = _get_salt(SALTED_ALGO_SALT_LEN) |
314 salt = _get_salt(SALTED_ALGO_SALT_LEN) |
288 sha512 = hashlib.sha512(password + salt) |
315 sha512 = hashlib.sha512(password + salt) |
289 if encoding in DEFAULT_B64: |
316 if encoding in DEFAULT_B64: |
290 digest = (sha512.digest() + salt).encode('base64').replace('\n', '') |
317 digest = (sha512.digest() + salt).encode('base64').replace('\n', |
291 else: |
318 '') |
292 digest = sha512.hexdigest() + salt.encode('hex') |
319 else: |
293 return _format_digest(digest, scheme, encoding) |
320 digest = sha512.hexdigest() + salt.encode('hex') |
|
321 return _format_digest(digest, scheme, encoding) |
|
322 return _dovecotpw(password, scheme, encoding) |
|
323 |
294 |
324 _scheme_info = { |
295 _scheme_info = { |
325 'CLEARTEXT': (_clear_hash, 0x10000f00), |
296 'CLEARTEXT': (_clear_hash, 0x10000f00), |
326 'CRAM-MD5': (_dovecotpw, 0x10000f00), |
297 'CRAM-MD5': (_dovecotpw, 0x10000f00), |
327 'CRYPT': (_crypt_hash, 0x10000f00), |
298 'CRYPT': (_crypt_hash, 0x10000f00), |