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.
--- 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 _
--- 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)