This list is closed, nobody may subscribe to it.
| 2009 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(2) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2010 |
Jan
(18) |
Feb
(43) |
Mar
(11) |
Apr
(50) |
May
(10) |
Jun
|
Jul
(39) |
Aug
(30) |
Sep
|
Oct
|
Nov
|
Dec
|
| 2011 |
Jan
(14) |
Feb
(43) |
Mar
(2) |
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
(4) |
Oct
(12) |
Nov
(45) |
Dec
(3) |
| 2012 |
Jan
|
Feb
|
Mar
(2) |
Apr
(65) |
May
(2) |
Jun
(19) |
Jul
(6) |
Aug
(19) |
Sep
(23) |
Oct
(11) |
Nov
(21) |
Dec
(16) |
| 2013 |
Jan
(21) |
Feb
(2) |
Mar
(2) |
Apr
|
May
|
Jun
(2) |
Jul
|
Aug
(2) |
Sep
|
Oct
|
Nov
|
Dec
|
| 2014 |
Jan
(4) |
Feb
(34) |
Mar
(10) |
Apr
|
May
|
Jun
(10) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
|
|
|
|
|
|
|
1
|
|
2
|
3
(3) |
4
(2) |
5
|
6
|
7
|
8
|
|
9
(1) |
10
(1) |
11
(1) |
12
(1) |
13
|
14
|
15
|
|
16
|
17
|
18
(1) |
19
|
20
|
21
|
22
|
|
23
|
24
|
25
|
26
|
27
|
28
|
29
|
|
30
|
31
|
|
|
|
|
|
|
From: <nev...@us...> - 2010-05-18 07:00:36
|
details: http://hg.localdomain.org/vmm/rev/7d1bafc6fa30 changeset: 294:7d1bafc6fa30 user: Pascal Volk date: Tue May 18 07:00:21 2010 +0000 description: VMM/Domain: removed functions ace2idna() and idn2ascii(). domainname.encode('idna')/domainname.decode('idna') works too. diffstat: VirtualMailManager/Domain.py | 16 +--------------- VirtualMailManager/Handler.py | 5 +++-- 2 files changed, 4 insertions(+), 17 deletions(-) diffs (70 lines): diff -r a77b67673aa6 -r 7d1bafc6fa30 VirtualMailManager/Domain.py --- a/VirtualMailManager/Domain.py Wed May 12 07:40:59 2010 +0000 +++ b/VirtualMailManager/Domain.py Tue May 18 07:00:21 2010 +0000 @@ -10,7 +10,6 @@ import os import re -from encodings.idna import ToASCII, ToUnicode from random import choice from VirtualMailManager.constants.ERROR import \ @@ -319,23 +318,15 @@ return aliasdomains -def ace2idna(domainname): - """Converts the domain name `domainname` from ACE according to IDNA.""" - return u'.'.join([ToUnicode(lbl) for lbl in domainname.split('.') if lbl]) - - def check_domainname(domainname): """Returns the validated domain name `domainname`. - It also converts the name of the domain from IDN to ASCII, if - necessary. - Throws an `DomainError`, if the domain name is too long or doesn't look like a valid domain name (label.label.label). """ if not RE_DOMAIN.match(domainname): - domainname = idn2ascii(domainname) + domainname = domainname.encode('idna') if len(domainname) > 255: raise DomErr(_(u'The domain name is too long'), DOMAIN_TOO_LONG) if not RE_DOMAIN.match(domainname): @@ -359,11 +350,6 @@ return 0 -def idn2ascii(domainname): - """Converts the idn domain name `domainname` into punycode.""" - return '.'.join([ToASCII(lbl) for lbl in domainname.split('.') if lbl]) - - def search(dbh, pattern=None, like=False): """'Search' for domains by *pattern* in the database. diff -r a77b67673aa6 -r 7d1bafc6fa30 VirtualMailManager/Handler.py --- a/VirtualMailManager/Handler.py Wed May 12 07:40:59 2010 +0000 +++ b/VirtualMailManager/Handler.py Tue May 18 07:00:21 2010 +0000 @@ -26,7 +26,7 @@ from VirtualMailManager.AliasDomain import AliasDomain from VirtualMailManager.common import exec_ok from VirtualMailManager.Config import Config as Cfg -from VirtualMailManager.Domain import Domain, ace2idna, get_gid +from VirtualMailManager.Domain import Domain, get_gid from VirtualMailManager.EmailAddress import EmailAddress from VirtualMailManager.errors import \ DomainError, NotRootError, PermissionError, VMMError @@ -416,7 +416,8 @@ dom = self.__getDomain(domainname) dominfo = dom.get_info() if dominfo['domainname'].startswith('xn--'): - dominfo['domainname'] += ' (%s)' % ace2idna(dominfo['domainname']) + dominfo['domainname'] += ' (%s)' % \ + dominfo['domainname'].decode('idna') if details is None: return dominfo elif details == 'accounts': |
|
From: <nev...@us...> - 2010-05-12 07:41:17
|
details: http://hg.localdomain.org/vmm/rev/a77b67673aa6 changeset: 293:a77b67673aa6 user: Pascal Volk date: Wed May 12 07:40:59 2010 +0000 description: VMM/Account: replaced attribute _mid : int by _mail : MailLocation. diffstat: VirtualMailManager/Account.py | 22 ++++++++++++++-------- VirtualMailManager/Handler.py | 2 +- 2 files changed, 15 insertions(+), 9 deletions(-) diffs (96 lines): diff -r 619dadc0fd25 -r a77b67673aa6 VirtualMailManager/Account.py --- a/VirtualMailManager/Account.py Tue May 11 01:54:50 2010 +0000 +++ b/VirtualMailManager/Account.py Wed May 12 07:40:59 2010 +0000 @@ -27,7 +27,7 @@ class Account(object): """Class to manage e-mail accounts.""" - __slots__ = ('_addr', '_dbh', '_domain', '_mid', '_new', '_passwd', + __slots__ = ('_addr', '_dbh', '_domain', '_mail', '_new', '_passwd', '_transport', '_uid') def __init__(self, dbh, address): @@ -52,7 +52,7 @@ raise AErr(_(u"The domain '%s' doesn't exist.") % self._addr.domainname, NO_SUCH_DOMAIN) self._uid = 0 - self._mid = 0 + self._mail = None self._transport = self._domain.transport self._passwd = None self._new = True @@ -71,9 +71,10 @@ result = dbc.fetchone() dbc.close() if result: - self._uid, self._mid, _tid = result + self._uid, _mid, _tid = result if _tid != self._transport.tid: self._transport = Transport(self._dbh, tid=_tid) + self._mail = MailLocation(mid=_mid) self._new = False def _set_uid(self): @@ -100,7 +101,7 @@ u" prefix '%(prefix)s'") % {'transport': self._transport, 'prefix': maillocation.prefix}, INVALID_MAIL_LOCATION) - self._mid = maillocation.mid + self._mail = maillocation self._set_uid() def _switch_state(self, state, service): @@ -175,6 +176,11 @@ return None @property + def mail_location(self): + """The Account's MailLocation.""" + return self._mail + + @property def uid(self): """The Account's unique ID.""" return self._uid @@ -246,7 +252,7 @@ smtp, pop3, imap, %s) VALUES ('%s', '%s', %d, %d, %d, %d, %s, %s, %s, %s)" % ( sieve_col, self._addr.localpart, pwhash(self._passwd, user=self._addr), - self._uid, self._domain.gid, self._mid, self._transport.tid, + self._uid, self._domain.gid, self._mail.mid, self._transport.tid, cfg_dget('account.smtp'), cfg_dget('account.pop3'), cfg_dget('account.imap'), cfg_dget('account.sieve')) dbc = self._dbh.cursor() @@ -318,7 +324,7 @@ info['address'] = self._addr info['gid'] = self._domain.gid info['home'] = '%s/%s' % (self._domain.directory, self._uid) - info['mail_location'] = MailLocation(mid=self._mid).mail_location + info['mail_location'] = self._mail.mail_location info['transport'] = self._transport.transport info['uid'] = self._uid return info @@ -374,9 +380,9 @@ self._dbh.commit() dbc.close() self._new = True - self._uid = self._mid = 0 + self._uid = 0 self._addr = self._dbh = self._domain = self._passwd = None - self._transport = None + self._mail = self._transport = None def get_account_by_uid(uid, dbh): diff -r 619dadc0fd25 -r a77b67673aa6 VirtualMailManager/Handler.py --- a/VirtualMailManager/Handler.py Tue May 11 01:54:50 2010 +0000 +++ b/VirtualMailManager/Handler.py Wed May 12 07:40:59 2010 +0000 @@ -577,7 +577,7 @@ acc.address, ERR.NO_SUCH_ACCOUNT) info = acc.get_info() if self._Cfg.dget('account.disk_usage') or details in ('du', 'full'): - path = os.path.join(acc.home, info['mail_location'].split('/')[-1]) + path = os.path.join(acc.home, acc.mail_location.directory) info['disk usage'] = self.__getDiskUsage(path) if details in (None, 'du'): return info |
|
From: <nev...@us...> - 2010-05-11 01:55:03
|
details: http://hg.localdomain.org/vmm/rev/619dadc0fd25 changeset: 292:619dadc0fd25 user: Pascal Volk date: Tue May 11 01:54:50 2010 +0000 description: VMM/password: added some CRYPT_* constants. Reverted modification (284:ec1966828246) in _get_salt(). diffstat: TODO | 8 ++-- VirtualMailManager/password.py | 67 ++++++++++++++++++++++++++--------------- 2 files changed, 47 insertions(+), 28 deletions(-) diffs (152 lines): diff -r 7ef3f117a230 -r 619dadc0fd25 TODO --- a/TODO Mon May 10 09:06:57 2010 +0000 +++ b/TODO Tue May 11 01:54:50 2010 +0000 @@ -19,9 +19,9 @@ + alias domains Database: - public.users.passwd: increase to "character varying(250)" - why? len(VirtualMailManager.password.pwhash('1', 'crypt.hex')) -> 249 - if VirtualMailManager.password.CRYPT_SHA512 is True and - misc.crypt_sha512_rounds > 0 + public.users.passwd: increase to "character varying(264)" + why? len(VirtualMailManager.password.pwhash('1', 'sha512-crypt.hex')) -> 264 + if Dovecot >= v2.0.beta6 || changeset >= 11278:2ead7574bb08 and + misc.crypt_sha512_rounds >= 100000000 public.users.digestmd5: add "character varying(48)" Outlook will love it. (`doveadm pw -s DIGEST-MD5.hex -p 1 -u 0`) diff -r 7ef3f117a230 -r 619dadc0fd25 VirtualMailManager/password.py --- a/VirtualMailManager/password.py Mon May 10 09:06:57 2010 +0000 +++ b/VirtualMailManager/password.py Tue May 11 01:54:50 2010 +0000 @@ -34,11 +34,27 @@ PASSWDCHARS = '._-+#*23456789abcdefghikmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ' DEFAULT_B64 = (None, 'B64', 'BASE64') DEFAULT_HEX = (None, 'HEX') +CRYPT_ID_MD5 = 1 +CRYPT_ID_BLF = '2a' +CRYPT_ID_SHA256 = 5 +CRYPT_ID_SHA512 = 6 +CRYPT_SALT_LEN = 2 +CRYPT_BLF_ROUNDS_MIN = 4 +CRYPT_BLF_ROUNDS_MAX = 31 +CRYPT_BLF_SALT_LEN = 22 +CRYPT_MD5_SALT_LEN = 8 +CRYPT_SHA2_ROUNDS_DEFAULT = 5000 +CRYPT_SHA2_ROUNDS_MIN = 1000 +CRYPT_SHA2_ROUNDS_MAX = 999999999 +CRYPT_SHA2_SALT_LEN = 16 +SALTED_ALGO_SALT_LEN = 4 + _ = lambda msg: msg cfg_dget = lambda option: None _sys_rand = SystemRandom() -_get_salt = lambda salt_len: ''.join(_sys_rand.sample(SALTCHARS, salt_len)) +_choice = _sys_rand.choice +_get_salt = lambda s_len: ''.join(_choice(SALTCHARS) for x in xrange(s_len)) def _dovecotpw(password, scheme, encoding): @@ -116,44 +132,47 @@ def _get_crypt_blowfish_salt(): """Generates a salt for Blowfish crypt.""" rounds = cfg_dget('misc.crypt_blowfish_rounds') - if rounds < 4: - rounds = 4 - elif rounds > 31: - rounds = 31 - return '$2a$%02d$%s' % (rounds, _get_salt(22)) + if rounds < CRYPT_BLF_ROUNDS_MIN: + rounds = CRYPT_BLF_ROUNDS_MIN + elif rounds > CRYPT_BLF_ROUNDS_MAX: + rounds = CRYPT_BLF_ROUNDS_MAX + return '$%s$%02d$%s' % (CRYPT_ID_BLF, rounds, + _get_salt(CRYPT_BLF_SALT_LEN)) def _get_crypt_sha2_salt(crypt_id): """Generates a salt for crypt using the SHA-256 or SHA-512 encryption method. - *crypt_id* must be either `5` (SHA-256) or `6` (SHA1-512). + *crypt_id* must be either `5` (SHA-256) or `6` (SHA-512). """ - assert crypt_id in (5, 6), 'invalid crypt id: %r' % crypt_id - if crypt_id is 6: + assert crypt_id in (CRYPT_ID_SHA256, CRYPT_ID_SHA512), 'invalid crypt ' \ + 'id: %r' % crypt_id + if crypt_id is CRYPT_ID_SHA512: rounds = cfg_dget('misc.crypt_sha512_rounds') else: rounds = cfg_dget('misc.crypt_sha256_rounds') - if rounds < 1000: - rounds = 1000 - elif rounds > 999999999: - rounds = 999999999 - if rounds == 5000: - return '$%d$%s' % (crypt_id, _get_salt(16)) - return '$%d$rounds=%d$%s' % (crypt_id, rounds, _get_salt(16)) + if rounds < CRYPT_SHA2_ROUNDS_MIN: + rounds = CRYPT_SHA2_ROUNDS_MIN + elif rounds > CRYPT_SHA2_ROUNDS_MAX: + rounds = CRYPT_SHA2_ROUNDS_MAX + if rounds == CRYPT_SHA2_ROUNDS_DEFAULT: + return '$%d$%s' % (crypt_id, _get_salt(CRYPT_SHA2_SALT_LEN)) + return '$%d$rounds=%d$%s' % (crypt_id, rounds, + _get_salt(CRYPT_SHA2_SALT_LEN)) def _crypt_hash(password, scheme, encoding): """Generates (encoded) CRYPT/MD5/{BLF,MD5,SHA{256,512}}-CRYPT hashes.""" if scheme == 'CRYPT': - salt = _get_salt(2) + salt = _get_salt(CRYPT_SALT_LEN) elif scheme == 'BLF-CRYPT': salt = _get_crypt_blowfish_salt() elif scheme in ('MD5-CRYPT', 'MD5'): - salt = '$1$%s' % _get_salt(8) + salt = '$%d$%s' % (CRYPT_ID_MD5, _get_salt(CRYPT_MD5_SALT_LEN)) elif scheme == 'SHA256-CRYPT': - salt = _get_crypt_sha2_salt(5) + salt = _get_crypt_sha2_salt(CRYPT_ID_SHA256) else: - salt = _get_crypt_sha2_salt(6) + salt = _get_crypt_sha2_salt(CRYPT_ID_SHA512) encrypted = crypt(password, salt) if encoding: if encoding == 'HEX': @@ -253,7 +272,7 @@ def _smd5_hash(password, scheme, encoding): """Generates SMD5 (salted PLAIN-MD5) hashes.""" md5 = hashlib.md5(password) - salt = _get_salt(4) + salt = _get_salt(SALTED_ALGO_SALT_LEN) md5.update(salt) if encoding in DEFAULT_B64: digest = (md5.digest() + salt).encode('base64').rstrip() @@ -265,7 +284,7 @@ def _ssha1_hash(password, scheme, encoding): """Generates SSHA (salted SHA/SHA1) hashes.""" sha1 = hashlib.sha1(password) - salt = _get_salt(4) + salt = _get_salt(SALTED_ALGO_SALT_LEN) sha1.update(salt) if encoding in DEFAULT_B64: digest = (sha1.digest() + salt).encode('base64').rstrip() @@ -278,7 +297,7 @@ """Generates SSHA256 (salted SHA256) hashes.""" sha256 = _sha256_new(password) if sha256: - salt = _get_salt(4) + salt = _get_salt(SALTED_ALGO_SALT_LEN) sha256.update(salt) if encoding in DEFAULT_B64: digest = (sha256.digest() + salt).encode('base64').rstrip() @@ -291,7 +310,7 @@ def _ssha512_hash(password, scheme, encoding): """Generates SSHA512 (salted SHA512) hashes.""" if not COMPAT: - salt = _get_salt(4) + salt = _get_salt(SALTED_ALGO_SALT_LEN) sha512 = hashlib.sha512(password + salt) if encoding in DEFAULT_B64: digest = (sha512.digest() + salt).encode('base64').replace('\n', |
|
From: <nev...@us...> - 2010-05-10 09:07:12
|
details: http://hg.localdomain.org/vmm/rev/7ef3f117a230 changeset: 291:7ef3f117a230 user: Pascal Volk date: Mon May 10 09:06:57 2010 +0000 description: VMM/password: adapted Blowfish/SHA-256/SHA-512 crypt() to recent changes in the Dovecot-2.0 source tree. VMM/Config: Added default number of encryption rounds to the configuration. man5: updated description of misc.crypt_{blowfish,sha{256,512}}_rounds. diffstat: VirtualMailManager/Config.py | 6 +- VirtualMailManager/password.py | 65 +++++++++++++++++++++-------------------- man/de/man5/vmm.cfg.5.rst | 38 ++++++------------------ man/man5/vmm.cfg.5.rst | 31 ++++--------------- 4 files changed, 53 insertions(+), 87 deletions(-) diffs (252 lines): diff -r e2785e04f92e -r 7ef3f117a230 VirtualMailManager/Config.py --- a/VirtualMailManager/Config.py Sun May 09 06:20:52 2010 +0000 +++ b/VirtualMailManager/Config.py Mon May 10 09:06:57 2010 +0000 @@ -344,9 +344,9 @@ }, 'misc': { 'base_directory': LCO(str, '/srv/mail', self.get, is_dir), - 'crypt_blowfish_rounds': LCO(int, 0, self.getint), - 'crypt_sha256_rounds': LCO(int, 0, self.getint), - 'crypt_sha512_rounds': LCO(int, 0, self.getint), + 'crypt_blowfish_rounds': LCO(int, 5, self.getint), + 'crypt_sha256_rounds': LCO(int, 5000, self.getint), + 'crypt_sha512_rounds': LCO(int, 5000, self.getint), 'dovecot_version': LCO(str, None, self.hexversion, check_version_format), 'password_scheme': LCO(str, 'CRAM-MD5', self.get, diff -r e2785e04f92e -r 7ef3f117a230 VirtualMailManager/password.py --- a/VirtualMailManager/password.py Sun May 09 06:20:52 2010 +0000 +++ b/VirtualMailManager/password.py Mon May 10 09:06:57 2010 +0000 @@ -41,26 +41,6 @@ _get_salt = lambda salt_len: ''.join(_sys_rand.sample(SALTCHARS, salt_len)) -def _test_crypt_algorithms(): - """Check for Blowfish/SHA-256/SHA-512 support in crypt.crypt().""" - blowfish_ = sha256_ = sha512_ = False - _blowfish = '$2a$04$0123456789abcdefABCDE.N.drYX5yIAL1LkTaaZotW3yI0hQhZru' - _sha256 = '$5$rounds=1000$0123456789abcdef$K/DksR0DT01hGc8g/kt9McEgrbFMKi\ -9qrb1jehe7hn4' - _sha512 = '$6$rounds=1000$0123456789abcdef$ZIAd5WqfyLkpvsVCVUU1GrvqaZTqvh\ -JoouxdSqJO71l9Ld3tVrfOatEjarhghvEYADkq//LpDnTeO90tcbtHR1' - - if crypt('08/15!test~4711', '$2a$04$0123456789abcdefABCDEF$') == _blowfish: - blowfish_ = True - if crypt('08/15!test~4711', '$5$rounds=1000$0123456789abcdef$') == _sha256: - sha256_ = True - if crypt('08/15!test~4711', '$6$rounds=1000$0123456789abcdef$') == _sha512: - sha512_ = True - return blowfish_, sha256_, sha512_ - -CRYPT_BLOWFISH, CRYPT_SHA256, CRYPT_SHA512 = _test_crypt_algorithms() - - def _dovecotpw(password, scheme, encoding): """Communicates with dovecotpw (Dovecot 2.0: `doveadm pw`) and returns the hashed password: {scheme[.encoding]}hash @@ -143,7 +123,7 @@ return '$2a$%02d$%s' % (rounds, _get_salt(22)) -def _get_crypt_shaxxx_salt(crypt_id): +def _get_crypt_sha2_salt(crypt_id): """Generates a salt for crypt using the SHA-256 or SHA-512 encryption method. *crypt_id* must be either `5` (SHA-256) or `6` (SHA1-512). @@ -157,28 +137,32 @@ rounds = 1000 elif rounds > 999999999: rounds = 999999999 + if rounds == 5000: + return '$%d$%s' % (crypt_id, _get_salt(16)) return '$%d$rounds=%d$%s' % (crypt_id, rounds, _get_salt(16)) def _crypt_hash(password, scheme, encoding): - """Generates (encoded) CRYPT/MD5/MD5-CRYPT hashes.""" + """Generates (encoded) CRYPT/MD5/{BLF,MD5,SHA{256,512}}-CRYPT hashes.""" if scheme == 'CRYPT': - if CRYPT_BLOWFISH and cfg_dget('misc.crypt_blowfish_rounds'): - salt = _get_crypt_blowfish_salt() - elif CRYPT_SHA512 and cfg_dget('misc.crypt_sha512_rounds'): - salt = _get_crypt_shaxxx_salt(6) - elif CRYPT_SHA256 and cfg_dget('misc.crypt_sha256_rounds'): - salt = _get_crypt_shaxxx_salt(5) - else: - salt = _get_salt(2) + salt = _get_salt(2) + elif scheme == 'BLF-CRYPT': + salt = _get_crypt_blowfish_salt() + elif scheme in ('MD5-CRYPT', 'MD5'): + salt = '$1$%s' % _get_salt(8) + elif scheme == 'SHA256-CRYPT': + salt = _get_crypt_sha2_salt(5) else: - salt = '$1$%s' % _get_salt(8) + salt = _get_crypt_sha2_salt(6) encrypted = crypt(password, salt) if encoding: if encoding == 'HEX': encrypted = encrypted.encode('hex') else: encrypted = encrypted.encode('base64').replace('\n', '') + if scheme in ('BLF-CRYPT', 'SHA256-CRYPT', 'SHA512-CRYPT') and \ + cfg_dget('misc.dovecot_version') < 0x20000b06: + scheme = 'CRYPT' return _format_digest(encrypted, scheme, encoding) @@ -363,7 +347,7 @@ assert isinstance(scheme, basestring), 'Not a str/unicode: %r' % scheme scheme_encoding = scheme.upper().split('.') scheme = scheme_encoding[0] - if not scheme in _scheme_info: + if scheme not in _scheme_info: raise VMMError(_(u"Unsupported password scheme: '%s'") % scheme, VMM_ERROR) if cfg_dget('misc.dovecot_version') < _scheme_info[scheme][1]: @@ -418,4 +402,21 @@ pw_len = 8 return ''.join(_sys_rand.sample(PASSWDCHARS, pw_len)) + +def _test_crypt_algorithms(): + """Check for Blowfish/SHA-256/SHA-512 support in crypt.crypt().""" + _blowfish = '$2a$04$0123456789abcdefABCDE.N.drYX5yIAL1LkTaaZotW3yI0hQhZru' + _sha256 = '$5$rounds=1000$0123456789abcdef$K/DksR0DT01hGc8g/kt9McEgrbFMKi\ +9qrb1jehe7hn4' + _sha512 = '$6$rounds=1000$0123456789abcdef$ZIAd5WqfyLkpvsVCVUU1GrvqaZTqvh\ +JoouxdSqJO71l9Ld3tVrfOatEjarhghvEYADkq//LpDnTeO90tcbtHR1' + + if crypt('08/15!test~4711', '$2a$04$0123456789abcdefABCDEF$') == _blowfish: + _scheme_info['BLF-CRYPT'] = (_crypt_hash, 0x10000f00) + if crypt('08/15!test~4711', '$5$rounds=1000$0123456789abcdef$') == _sha256: + _scheme_info['SHA256-CRYPT'] = (_crypt_hash, 0x10000f00) + if crypt('08/15!test~4711', '$6$rounds=1000$0123456789abcdef$') == _sha512: + _scheme_info['SHA512-CRYPT'] = (_crypt_hash, 0x10000f00) + +_test_crypt_algorithms() del _, cfg_dget, _test_crypt_algorithms diff -r e2785e04f92e -r 7ef3f117a230 man/de/man5/vmm.cfg.5.rst --- a/man/de/man5/vmm.cfg.5.rst Sun May 09 06:20:52 2010 +0000 +++ b/man/de/man5/vmm.cfg.5.rst Mon May 10 09:06:57 2010 +0000 @@ -360,43 +360,25 @@ .. _misc.crypt_blowfish_rounds: -``crypt_blowfish_rounds (Vorgabe: 0)`` : *Int* - Anzahl der Verschlüsselungsdurchgänge für Blowfish-Crypt. - - Diese Einstellung beeinflusst das Verhalten des 'CRYPT'-Passwortschematas. - Standardmäßig verwendet crypt den DES-Algorithmus für die - Kennwortverschlüsselung. |vmm(1)|_ prüft, ob Blowfish-Crypt verfügbar - ist. Wenn der Blowfishalgorithmus unterstützt wird und der Wert dieser - Einstellung größer als 0 ist, wird Blowfish anstelle von DES als - Algorithmus verwendet. +``crypt_blowfish_rounds (Vorgabe: 5)`` : *Int* + Anzahl der Verschlüsselungsdurchgänge für das *password_scheme* + **BLF-CRYPT**. Der Wert muss im Bereich von **4** - **31** liegen. .. _misc.crypt_sha256_rounds: -``crypt_sha256_rounds (Vorgabe: 0)`` : *Int* - Anzahl der Verschlüsselungdurchgänge für crypt unter Verwendung der SHA-256 - Verschlüsselungsmethode. - - Diese Einstellung beeinflusst das Verhalten des 'CRYPT'-Passwortschematas. - Standardmäßig verwendet crypt den DES-Algorithmus für die - Kennwortverschlüsselung. |vmm(1)|_ prüft, ob crypt die SHA-256 und/oder - SHA-512 Algorithmen unterstützt. Wenn die Algorithmen unterstützt werden - und der Wert dieser Einstellung größer als 0 ist, wird SHA-256 anstelle - von DES als Algorithmus verwendet. - - Wenn der Wert von |misc.crypt_sha512_rounds|_ größer als 0 ist, wird der - SHA-512 Algorithmus anstelle von SHA-256 verwendet. +``crypt_sha256_rounds (Vorgabe: 5000)`` : *Int* + Anzahl der Verschlüsselungdurchgänge für das *password_scheme* + **SHA256-CRYPT**. Der Wert muss im Bereich von **1000** - **999999999** liegen. .. _misc.crypt_sha512_rounds: -``crypt_sha512_rounds (Vorgabe: 0)`` : *Int* - Anzahl der Verschlüsselungsdurchgänge für crypt unter Verwendung - der SHA-512 Verschlüsselungsmethode. - - Siehe |misc.crypt_sha256_rounds|_ für Details. +``crypt_sha512_rounds (Vorgabe: 5000)`` : *Int* + Anzahl der Verschlüsselungsdurchgänge für das *password_scheme* + **SHA256-CRYPT**. Der Wert muss im Bereich von **1000** - **999999999** liegen. @@ -427,7 +409,7 @@ [misc] base_directory = /srv/mail crypt_sha512_rounds = 10000 - password_scheme = CRYPT + password_scheme = SHA512-CRYPT transport = dovecot: dovecot_version = 2.0.beta4 diff -r e2785e04f92e -r 7ef3f117a230 man/man5/vmm.cfg.5.rst --- a/man/man5/vmm.cfg.5.rst Sun May 09 06:20:52 2010 +0000 +++ b/man/man5/vmm.cfg.5.rst Mon May 10 09:06:57 2010 +0000 @@ -344,39 +344,22 @@ .. _misc.crypt_blowfish_rounds: -``crypt_blowfish_rounds (default: 0)`` : *Int* - Number of encryption rounds for Blowfish crypt. - - This setting affects the behavior of the 'CRYPT' password scheme. By - default crypt will use the DES algorithm for password encryption. - |vmm(1)|_ checks if Blowfish crypt is available. When the Blowfish - algorithm is supported and the value of this setting is greater than 0 - Blowfish will be used for crypt, instead of DES. +``crypt_blowfish_rounds (default: 5)`` : *Int* + Number of encryption rounds for the *password_scheme* **BLF-CRYPT**. The value must be in range **4** - **31**. .. _misc.crypt_sha256_rounds: -``crypt_sha256_rounds (default: 0)`` : *Int* - Number of encryption rounds for crypt using the SHA-256 encryption method. - - This setting affects the behavior of the 'CRYPT' password scheme. By - default crypt will use the DES algorithm for password encryption. - |vmm(1)|_ checks if crypt supports the SHA-256 and/or SHA-512 algorithms. - When the algorithms are supported and the value of this setting is greater - than 0, SHA-256 will be used instead of DES. - - When the value of |misc.crypt_sha512_rounds|_ is greater than 0, the - SHA-512 algorithm will be used instead of SHA-256. +``crypt_sha256_rounds (default: 5000)`` : *Int* + Number of encryption rounds for the *password_scheme* **SHA256-CRYPT**. The value must be in range **1000** - **999999999**. .. _misc.crypt_sha512_rounds: -``crypt_sha512_rounds (default: 0)`` : *Int* - Number of encryption rounds for crypt using the SHA-512 encryption method. - - See |misc.crypt_sha256_rounds|_ for details. +``crypt_sha512_rounds (default: 5000)`` : *Int* + Number of encryption rounds for the *password_scheme* **SHA512-CRYPT**. The value must be in range **1000** - **999999999**. @@ -407,7 +390,7 @@ [misc] base_directory = /srv/mail crypt_sha512_rounds = 10000 - password_scheme = CRYPT + password_scheme = SHA512-CRYPT transport = dovecot: dovecot_version = 2.0.beta4 |
|
From: <nev...@us...> - 2010-05-09 06:21:10
|
details: http://hg.localdomain.org/vmm/rev/e2785e04f92e changeset: 290:e2785e04f92e user: Pascal Volk date: Sun May 09 06:20:52 2010 +0000 description: VMM/…: re-indented long queries and error messages. diffstat: VirtualMailManager/Account.py | 42 ++++++++++++++------------- VirtualMailManager/Alias.py | 20 ++++++------- VirtualMailManager/AliasDomain.py | 30 ++++++++----------- VirtualMailManager/Config.py | 4 +- VirtualMailManager/Domain.py | 32 ++++++++++----------- VirtualMailManager/EmailAddress.py | 7 ++-- VirtualMailManager/Handler.py | 56 +++++++++++++++++-------------------- VirtualMailManager/Relocated.py | 13 ++++---- VirtualMailManager/cli/Config.py | 8 ++-- VirtualMailManager/ext/Postconf.py | 5 ++- VirtualMailManager/password.py | 16 ++++------ 11 files changed, 110 insertions(+), 123 deletions(-) diffs (truncated from 540 to 300 lines): diff -r 142f188f7552 -r e2785e04f92e VirtualMailManager/Account.py --- a/VirtualMailManager/Account.py Wed May 05 21:50:31 2010 +0000 +++ b/VirtualMailManager/Account.py Sun May 09 06:20:52 2010 +0000 @@ -66,9 +66,8 @@ """Load 'uid', 'mid' and 'tid' from the database and set _new to `False` - if the user could be found. """ dbc = self._dbh.cursor() - dbc.execute( - "SELECT uid, mid, tid FROM users WHERE gid=%s AND local_part=%s", - self._domain.gid, self._addr.localpart) + dbc.execute('SELECT uid, mid, tid FROM users WHERE gid = %s AND ' + 'local_part = %s', self._domain.gid, self._addr.localpart) result = dbc.fetchone() dbc.close() if result: @@ -90,16 +89,17 @@ information in the database. """ if maillocation.dovecot_version > cfg_dget('misc.dovecot_version'): - raise AErr(_("The mail_location prefix '%(prefix)s' requires \ -Dovecot >= v%(version)s") % {'prefix': maillocation.prefix, - 'version': version_str(maillocation.dovecot_version)}, + raise AErr(_(u"The mail_location prefix '%(prefix)s' requires " + u"Dovecot >= v%(version)s") % + {'prefix': maillocation.prefix, + 'version': version_str(maillocation.dovecot_version)}, INVALID_MAIL_LOCATION) if not maillocation.postfix and \ self._transport.transport.lower() in ('virtual:', 'virtual'): - raise AErr(_(u"Invalid transport '%(transport)s' for mail_location\ - prefix '%(prefix)s'") % {'transport': self._transport, - 'prefix': maillocation.prefix}, - INVALID_MAIL_LOCATION) + raise AErr(_(u"Invalid transport '%(transport)s' for mail_location" + u" prefix '%(prefix)s'") % + {'transport': self._transport, + 'prefix': maillocation.prefix}, INVALID_MAIL_LOCATION) self._mid = maillocation.mid self._set_uid() @@ -323,17 +323,18 @@ info['uid'] = self._uid return info # nearly impossible‽ - raise AErr(_(u"Couldn't fetch information for account: '%s'") \ - % self._addr, NO_SUCH_ACCOUNT) + raise AErr(_(u"Couldn't fetch information for account: '%s'") % + self._addr, NO_SUCH_ACCOUNT) def get_aliases(self): """Return a list with all alias e-mail addresses, whose destination is the address of the Account.""" self._chk_state() dbc = self._dbh.cursor() - dbc.execute("SELECT address ||'@'|| domainname FROM alias, domain_name\ - WHERE destination = %s AND domain_name.gid = alias.gid\ - AND domain_name.is_primary ORDER BY address", str(self._addr)) + dbc.execute("SELECT address ||'@'|| domainname FROM alias, " + "domain_name WHERE destination = %s AND domain_name.gid = " + "alias.gid AND domain_name.is_primary ORDER BY address", + str(self._addr)) addresses = dbc.fetchall() dbc.close() aliases = [] @@ -365,8 +366,8 @@ a_count = self._count_aliases() if a_count > 0: dbc.close() - raise AErr(_(u"There are %(count)d aliases with the \ -destination address '%(address)s'.") % \ + raise AErr(_(u"There are %(count)d aliases with the " + u"destination address '%(address)s'.") % {'count': a_count, 'address': self._addr}, ALIAS_PRESENT) dbc.execute('DELETE FROM users WHERE uid = %s', self._uid) @@ -398,9 +399,10 @@ if uid < 1: raise AErr(_(u'UID must be greater than 0.'), INVALID_AGUMENT) dbc = dbh.cursor() - dbc.execute("SELECT local_part||'@'|| domain_name.domainname AS address,\ - uid, users.gid FROM users LEFT JOIN domain_name ON (domain_name.gid \ - = users.gid AND is_primary) WHERE uid = %s;", uid) + dbc.execute("SELECT local_part||'@'|| domain_name.domainname AS address, " + "uid, users.gid FROM users LEFT JOIN domain_name ON " + "(domain_name.gid = users.gid AND is_primary) WHERE uid = %s", + uid) info = dbc.fetchone() dbc.close() if not info: diff -r 142f188f7552 -r e2785e04f92e VirtualMailManager/Alias.py --- a/VirtualMailManager/Alias.py Wed May 05 21:50:31 2010 +0000 +++ b/VirtualMailManager/Alias.py Sun May 09 06:20:52 2010 +0000 @@ -40,9 +40,8 @@ def __load_dests(self): """Loads all known destination addresses into the _dests list.""" dbc = self._dbh.cursor() - dbc.execute( - 'SELECT destination FROM alias WHERE gid=%s AND address=%s', - self._gid, self._addr.localpart) + dbc.execute('SELECT destination FROM alias WHERE gid = %s AND ' + 'address = %s', self._gid, self._addr.localpart) dests = iter(dbc.fetchall()) if dbc.rowcount > 0: self._dests.extend(EmailAddress(dest[0]) for dest in dests) @@ -81,12 +80,12 @@ """ dbc = self._dbh.cursor() if not destination: - dbc.execute("DELETE FROM alias WHERE gid=%s AND address=%s", + dbc.execute('DELETE FROM alias WHERE gid = %s AND address = %s', self._gid, self._addr.localpart) else: - dbc.execute("DELETE FROM alias WHERE gid=%s AND address=%s AND \ - destination=%s", - self._gid, self._addr.localpart, str(destination)) + dbc.execute('DELETE FROM alias WHERE gid = %s AND address = %s ' + 'AND destination = %s', self._gid, + self._addr.localpart, str(destination)) if dbc.rowcount > 0: self._dbh.commit() dbc.close() @@ -141,10 +140,9 @@ raise AErr(_(u"The alias '%s' doesn't exist.") % self._addr, NO_SUCH_ALIAS) if not destination in self._dests: - raise AErr(_(u"The address '%(d)s' isn't a destination of \ -the alias '%(a)s'.") % - {'a': self._addr, 'd': destination}, - NO_SUCH_ALIAS) + raise AErr(_(u"The address '%(addr)s' isn't a destination of " + u"the alias '%(alias)s'.") % {'addr': self._addr, + 'alias': destination}, NO_SUCH_ALIAS) self.__delete(destination) self._dests.remove(destination) diff -r 142f188f7552 -r e2785e04f92e VirtualMailManager/AliasDomain.py --- a/VirtualMailManager/AliasDomain.py Wed May 05 21:50:31 2010 +0000 +++ b/VirtualMailManager/AliasDomain.py Sun May 09 06:20:52 2010 +0000 @@ -41,9 +41,8 @@ """Loads the AliasDomain's GID from the database and checks if the domain name is marked as primary.""" dbc = self._dbh.cursor() - dbc.execute( - 'SELECT gid, is_primary FROM domain_name WHERE domainname = %s', - self._name) + dbc.execute('SELECT gid, is_primary FROM domain_name WHERE ' + 'domainname = %s', self._name) result = dbc.fetchone() dbc.close() if result: @@ -89,17 +88,15 @@ raise ADErr(_(u"The alias domain '%s' doesn't exist.") % self._name, NO_SUCH_ALIASDOMAIN) dbc = self._dbh.cursor() - dbc.execute( - 'SELECT domainname FROM domain_name WHERE gid = %s AND is_primary', - self._gid) + dbc.execute('SELECT domainname FROM domain_name WHERE gid = %s AND ' + 'is_primary', self._gid) domain = dbc.fetchone() dbc.close() if domain: return {'alias': self._name, 'domain': domain[0]} else: # an almost unlikely case, isn't it? - raise ADErr( - _(u"There is no primary domain for the alias domain '%s'.")\ - % self._name, NO_SUCH_DOMAIN) + raise ADErr(_(u'There is no primary domain for the alias domain ' + u"'%s'.") % self._name, NO_SUCH_DOMAIN) def switch(self): """Switch the destination of the AliasDomain to the new destination, @@ -115,14 +112,14 @@ raise ADErr(_(u"The alias domain '%s' doesn't exist.") % self._name, NO_SUCH_ALIASDOMAIN) if self._gid == self._domain.gid: - raise ADErr(_(u"The alias domain '%(alias)s' is already assigned\ - to the domain '%(domain)s'.") % + raise ADErr(_(u"The alias domain '%(alias)s' is already assigned " + u"to the domain '%(domain)s'.") % {'alias': self._name, 'domain': self._domain.name}, ALIASDOMAIN_EXISTS) dbc = self._dbh.cursor() - dbc.execute('UPDATE domain_name SET gid = %s WHERE gid = %s\ - AND domainname = %s AND NOT is_primary', - self._domain.gid, self._gid, self._name) + dbc.execute('UPDATE domain_name SET gid = %s WHERE gid = %s AND ' + 'domainname = %s AND NOT is_primary', self._domain.gid, + self._gid, self._name) self._dbh.commit() dbc.close() self._gid = self._domain.gid @@ -136,9 +133,8 @@ raise ADErr(_(u"The alias domain '%s' doesn't exist.") % self._name, NO_SUCH_ALIASDOMAIN) dbc = self._dbh.cursor() - dbc.execute( - 'DELETE FROM domain_name WHERE domainname = %s AND NOT is_primary', - self._name) + dbc.execute('DELETE FROM domain_name WHERE domainname = %s AND NOT ' + 'is_primary', self._name) if dbc.rowcount > 0: self._dbh.commit() self._gid = 0 diff -r 142f188f7552 -r e2785e04f92e VirtualMailManager/Config.py --- a/VirtualMailManager/Config.py Wed May 05 21:50:31 2010 +0000 +++ b/VirtualMailManager/Config.py Sun May 09 06:20:52 2010 +0000 @@ -124,8 +124,8 @@ sect_opt = section_option.lower().split('.') # TODO: cache it if len(sect_opt) != 2: # do we need a regexp to check the format? - raise BadOptionError( - _(u"Bad format: '%s' - expected: section.option") % + raise BadOptionError(_(u"Bad format: '%s' - expected: " + u"section.option") % get_unicode(section_option)) if not sect_opt[0] in self._cfg: raise NoSectionError(sect_opt[0]) diff -r 142f188f7552 -r e2785e04f92e VirtualMailManager/Domain.py --- a/VirtualMailManager/Domain.py Wed May 05 21:50:31 2010 +0000 +++ b/VirtualMailManager/Domain.py Sun May 09 06:20:52 2010 +0000 @@ -63,9 +63,9 @@ domain. """ dbc = self._dbh.cursor() - dbc.execute('SELECT dd.gid, tid, domaindir, is_primary FROM \ - domain_data dd, domain_name dn WHERE domainname = %s AND dn.gid = dd.gid', - self._name) + dbc.execute('SELECT dd.gid, tid, domaindir, is_primary FROM ' + 'domain_data dd, domain_name dn WHERE domainname = %s AND ' + 'dn.gid = dd.gid', self._name) result = dbc.fetchone() dbc.close() if result: @@ -250,12 +250,10 @@ def get_info(self): """Returns a dictionary with information about the domain.""" self._chk_state() - sql = """SELECT gid, domainname, transport, domaindir, aliasdomains, - accounts, aliases, relocated - FROM vmm_domain_info - WHERE gid = %i""" % self._gid dbc = self._dbh.cursor() - dbc.execute(sql) + dbc.execute('SELECT gid, domainname, transport, domaindir, ' + 'aliasdomains accounts, aliases, relocated FROM ' + 'vmm_domain_info WHERE gid = %s', self._gid) info = dbc.fetchone() dbc.close() keys = ('gid', 'domainname', 'transport', 'domaindir', 'aliasdomains', @@ -266,12 +264,12 @@ """Returns a list with all accounts of the domain.""" self._chk_state() dbc = self._dbh.cursor() - dbc.execute("SELECT local_part from users where gid = %s ORDER BY\ - local_part", self._gid) + dbc.execute('SELECT local_part from users where gid = %s ORDER BY ' + 'local_part', self._gid) users = dbc.fetchall() dbc.close() accounts = [] - if len(users) > 0: + if users: addr = u'@'.join _dom = self._name accounts = [addr((account[0], _dom)) for account in users] @@ -281,8 +279,8 @@ """Returns a list with all aliases e-mail addresses of the domain.""" self._chk_state() dbc = self._dbh.cursor() - dbc.execute("SELECT DISTINCT address FROM alias WHERE gid = %s\ - ORDER BY address", self._gid) + dbc.execute('SELECT DISTINCT address FROM alias WHERE gid = %s ORDER ' + 'BY address', self._gid) addresses = dbc.fetchall() dbc.close() aliases = [] @@ -296,8 +294,8 @@ """Returns a list with all addresses of relocated users.""" self._chk_state() dbc = self._dbh.cursor() - dbc.execute("SELECT address FROM relocated WHERE gid = %s\ - ORDER BY address", self._gid) + dbc.execute('SELECT address FROM relocated WHERE gid = %s ORDER BY ' + 'address', self._gid) addresses = dbc.fetchall() dbc.close() relocated = [] @@ -311,8 +309,8 @@ """Returns a list with all alias domain names of the domain.""" self._chk_state() dbc = self._dbh.cursor() - dbc.execute("SELECT domainname FROM domain_name WHERE gid = %s\ - AND NOT is_primary ORDER BY domainname", self._gid) + dbc.execute('SELECT domainname FROM domain_name WHERE gid = %s AND ' + 'NOT is_primary ORDER BY domainname', self._gid) anames = dbc.fetchall() dbc.close() aliasdomains = [] diff -r 142f188f7552 -r e2785e04f92e VirtualMailManager/EmailAddress.py |
|
From: <nev...@us...> - 2010-05-04 22:26:18
|
details: http://hg.localdomain.org/vmm/rev/01cb71c1ae33 changeset: 288:01cb71c1ae33 user: Pascal Volk date: Tue May 04 22:26:04 2010 +0000 description: man5: added misc.dovecot_version to the minimal config example. diffstat: man/de/man5/vmm.cfg.5.rst | 3 +++ man/man5/vmm.cfg.5.rst | 3 +++ 2 files changed, 6 insertions(+), 0 deletions(-) diffs (26 lines): diff -r 1e77dd639fa3 -r 01cb71c1ae33 man/de/man5/vmm.cfg.5.rst --- a/man/de/man5/vmm.cfg.5.rst Tue May 04 00:01:35 2010 +0000 +++ b/man/de/man5/vmm.cfg.5.rst Tue May 04 22:26:04 2010 +0000 @@ -63,6 +63,9 @@ user = ich pass = xxxxxxxx + [misc] + dovecot_version = 1.2.11 + SUCHREIHENFOLGE --------------- diff -r 1e77dd639fa3 -r 01cb71c1ae33 man/man5/vmm.cfg.5.rst --- a/man/man5/vmm.cfg.5.rst Tue May 04 00:01:35 2010 +0000 +++ b/man/man5/vmm.cfg.5.rst Tue May 04 22:26:04 2010 +0000 @@ -59,6 +59,9 @@ user = me pass = xxxxxxxx + [misc] + dovecot_version = 1.2.11 + SEARCH ORDER ------------- |
|
From: <nev...@us...> - 2010-05-04 00:01:50
|
details: http://hg.localdomain.org/vmm/rev/1e77dd639fa3 changeset: 287:1e77dd639fa3 user: Pascal Volk date: Tue May 04 00:01:35 2010 +0000 description: VMM/password: moved the 'scheme check' code from pwhash() to the new function verify_scheme(). VMM/Config: use verify_scheme() to check the scheme when LazyConfig.set() is called. diffstat: VirtualMailManager/Config.py | 33 ++++++++++---------- VirtualMailManager/password.py | 65 +++++++++++++++++++++++++++++------------ 2 files changed, 62 insertions(+), 36 deletions(-) diffs (156 lines): diff -r e2046d47688b -r 1e77dd639fa3 VirtualMailManager/Config.py --- a/VirtualMailManager/Config.py Mon May 03 20:38:36 2010 +0000 +++ b/VirtualMailManager/Config.py Tue May 04 00:01:35 2010 +0000 @@ -17,7 +17,8 @@ from VirtualMailManager.common import exec_ok, get_unicode, is_dir, version_hex from VirtualMailManager.constants.ERROR import CONF_ERROR -from VirtualMailManager.errors import ConfigError +from VirtualMailManager.errors import ConfigError, VMMError +from VirtualMailManager.password import verify_scheme as _verify_scheme _ = lambda msg: msg @@ -349,7 +350,7 @@ 'dovecot_version': LCO(str, None, self.hexversion, check_version_format), 'password_scheme': LCO(str, 'CRAM-MD5', self.get, - self.known_scheme), + verify_scheme), 'transport': LCO(str, 'dovecot:', self.get), }, } @@ -396,22 +397,9 @@ value to an int.""" return version_hex(self.get(section, option)) - def known_scheme(self, scheme): - """Converts `scheme` to upper case and checks if is known by - Dovecot (listed in VirtualMailManager.SCHEMES). - - Throws a `ConfigValueError` if the scheme is not listed in - VirtualMailManager.SCHEMES. - - """ - scheme = scheme.upper() - # TODO: VMM.SCHEMES - def unicode(self, section, option): """Returns the value of the `option` from `section`, converted - to Unicode. - - """ + to Unicode.""" return get_unicode(self.get(section, option)) def __chk_cfg(self): @@ -445,4 +433,17 @@ get_unicode(version_string)) return version_string + +def verify_scheme(scheme): + """Checks if the password scheme *scheme* can be accepted and returns + the verified scheme. + """ + try: + scheme, encoding = _verify_scheme(scheme) + except VMMError, err: # 'cast' it + raise ConfigValueError(err.msg) + if not encoding: + return scheme + return '%s.%s' % (scheme, encoding) + del _ diff -r e2046d47688b -r 1e77dd639fa3 VirtualMailManager/password.py --- a/VirtualMailManager/password.py Mon May 03 20:38:36 2010 +0000 +++ b/VirtualMailManager/password.py Tue May 04 00:01:35 2010 +0000 @@ -6,10 +6,12 @@ VirtualMailManager.password VirtualMailManager's password module to generate password hashes from - passwords or random passwords. There are two functions: + passwords or random passwords. This module provides following + functions: hashed_password = pwhash(password[, scheme][, user]) random_password = randompw() + scheme, encoding = verify_scheme(scheme) """ from crypt import crypt @@ -343,6 +345,47 @@ } +def verify_scheme(scheme): + """Checks if the password scheme *scheme* is known and supported by the + configured `misc.dovecot_version`. + + The *scheme* maybe a password scheme's name (e.g.: 'PLAIN') or a scheme + name with a encoding suffix (e.g. 'PLAIN.BASE64'). If the scheme is + known and supported by the used Dovecot version, + a tuple ``(scheme, encoding)`` will be returned. + The `encoding` in the tuple may be `None`. + + Raises a `VMMError` if the password scheme: + * is unknown + * depends on a newer Dovecot version + * has a unknown encoding suffix + """ + assert isinstance(scheme, basestring), 'Not a str/unicode: %r' % scheme + scheme_encoding = scheme.upper().split('.') + scheme = scheme_encoding[0] + if not scheme in _scheme_info: + raise VMMError(_(u"Unsupported password scheme: '%s'") % scheme, + VMM_ERROR) + if cfg_dget('misc.dovecot_version') < _scheme_info[scheme][1]: + raise VMMError(_(u"The password scheme '%(scheme)s' requires Dovecot \ +>= v%(version)s") % + {'scheme': scheme, + 'version': version_str(_scheme_info[scheme][1])}, + VMM_ERROR) + if len(scheme_encoding) > 1: + if cfg_dget('misc.dovecot_version') < 0x10100a01: + raise VMMError(_(u'Encoding suffixes for password schemes require \ +Dovecot >= v1.1.alpha1'), + VMM_ERROR) + if scheme_encoding[1] not in ('B64', 'BASE64', 'HEX'): + raise VMMError(_(u"Unsupported password encoding: '%s'") % + scheme_encoding[1], VMM_ERROR) + encoding = scheme_encoding[1] + else: + encoding = None + return scheme, encoding + + def pwhash(password, scheme=None, user=None): """Generates a password hash from the plain text *password* string. @@ -359,25 +402,7 @@ raise ValueError("Couldn't accept empty password.") if scheme is None: scheme = cfg_dget('misc.password_scheme') - scheme_encoding = scheme.split('.') - scheme = scheme_encoding[0].upper() - if not scheme in _scheme_info: - raise VMMError(_(u"Unsupported password scheme: '%s'") % scheme, - VMM_ERROR) - if cfg_dget('misc.dovecot_version') < _scheme_info[scheme][1]: - raise VMMError(_(u"The scheme '%s' requires Dovecot >= v%s") % - (scheme, version_str(_scheme_info[scheme][1])), - VMM_ERROR) - if len(scheme_encoding) > 1: - if cfg_dget('misc.dovecot_version') < 0x10100a01: - raise VMMError(_(u'Encoding suffixes for password schemes require \ -Dovecot >= v1.1.alpha1'), - VMM_ERROR) - if scheme_encoding[1].upper() not in ('B64', 'BASE64', 'HEX'): - raise ValueError('Unsupported encoding: %r' % scheme_encoding[1]) - encoding = scheme_encoding[1].upper() - else: - encoding = None + scheme, encoding = verify_scheme(scheme) if scheme == 'DIGEST-MD5': assert isinstance(user, EmailAddress) return _md5_hash(password, scheme, encoding, user) |
|
From: <nev...@us...> - 2010-05-03 20:38:46
|
details: http://hg.localdomain.org/vmm/rev/e2046d47688b changeset: 286:e2046d47688b user: Pascal Volk date: Mon May 03 20:38:36 2010 +0000 description: VMM/Config: removed the default value of misc.dovecot_version. There are too many different versions installed on different systems. So, it doesn't make much sense to have a default value. diffstat: VirtualMailManager/Config.py | 2 +- man/de/man5/vmm.cfg.5.rst | 2 +- man/man5/vmm.cfg.5.rst | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diffs (36 lines): diff -r d30a94f5aef5 -r e2046d47688b VirtualMailManager/Config.py --- a/VirtualMailManager/Config.py Mon May 03 20:00:06 2010 +0000 +++ b/VirtualMailManager/Config.py Mon May 03 20:38:36 2010 +0000 @@ -346,7 +346,7 @@ 'crypt_blowfish_rounds': LCO(int, 0, self.getint), 'crypt_sha256_rounds': LCO(int, 0, self.getint), 'crypt_sha512_rounds': LCO(int, 0, self.getint), - 'dovecot_version': LCO(str, '1.2.11', self.hexversion, + 'dovecot_version': LCO(str, None, self.hexversion, check_version_format), 'password_scheme': LCO(str, 'CRAM-MD5', self.get, self.known_scheme), diff -r d30a94f5aef5 -r e2046d47688b man/de/man5/vmm.cfg.5.rst --- a/man/de/man5/vmm.cfg.5.rst Mon May 03 20:00:06 2010 +0000 +++ b/man/de/man5/vmm.cfg.5.rst Mon May 03 20:38:36 2010 +0000 @@ -412,7 +412,7 @@ .. _misc.dovecot_version: -``dovecot_version (Vorgabe: 1.2.11)`` : *String* +``dovecot_version (Vorgabe: Nichts)`` : *String* Die eingesetzten Dovecot-Version. (siehe: **dovecot --version**). Wenn das Kommando **dovecot --version** zum Beispiel diff -r d30a94f5aef5 -r e2046d47688b man/man5/vmm.cfg.5.rst --- a/man/man5/vmm.cfg.5.rst Mon May 03 20:00:06 2010 +0000 +++ b/man/man5/vmm.cfg.5.rst Mon May 03 20:38:36 2010 +0000 @@ -392,7 +392,7 @@ .. _misc.dovecot_version: -``dovecot_version (default: 1.2.11)`` : *String* +``dovecot_version (default: None)`` : *String* The version number of the currently used Dovecot version. (see: **dovecot --version**). |
|
From: <nev...@us...> - 2010-05-03 20:00:21
|
details: http://hg.localdomain.org/vmm/rev/d30a94f5aef5 changeset: 285:d30a94f5aef5 user: Pascal Volk date: Mon May 03 20:00:06 2010 +0000 description: VMM/Handler: import the errors before raising them. Rephrased the 'permission error' message. diffstat: VirtualMailManager/Handler.py | 13 +++++++------ 1 files changed, 7 insertions(+), 6 deletions(-) diffs (30 lines): diff -r ec1966828246 -r d30a94f5aef5 VirtualMailManager/Handler.py --- a/VirtualMailManager/Handler.py Mon May 03 08:25:26 2010 +0000 +++ b/VirtualMailManager/Handler.py Mon May 03 20:00:06 2010 +0000 @@ -28,7 +28,8 @@ from VirtualMailManager.Config import Config as Cfg from VirtualMailManager.Domain import Domain, ace2idna, get_gid from VirtualMailManager.EmailAddress import EmailAddress -from VirtualMailManager.errors import VMMError, DomainError +from VirtualMailManager.errors import \ + DomainError, NotRootError, PermissionError, VMMError from VirtualMailManager.Relocated import Relocated from VirtualMailManager.Transport import Transport @@ -94,11 +95,11 @@ fstat = os.stat(self._cfgFileName) fmode = int(oct(fstat.st_mode & 0777)) if fmode % 100 and fstat.st_uid != fstat.st_gid or \ - fmode % 10 and fstat.st_uid == fstat.st_gid: - raise PermissionError(_( - u'fix permissions (%(perms)s) for “%(file)s”\n\ -`chmod 0600 %(file)s` would be great.') % {'file': - self._cfgFileName, 'perms': fmode}, ERR.CONF_WRONGPERM) + fmode % 10 and fstat.st_uid == fstat.st_gid: + raise PermissionError(_(u"wrong permissions for '%(file)s': \ +%(perms)s\n`chmod 0600 %(file)s` would be great.") % + {'file': self._cfgFileName, 'perms': fmode}, + ERR.CONF_WRONGPERM) else: return True |
|
From: <nev...@us...> - 2010-05-03 08:25:40
|
details: http://hg.localdomain.org/vmm/rev/ec1966828246 changeset: 284:ec1966828246 user: Pascal Volk date: Mon May 03 08:25:26 2010 +0000 description: VMM/password: Added support Blowfish/SHA-256/SHA-512 crypt(). Also updated Config and man section 5. diffstat: TODO | 10 ++++- VirtualMailManager/Config.py | 3 + VirtualMailManager/password.py | 69 +++++++++++++++++++++++++++++++++++++---- man/de/man5/vmm.cfg.5.rst | 45 ++++++++++++++++++++++++++- man/man5/vmm.cfg.5.rst | 41 ++++++++++++++++++++++++- man/substitute_links_5.rst | 2 + 6 files changed, 158 insertions(+), 12 deletions(-) diffs (282 lines): diff -r ea6d052de24a -r ec1966828246 TODO --- a/TODO Fri Apr 30 08:02:03 2010 +0000 +++ b/TODO Mon May 03 08:25:26 2010 +0000 @@ -4,6 +4,10 @@ ds - domainservices: smtp pop imap sieve??? + +subcommand for displaying support crypt algorithms. + + - Aliases - avoid looping aliases @@ -15,7 +19,9 @@ + alias domains Database: - public.users.passwd: increase to "character varying(150)" - why? `doveadm pw -s SSHA512.hex -p 1` + public.users.passwd: increase to "character varying(250)" + why? len(VirtualMailManager.password.pwhash('1', 'crypt.hex')) -> 249 + if VirtualMailManager.password.CRYPT_SHA512 is True and + misc.crypt_sha512_rounds > 0 public.users.digestmd5: add "character varying(48)" Outlook will love it. (`doveadm pw -s DIGEST-MD5.hex -p 1 -u 0`) diff -r ea6d052de24a -r ec1966828246 VirtualMailManager/Config.py --- a/VirtualMailManager/Config.py Fri Apr 30 08:02:03 2010 +0000 +++ b/VirtualMailManager/Config.py Mon May 03 08:25:26 2010 +0000 @@ -343,6 +343,9 @@ }, 'misc': { 'base_directory': LCO(str, '/srv/mail', self.get, is_dir), + 'crypt_blowfish_rounds': LCO(int, 0, self.getint), + 'crypt_sha256_rounds': LCO(int, 0, self.getint), + 'crypt_sha512_rounds': LCO(int, 0, self.getint), 'dovecot_version': LCO(str, '1.2.11', self.hexversion, check_version_format), 'password_scheme': LCO(str, 'CRAM-MD5', self.get, diff -r ea6d052de24a -r ec1966828246 VirtualMailManager/password.py --- a/VirtualMailManager/password.py Fri Apr 30 08:02:03 2010 +0000 +++ b/VirtualMailManager/password.py Mon May 03 08:25:26 2010 +0000 @@ -13,7 +13,7 @@ """ from crypt import crypt -from random import choice, shuffle +from random import SystemRandom from subprocess import Popen, PIPE try: @@ -35,7 +35,28 @@ _ = lambda msg: msg cfg_dget = lambda option: None -_get_salt = lambda s_len: ''.join(choice(SALTCHARS) for x in xrange(s_len)) +_sys_rand = SystemRandom() +_get_salt = lambda salt_len: ''.join(_sys_rand.sample(SALTCHARS, salt_len)) + + +def _test_crypt_algorithms(): + """Check for Blowfish/SHA-256/SHA-512 support in crypt.crypt().""" + blowfish_ = sha256_ = sha512_ = False + _blowfish = '$2a$04$0123456789abcdefABCDE.N.drYX5yIAL1LkTaaZotW3yI0hQhZru' + _sha256 = '$5$rounds=1000$0123456789abcdef$K/DksR0DT01hGc8g/kt9McEgrbFMKi\ +9qrb1jehe7hn4' + _sha512 = '$6$rounds=1000$0123456789abcdef$ZIAd5WqfyLkpvsVCVUU1GrvqaZTqvh\ +JoouxdSqJO71l9Ld3tVrfOatEjarhghvEYADkq//LpDnTeO90tcbtHR1' + + if crypt('08/15!test~4711', '$2a$04$0123456789abcdefABCDEF$') == _blowfish: + blowfish_ = True + if crypt('08/15!test~4711', '$5$rounds=1000$0123456789abcdef$') == _sha256: + sha256_ = True + if crypt('08/15!test~4711', '$6$rounds=1000$0123456789abcdef$') == _sha512: + sha512_ = True + return blowfish_, sha256_, sha512_ + +CRYPT_BLOWFISH, CRYPT_SHA256, CRYPT_SHA512 = _test_crypt_algorithms() def _dovecotpw(password, scheme, encoding): @@ -110,10 +131,44 @@ return get_unicode('{%s}%s' % (scheme, password)) +def _get_crypt_blowfish_salt(): + """Generates a salt for Blowfish crypt.""" + rounds = cfg_dget('misc.crypt_blowfish_rounds') + if rounds < 4: + rounds = 4 + elif rounds > 31: + rounds = 31 + return '$2a$%02d$%s$' % (rounds, _get_salt(22)) + + +def _get_crypt_shaxxx_salt(crypt_id): + """Generates a salt for crypt using the SHA-256 or SHA-512 encryption + method. + *crypt_id* must be either `5` (SHA-256) or `6` (SHA1-512). + """ + assert crypt_id in (5, 6), 'invalid crypt id: %r' % crypt_id + if crypt_id is 6: + rounds = cfg_dget('misc.crypt_sha512_rounds') + else: + rounds = cfg_dget('misc.crypt_sha256_rounds') + if rounds < 1000: + rounds = 1000 + elif rounds > 999999999: + rounds = 999999999 + return '$%d$rounds=%d$%s$' % (crypt_id, rounds, _get_salt(16)) + + def _crypt_hash(password, scheme, encoding): """Generates (encoded) CRYPT/MD5/MD5-CRYPT hashes.""" if scheme == 'CRYPT': - salt = _get_salt(2) + if CRYPT_BLOWFISH and cfg_dget('misc.crypt_blowfish_rounds'): + salt = _get_crypt_blowfish_salt() + elif CRYPT_SHA512 and cfg_dget('misc.crypt_sha512_rounds'): + salt = _get_crypt_shaxxx_salt(6) + elif CRYPT_SHA256 and cfg_dget('misc.crypt_sha256_rounds'): + salt = _get_crypt_shaxxx_salt(5) + else: + salt = _get_salt(2) else: salt = '$1$%s$' % _get_salt(8) encrypted = crypt(password, salt) @@ -121,7 +176,7 @@ if encoding == 'HEX': encrypted = encrypted.encode('hex') else: - encrypted = encrypted.encode('base64').rstrip() + encrypted = encrypted.encode('base64').replace('\n', '') return _format_digest(encrypted, scheme, encoding) @@ -335,11 +390,9 @@ The length of the password can be configured in the ``vmm.cfg`` (account.password_length). """ - pw_chars = list(PASSWDCHARS) - shuffle(pw_chars) pw_len = cfg_dget('account.password_length') if pw_len < 8: pw_len = 8 - return ''.join(choice(pw_chars) for x in xrange(pw_len)) + return ''.join(_sys_rand.sample(PASSWDCHARS, pw_len)) -del _, cfg_dget +del _, cfg_dget, _test_crypt_algorithms diff -r ea6d052de24a -r ec1966828246 man/de/man5/vmm.cfg.5.rst --- a/man/de/man5/vmm.cfg.5.rst Fri Apr 30 08:02:03 2010 +0000 +++ b/man/de/man5/vmm.cfg.5.rst Mon May 03 08:25:26 2010 +0000 @@ -355,6 +355,48 @@ Alle Domain-Verzeichnisse werden innerhalb dieses Basis-Verzeichnisses angelegt. +.. _misc.crypt_blowfish_rounds: + +``crypt_blowfish_rounds (Vorgabe: 0)`` : *Int* + Anzahl der Verschlüsselungsdurchgänge für Blowfish-Crypt. + + Diese Einstellung beeinflusst das Verhalten des 'CRYPT'-Passwortschematas. + Standardmäßig verwendet crypt den DES-Algorithmus für die + Kennwortverschlüsselung. |vmm(1)|_ prüft, ob Blowfish-Crypt verfügbar + ist. Wenn der Blowfishalgorithmus unterstützt wird und der Wert dieser + Einstellung größer als 0 ist, wird Blowfish anstelle von DES als + Algorithmus verwendet. + + Der Wert muss im Bereich von **4** - **31** liegen. + +.. _misc.crypt_sha256_rounds: + +``crypt_sha256_rounds (Vorgabe: 0)`` : *Int* + Anzahl der Verschlüsselungdurchgänge für crypt unter Verwendung der SHA-256 + Verschlüsselungsmethode. + + Diese Einstellung beeinflusst das Verhalten des 'CRYPT'-Passwortschematas. + Standardmäßig verwendet crypt den DES-Algorithmus für die + Kennwortverschlüsselung. |vmm(1)|_ prüft, ob crypt die SHA-256 und/oder + SHA-512 Algorithmen unterstützt. Wenn die Algorithmen unterstützt werden + und der Wert dieser Einstellung größer als 0 ist, wird SHA-256 anstelle + von DES als Algorithmus verwendet. + + Wenn der Wert von |misc.crypt_sha512_rounds|_ größer als 0 ist, wird der + SHA-512 Algorithmus anstelle von SHA-256 verwendet. + + Der Wert muss im Bereich von **1000** - **999999999** liegen. + +.. _misc.crypt_sha512_rounds: + +``crypt_sha512_rounds (Vorgabe: 0)`` : *Int* + Anzahl der Verschlüsselungsdurchgänge für crypt unter Verwendung + der SHA-512 Verschlüsselungsmethode. + + Siehe |misc.crypt_sha256_rounds|_ für Details. + + Der Wert muss im Bereich von **1000** - **999999999** liegen. + .. _misc.password_scheme: ``password_scheme (Vorgabe: CRAM-MD5)`` : *String* @@ -381,7 +423,8 @@ [misc] base_directory = /srv/mail - password_scheme = PLAIN + crypt_sha512_rounds = 10000 + password_scheme = CRYPT transport = dovecot: dovecot_version = 2.0.beta4 diff -r ea6d052de24a -r ec1966828246 man/man5/vmm.cfg.5.rst --- a/man/man5/vmm.cfg.5.rst Fri Apr 30 08:02:03 2010 +0000 +++ b/man/man5/vmm.cfg.5.rst Mon May 03 08:25:26 2010 +0000 @@ -339,6 +339,44 @@ ``base_directory (default: /srv/mail)`` : *String* All domain directories will be created inside this directory. +.. _misc.crypt_blowfish_rounds: + +``crypt_blowfish_rounds (default: 0)`` : *Int* + Number of encryption rounds for Blowfish crypt. + + This setting affects the behavior of the 'CRYPT' password scheme. By + default crypt will use the DES algorithm for password encryption. + |vmm(1)|_ checks if Blowfish crypt is available. When the Blowfish + algorithm is supported and the value of this setting is greater than 0 + Blowfish will be used for crypt, instead of DES. + + The value must be in range **4** - **31**. + +.. _misc.crypt_sha256_rounds: + +``crypt_sha256_rounds (default: 0)`` : *Int* + Number of encryption rounds for crypt using the SHA-256 encryption method. + + This setting affects the behavior of the 'CRYPT' password scheme. By + default crypt will use the DES algorithm for password encryption. + |vmm(1)|_ checks if crypt supports the SHA-256 and/or SHA-512 algorithms. + When the algorithms are supported and the value of this setting is greater + than 0, SHA-256 will be used instead of DES. + + When the value of |misc.crypt_sha512_rounds|_ is greater than 0, the + SHA-512 algorithm will be used instead of SHA-256. + + The value must be in range **1000** - **999999999**. + +.. _misc.crypt_sha512_rounds: + +``crypt_sha512_rounds (default: 0)`` : *Int* + Number of encryption rounds for crypt using the SHA-512 encryption method. + + See |misc.crypt_sha256_rounds|_ for details. + + The value must be in range **1000** - **999999999**. + .. _misc.password_scheme: ``password_scheme (default: CRAM-MD5)`` : *String* @@ -365,7 +403,8 @@ [misc] base_directory = /srv/mail - password_scheme = PLAIN + crypt_sha512_rounds = 10000 + password_scheme = CRYPT transport = dovecot: dovecot_version = 2.0.beta4 diff -r ea6d052de24a -r ec1966828246 man/substitute_links_5.rst --- a/man/substitute_links_5.rst Fri Apr 30 08:02:03 2010 +0000 +++ b/man/substitute_links_5.rst Mon May 03 08:25:26 2010 +0000 @@ -2,6 +2,8 @@ .. |account.password_length| replace:: **password_length** .. |mailbox.format| replace:: **format** +.. |misc.crypt_sha256_rounds| replace:: **crypt_sha256_rounds** +.. |misc.crypt_sha512_rounds| replace:: **crypt_sha512_rounds** .. |misc.password_scheme| replace:: **misc.password_scheme** .. |vmm configure| replace:: **vmm configure** |