diff options
| author | Eli Collins <elic@assurancetechnologies.com> | 2012-04-11 19:31:37 -0400 |
|---|---|---|
| committer | Eli Collins <elic@assurancetechnologies.com> | 2012-04-11 19:31:37 -0400 |
| commit | 046cfe8a3489ccf87e06a5a9982b283eb71945b0 (patch) | |
| tree | 1d9fd914de2826d339b3893ff5b8457efa2ac714 /passlib | |
| parent | 2183916ae35ca69fcf3c7d1550d096488e51a9a8 (diff) | |
| download | passlib-046cfe8a3489ccf87e06a5a9982b283eb71945b0.tar.gz | |
ran full UTs, found and fixed a few bugs introduced in last few commits.
Diffstat (limited to 'passlib')
| -rw-r--r-- | passlib/context.py | 3 | ||||
| -rw-r--r-- | passlib/exc.py | 2 | ||||
| -rw-r--r-- | passlib/ext/django/models.py | 2 | ||||
| -rw-r--r-- | passlib/ext/django/utils.py | 2 | ||||
| -rw-r--r-- | passlib/handlers/bcrypt.py | 17 | ||||
| -rw-r--r-- | passlib/handlers/cisco.py | 8 | ||||
| -rw-r--r-- | passlib/handlers/des_crypt.py | 4 | ||||
| -rw-r--r-- | passlib/handlers/django.py | 2 | ||||
| -rw-r--r-- | passlib/tests/test_ext_django.py | 6 | ||||
| -rw-r--r-- | passlib/tests/test_handlers.py | 4 | ||||
| -rw-r--r-- | passlib/tests/test_utils.py | 5 | ||||
| -rw-r--r-- | passlib/tests/test_utils_handlers.py | 17 | ||||
| -rw-r--r-- | passlib/tests/test_win32.py | 2 | ||||
| -rw-r--r-- | passlib/tests/utils.py | 6 | ||||
| -rw-r--r-- | passlib/utils/__init__.py | 2 |
15 files changed, 48 insertions, 34 deletions
diff --git a/passlib/context.py b/passlib/context.py index e5bc2c7..2eb1a4f 100644 --- a/passlib/context.py +++ b/passlib/context.py @@ -1576,7 +1576,8 @@ class LazyCryptContext(CryptContext): kwds = self._lazy_kwds if 'create_policy' in kwds: create_policy = kwds.pop("create_policy") - kwds = dict(policy=create_policy(**kwds)) + policy = create_policy(**kwds) + kwds = dict(policy=CryptPolicy.from_source(policy)) super(LazyCryptContext, self).__init__(**kwds) del self._lazy_kwds self.__class__ = CryptContext diff --git a/passlib/exc.py b/passlib/exc.py index 7c2bd30..1e78123 100644 --- a/passlib/exc.py +++ b/passlib/exc.py @@ -106,7 +106,7 @@ def ExpectedStringError(value, param): "error message when param was supposed to be unicode or bytes" # NOTE: value is never displayed, since it may sometimes be a password. cls = value.__class__ - if cls.__module__ and cls.__module__ != "__builtin__": + if cls.__module__ and cls.__module__ not in ["__builtin__", "builtins"]: name = "%s.%s" % (cls.__module__, cls.__name__) elif value is None: name = 'None' diff --git a/passlib/ext/django/models.py b/passlib/ext/django/models.py index edc334a..d76cc9c 100644 --- a/passlib/ext/django/models.py +++ b/passlib/ext/django/models.py @@ -28,7 +28,7 @@ def patch(): catfunc = getattr(settings, "PASSLIB_GET_CATEGORY", get_category) #parse & validate input value - if ctx == "disabled": + if ctx == "disabled" or ctx is None: # remove any patching that was already set, just in case. set_django_password_context(None) return diff --git a/passlib/ext/django/utils.py b/passlib/ext/django/utils.py index 32aa96c..bb95a71 100644 --- a/passlib/ext/django/utils.py +++ b/passlib/ext/django/utils.py @@ -47,7 +47,7 @@ def _import_django(): import django.contrib.auth.models as _dam from django import VERSION _has_django0 = VERSION < (1,0) - _has_django14 = VERISON >= (1,4) + _has_django14 = VERSION >= (1,4) if _has_django14: # django 1.4 had a large rewrite that adds new stronger schemes, # but changes how things work. our monkeypatching may not jive. diff --git a/passlib/handlers/bcrypt.py b/passlib/handlers/bcrypt.py index 6d03c98..f07a194 100644 --- a/passlib/handlers/bcrypt.py +++ b/passlib/handlers/bcrypt.py @@ -27,7 +27,7 @@ except ImportError: #pragma: no cover bcryptor_engine = None #libs from passlib.exc import PasslibHashWarning, PasslibSecurityWarning -from passlib.utils import bcrypt64, safe_crypt, \ +from passlib.utils import bcrypt64, safe_crypt, repeat_string, \ classproperty, rng, getrandstr, test_crypt from passlib.utils.compat import bytes, u, uascii_to_str, unicode, str_to_uascii import passlib.utils.handlers as uh @@ -250,10 +250,12 @@ class bcrypt(uh.HasManyIdents, uh.HasRounds, uh.HasSalt, uh.HasManyBackends, uh. assert hash.startswith(config) and len(hash) == len(config)+31 return hash[-31:] else: - #NOTE: not checking backends since this is lowest priority, - # so they probably aren't available either - raise ValueError("encoded password can't be handled by os_crypt, " - "recommend installing py-bcrypt or bcryptor.") + #NOTE: not checking other backends since this is lowest priority one, + # so they probably aren't available either. + raise uh.exc.MissingBackendError( + "encoded password can't be handled by os_crypt, " + "recommend installing py-bcrypt.", + ) def _calc_checksum_pybcrypt(self, secret): #py-bcrypt behavior: @@ -278,9 +280,8 @@ class bcrypt(uh.HasManyIdents, uh.HasRounds, uh.HasSalt, uh.HasManyBackends, uh. # bcryptor doesn't support $2$ hashes; but we can fake $2$ behavior # using the $2a$ algorithm, by repeating the password until # it's at least 72 chars in length. - ss = len(secret) - if 0 < ss < 72: - secret = secret * (1 + 72//ss) + if secret: + secret = repeat_string(secret, 72) config = self._get_config(IDENT_2A) else: config = self._get_config() diff --git a/passlib/handlers/cisco.py b/passlib/handlers/cisco.py index b4519a9..184134e 100644 --- a/passlib/handlers/cisco.py +++ b/passlib/handlers/cisco.py @@ -120,6 +120,14 @@ class cisco_type7(uh.GenericHandler): return None @classmethod + def genhash(cls, secret, config): + # special case to handle ``config=None`` in same style as StaticHandler + if config is None: + return cls.encrypt(secret) + else: + return super(cisco_type7, cls).genhash(secret, config) + + @classmethod def from_string(cls, hash): hash = to_unicode(hash, "ascii", "hash") if len(hash) < 2: diff --git a/passlib/handlers/des_crypt.py b/passlib/handlers/des_crypt.py index 9517899..56102c0 100644 --- a/passlib/handlers/des_crypt.py +++ b/passlib/handlers/des_crypt.py @@ -216,8 +216,8 @@ class des_crypt(uh.HasManyBackends, uh.HasSalt, uh.GenericHandler): # no official policy since des-crypt predates unicode hash = safe_crypt(secret, self.salt) if hash: - assert hash.startswith(self.salt) and len(hash) == 4 - return hash[-2:] + assert hash.startswith(self.salt) and len(hash) == 13 + return hash[2:] else: return self._calc_checksum_builtin(secret) diff --git a/passlib/handlers/django.py b/passlib/handlers/django.py index d0c7e11..c79a00d 100644 --- a/passlib/handlers/django.py +++ b/passlib/handlers/django.py @@ -157,7 +157,7 @@ class django_des_crypt(DjangoSaltedHash): chk = self.checksum if salt and chk: if salt[:2] != chk[:2]: - raise uh.exc.MalformedHashError(cls, + raise uh.exc.MalformedHashError(self, "first two digits of salt and checksum must match") # repeat stub checksum detection since salt isn't set # when _norm_checksum() is called. diff --git a/passlib/tests/test_ext_django.py b/passlib/tests/test_ext_django.py index 96de69e..890c87b 100644 --- a/passlib/tests/test_ext_django.py +++ b/passlib/tests/test_ext_django.py @@ -533,7 +533,7 @@ class PluginTest(TestCase): def test_06_categories(self): "test PASSLIB_GET_CATEGORY unset" update_settings( - PASSLIB_CONTEXT=category_context.policy, + PASSLIB_CONTEXT=category_context.policy.to_string(), ) import passlib.ext.django.models @@ -546,7 +546,7 @@ class PluginTest(TestCase): def get_category(user): return user.first_name or None update_settings( - PASSLIB_CONTEXT = category_context.policy, + PASSLIB_CONTEXT = category_context.policy.to_string(), PASSLIB_GET_CATEGORY = get_category, ) import passlib.ext.django.models @@ -559,7 +559,7 @@ class PluginTest(TestCase): def test_08_categories_disabled(self): "test PASSLIB_GET_CATEGORY = None" update_settings( - PASSLIB_CONTEXT = category_context.policy, + PASSLIB_CONTEXT = category_context.policy.to_string(), PASSLIB_GET_CATEGORY = None, ) import passlib.ext.django.models diff --git a/passlib/tests/test_handlers.py b/passlib/tests/test_handlers.py index aaa114b..f00e1cf 100644 --- a/passlib/tests/test_handlers.py +++ b/passlib/tests/test_handlers.py @@ -178,7 +178,7 @@ class _bcrypt_test(HandlerCase): # override some methods #=============================================================== def setUp(self): - HandlerCase.setUp(self) + super(_bcrypt_test, self).setUp() if self.backend == "builtin": warnings.filterwarnings("ignore", "SECURITY WARNING: .*pure-python bcrypt.*") @@ -2325,7 +2325,7 @@ class sun_md5_crypt_test(HandlerCase): def do_verify(self, secret, hash): # override to fake error for "$..." hash strings listed in known_config. # these have to be hash strings, in order to test bare salt issue. - if hash and hash.endswith("$......................"): + if isinstance(hash, str) and hash.endswith("$......................"): raise ValueError("pretending '$.' hash is config string") return self.handler.verify(secret, hash) diff --git a/passlib/tests/test_utils.py b/passlib/tests/test_utils.py index 2d9d147..4c3a6d2 100644 --- a/passlib/tests/test_utils.py +++ b/passlib/tests/test_utils.py @@ -348,7 +348,6 @@ class CodecTest(TestCase): #check unicode w/ encodings self.assertEqual(to_bytes(u('\x00\xff'), 'latin-1'), b('\x00\xff')) self.assertRaises(ValueError, to_bytes, u('\x00\xff'), 'ascii') - self.assertRaises(TypeError, to_bytes, u('abc'), None) #check bytes inputs self.assertEqual(to_bytes(b('abc')), b('abc')) @@ -364,6 +363,7 @@ class CodecTest(TestCase): b('\x00\xff')) #check other + self.assertRaises(AssertionError, to_bytes, 'abc', None) self.assertRaises(TypeError, to_bytes, None) def test_to_unicode(self): @@ -375,7 +375,6 @@ class CodecTest(TestCase): self.assertEqual(to_unicode(u('\x00\xff')), u('\x00\xff')) #check unicode input ignores encoding - self.assertEqual(to_unicode(u('\x00\xff'), None), u('\x00\xff')) self.assertEqual(to_unicode(u('\x00\xff'), "ascii"), u('\x00\xff')) #check bytes input @@ -384,9 +383,9 @@ class CodecTest(TestCase): self.assertEqual(to_unicode(b('\x00\xff'), 'latin-1'), u('\x00\xff')) self.assertRaises(ValueError, to_unicode, b('\x00\xff')) - self.assertRaises(TypeError, to_unicode, b('\x00\xff'), None) #check other + self.assertRaises(AssertionError, to_unicode, 'abc', None) self.assertRaises(TypeError, to_unicode, None) def test_to_native_str(self): diff --git a/passlib/tests/test_utils_handlers.py b/passlib/tests/test_utils_handlers.py index 5044d1e..827fc1b 100644 --- a/passlib/tests/test_utils_handlers.py +++ b/passlib/tests/test_utils_handlers.py @@ -74,7 +74,8 @@ class SkeletonTest(TestCase): self.assertFalse(d1.identify(u('a'))) self.assertFalse(d1.identify(u('b'))) self.assertFalse(d1.identify(u('c'))) - self.assertFalse(d1.identify(None)) + self.assertRaises(TypeError, d1.identify, None) + self.assertRaises(TypeError, d1.identify, 1) # check default genconfig method self.assertIs(d1.genconfig(), None) @@ -109,23 +110,24 @@ class SkeletonTest(TestCase): raise ValueError # check fallback - self.assertFalse(d1.identify(None)) + self.assertRaises(TypeError, d1.identify, None) + self.assertRaises(TypeError, d1.identify, 1) self.assertFalse(d1.identify('')) self.assertTrue(d1.identify('a')) self.assertFalse(d1.identify('b')) # check regexp d1._hash_regex = re.compile(u('@.')) - self.assertFalse(d1.identify(None)) - self.assertFalse(d1.identify('')) + self.assertRaises(TypeError, d1.identify, None) + self.assertRaises(TypeError, d1.identify, 1) self.assertTrue(d1.identify('@a')) self.assertFalse(d1.identify('a')) del d1._hash_regex # check ident-based d1.ident = u('!') - self.assertFalse(d1.identify(None)) - self.assertFalse(d1.identify('')) + self.assertRaises(TypeError, d1.identify, None) + self.assertRaises(TypeError, d1.identify, 1) self.assertTrue(d1.identify('!a')) self.assertFalse(d1.identify('a')) del d1.ident @@ -372,7 +374,8 @@ class SkeletonTest(TestCase): self.assertFalse(d1.identify(u("!Cxxx"))) self.assertFalse(d1.identify(u("A"))) self.assertFalse(d1.identify(u(""))) - self.assertFalse(d1.identify(None)) + self.assertRaises(TypeError, d1.identify, None) + self.assertRaises(TypeError, d1.identify, 1) # check default_ident missing is detected. d1.default_ident = None diff --git a/passlib/tests/test_win32.py b/passlib/tests/test_win32.py index 09f5023..7fd475a 100644 --- a/passlib/tests/test_win32.py +++ b/passlib/tests/test_win32.py @@ -21,7 +21,7 @@ class UtilTest(TestCase): ## among other places def setUp(self): - TestCase.setUp(self) + super(UtilTest, self).setUp() warnings.filterwarnings("ignore", "the 'passlib.win32' module is deprecated") diff --git a/passlib/tests/utils.py b/passlib/tests/utils.py index 17a60ba..713824e 100644 --- a/passlib/tests/utils.py +++ b/passlib/tests/utils.py @@ -197,7 +197,7 @@ class TestCase(unittest.TestCase): resetWarningState = True def setUp(self): - unittest.TestCase.setUp(self) + super(TestCase, self).setUp() if self.resetWarningState: ctx = reset_warnings() ctx.__enter__() @@ -1535,7 +1535,7 @@ class HandlerCase(TestCase): from passlib.utils import tick handler = self.handler disabled = self.is_disabled_handler - max_time = int(os.environ.get("PASSLIB_TESTS_FUZZ_TIME") or 1) + max_time = float(os.environ.get("PASSLIB_TESTS_FUZZ_TIME") or 1) verifiers = self.get_fuzz_verifiers() def vname(v): return (v.__doc__ or v.__name__).splitlines()[0] @@ -1721,7 +1721,7 @@ class OsCryptMixin(HandlerCase): if not self.handler.has_backend("os_crypt"): self.handler.get_backend() # hack to prevent recursion issue self._patch_safe_crypt() - HandlerCase.setUp(self) + super(OsCryptMixin, self).setUp() def _patch_safe_crypt(self): """if crypt() doesn't support current hash alg, this patches diff --git a/passlib/utils/__init__.py b/passlib/utils/__init__.py index b9ee776..e0b9e75 100644 --- a/passlib/utils/__init__.py +++ b/passlib/utils/__init__.py @@ -548,6 +548,7 @@ def to_bytes(source, encoding="utf-8", errname="value", source_encoding=None): * if *source_encoding* is specified, byte strings will be transcoded to *encoding*. """ + assert encoding if isinstance(source, bytes): if source_encoding and not is_same_codec(source_encoding, encoding): return source.decode(source_encoding).encode(encoding) @@ -579,6 +580,7 @@ def to_unicode(source, source_encoding="utf-8", errname="value"): if isinstance(source, unicode): return source elif isinstance(source, bytes): + assert source_encoding return source.decode(source_encoding) else: raise ExpectedStringError(source, errname) |
