VMM/password: moved the 'scheme check' code from pwhash() to the v0.6.x
authorPascal Volk <neverseen@users.sourceforge.net>
Tue, 04 May 2010 00:01:35 +0000
branchv0.6.x
changeset 287 1e77dd639fa3
parent 286 e2046d47688b
child 288 01cb71c1ae33
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.
VirtualMailManager/Config.py
VirtualMailManager/password.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 _
--- 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)