diff options
| author | Eli Collins <elic@assurancetechnologies.com> | 2011-03-17 17:44:42 -0400 |
|---|---|---|
| committer | Eli Collins <elic@assurancetechnologies.com> | 2011-03-17 17:44:42 -0400 |
| commit | 72b370d8506a8a494e6841ffc4673ed63fdcfef4 (patch) | |
| tree | 157cee85c815fd25c79342268cb8a7c9904608d4 | |
| parent | 1f9b8fa19aee1aa3be5a826b6d15adbcb3d14539 (diff) | |
| download | passlib-72b370d8506a8a494e6841ffc4673ed63fdcfef4.tar.gz | |
to simplify things, merged StaticHash's minimal amount of code into ExtHash, and removed StaticHash entirely
| -rw-r--r-- | passlib/tests/test_utils_drivers.py | 6 | ||||
| -rw-r--r-- | passlib/tests/utils.py | 6 | ||||
| -rw-r--r-- | passlib/utils/drivers.py | 119 |
3 files changed, 41 insertions, 90 deletions
diff --git a/passlib/tests/test_utils_drivers.py b/passlib/tests/test_utils_drivers.py index 0a86604..eccb9fc 100644 --- a/passlib/tests/test_utils_drivers.py +++ b/passlib/tests/test_utils_drivers.py @@ -10,7 +10,7 @@ from logging import getLogger #site #pkg from passlib.utils import rng, getrandstr -from passlib.utils.drivers import ExtHash, StaticHash +from passlib.utils.drivers import ExtHash from passlib.tests.utils import HandlerCase #module log = getLogger(__name__) @@ -20,9 +20,10 @@ log = getLogger(__name__) # to test the unittests themselves, as well as other # parts of passlib. they shouldn't be used as actual password schemes. #========================================================= -class UnsaltedHash(StaticHash): +class UnsaltedHash(ExtHash): "test algorithm which lacks a salt" name = "unsalted_test_hash" + setting_kwds = () @classmethod def identify(cls, hash): @@ -60,6 +61,7 @@ class SaltedHash(ExtHash): return cls(salt=hash[5:7], checksum=hash[7:], strict=True) _stub_checksum = '0' * 40 + def to_string(self): return "@salt%s%s" % (self.salt, self.checksum or self._stub_checksum) diff --git a/passlib/tests/utils.py b/passlib/tests/utils.py index f92e3d1..e44db7a 100644 --- a/passlib/tests/utils.py +++ b/passlib/tests/utils.py @@ -18,7 +18,7 @@ except ImportError: #wasn't added until py26 from nose.plugins.skip import SkipTest #pkg from passlib.utils import classproperty -from passlib.utils.drivers import BaseHash, BackendMixin +from passlib.utils.drivers import BaseHash, BackendExtHash #local __all__ = [ #util funcs @@ -330,7 +330,7 @@ class HandlerCase(TestCase): h.validate_class() #should raise AssertionError if something's wrong. def test_05_backend_handler(self): - "check configuration of BackendMixin-derived classes" + "check configuration of multi-backend classes" h = self.handler if not hasattr(h, "get_backend"): raise SkipTest @@ -604,7 +604,7 @@ class HandlerCase(TestCase): #========================================================= def enable_backend_case(handler, name): "helper to check if a separate test is needed for the specified backend" - assert issubclass(handler, BackendMixin), "handler must derived from BackendMixin" + assert issubclass(handler, BackendExtHash), "handler must derived from BackendExtHash" assert name in handler.backends, "unknown backend: %r" % (name,) return enable_option("all-backends") and handler.get_backend() != name and handler.has_backend(name) diff --git a/passlib/utils/drivers.py b/passlib/utils/drivers.py index dedb6a4..2d210ee 100644 --- a/passlib/utils/drivers.py +++ b/passlib/utils/drivers.py @@ -21,11 +21,7 @@ __all__ = [ #framework for implementing handlers 'BaseHash', 'ExtHash', - 'StaticHash', - - 'BackendMixin', - 'BackendExtHash', - 'BackendStaticHash', + 'BackendExtHash', ] #========================================================= @@ -137,7 +133,8 @@ class BaseHash(object): # ExtHash # rounds+salt+xtra phpass, sha256_crypt, sha512_crypt # rounds+salt bcrypt, ext_des_crypt, sha1_crypt, sun_md5_crypt -# salt only apr_md5_crypt, des_crypt, md5_crypt +# salt apr_md5_crypt, des_crypt, md5_crypt +# nothing mysql_323, mysql_41, nthash, postgres_md5 #========================================================= class ExtHash(BaseHash): """helper class for implementing hash schemes @@ -393,6 +390,10 @@ class ExtHash(BaseHash): :returns: normalized rounds value """ + #XXX: for speed, could optimize this by replacing method at class level + # when cls._has_rounds check is first called. + # could make same optimization for norm_salt() + if not cls._has_rounds: #NOTE: special casing schemes which don't have rounds if rounds is not None: @@ -463,15 +464,23 @@ class ExtHash(BaseHash): ## return self.to_string() #========================================================= - #password hash api - primary interface (default implementation) + #'crypt-style' interface (default implementation) #========================================================= @classmethod def genconfig(cls, **settings): - return cls(**settings).to_string() + if cls._has_settings: + return cls(**settings).to_string() + elif settings: + raise TypeError, "%s.genconfig() takes no arguments" % (cls.name,) + else: + return None @classmethod def genhash(cls, secret, config): - self = cls.from_string(config) + if cls._has_settings or config is not None: + self = cls.from_string(config) + else: + self = cls() self.checksum = self.calc_checksum(secret) return self.to_string() @@ -480,7 +489,7 @@ class ExtHash(BaseHash): raise NotImplementedError, "%s must implement calc_checksum()" % (cls,) #========================================================= - #password hash api - secondary interface (default implementation) + #'application' interface (default implementation) #========================================================= @classmethod def encrypt(cls, secret, **settings): @@ -501,61 +510,11 @@ class ExtHash(BaseHash): #========================================================= #========================================================= -#static - mysql_323, mysql_41, nthash, postgres_md5 -#========================================================= -class StaticHash(ExtHash): - """helper class optimized for implementing hash schemes which have NO settings whatsoever. - - the main thing this changes from ExtHash: - - * :attr:`setting_kwds` must be an empty tuple (set by class) - * :meth:`genconfig` takes no kwds, and always returns ``None``. - * :meth:`genhash` accepts ``config=None``. - - otherwise, this requires the same methods be implemented - as does ExtHash. - """ - #========================================================= - #class attr - #========================================================= - setting_kwds = () - - #========================================================= - #init - #========================================================= - @classmethod - def validate_class(cls): - "helper to validate that class has been configured properly" - if cls.setting_kwds: - raise AssertionError, "StaticHash subclasses must not have any settings, perhaps you want ExtHash?" - super(StaticHash, cls).validate_class() - - #========================================================= - #primary interface - #========================================================= - @classmethod - def genconfig(cls): - return None - - @classmethod - def genhash(cls, secret, config): - if config is None: - self = cls() - else: - #just to verify input is correctly formatted - self = cls.from_string(config) - self.checksum = self.calc_checksum(secret) - return self.to_string() - - #========================================================= - #eoc - #========================================================= - -#========================================================= #helpful mixin which provides lazy-loading of different backends #to be used for calc_checksum #========================================================= -class BackendMixin(object): +class BackendExtHash(ExtHash): + "subclass of ExtHash which provides selecting from multiple backends for checksum calculation" #NOTE: subclass must provide: # * attr 'backends' containing list of known backends (top priority backend first) @@ -577,25 +536,20 @@ class BackendMixin(object): @classmethod def set_backend(cls, name=None): "change class to use specified backend" - if not name or name == "default": - if not name: - name = cls._backend - if name: - return name + if not name: + name = cls._backend + if name: + return name for name in cls.backends: if cls.has_backend(name): - cls.calc_checksum = getattr(cls, "_calc_checksum_" + name) - cls._backend = name - return name - raise EnvironmentError, "no %s backends available" % (cls.name,) - else: - ##if name not in cls.backends: - ## raise ValueError, "unknown %s backend: %r" % (cls.name, name) - if not cls.has_backend(name): - raise ValueError, "%s backend not available: %r" % (cls.name, name) - cls.calc_checksum = getattr(cls, "_calc_checksum_" + name) - cls._backend = name - return name + break + else: + raise EnvironmentError, "no %s backends available" % (cls.name,) + elif not cls.has_backend(name): + raise ValueError, "%s backend not available: %r" % (cls.name, name) + cls.calc_checksum = getattr(cls, "_calc_checksum_" + name) + cls._backend = name + return name def calc_checksum(self, secret): "stub for calc_checksum(), default backend will be selected first time stub is called" @@ -603,14 +557,9 @@ class BackendMixin(object): assert not self._backend, "set_backend() failed to replace lazy loader" self.set_backend() assert self._backend, "set_backend() failed to load a default backend" + #set_backend() should have replaced this method, so call it again. return self.calc_checksum(secret) -class BackendExtHash(BackendMixin, ExtHash): - pass - -class BackendStaticHash(BackendMixin, StaticHash): - pass - #========================================================= # eof #========================================================= |
