diff options
| author | Eli Collins <elic@assurancetechnologies.com> | 2012-02-08 23:35:38 -0500 |
|---|---|---|
| committer | Eli Collins <elic@assurancetechnologies.com> | 2012-02-08 23:35:38 -0500 |
| commit | 4b3590ab0d73e9defb70c97763a1b69a07a7f9be (patch) | |
| tree | 7550b3c72d80816651c7ea8fc9f7ea28ae8f4b4c /passlib/tests | |
| parent | d9b0143bd9026a403f8aff2e4d468b385e3e313c (diff) | |
| parent | dcd2dcc7243052b2d5bd7d9f4abbedbb01911e13 (diff) | |
| download | passlib-4b3590ab0d73e9defb70c97763a1b69a07a7f9be.tar.gz | |
Merge
Diffstat (limited to 'passlib/tests')
| -rw-r--r-- | passlib/tests/test_context.py | 19 | ||||
| -rw-r--r-- | passlib/tests/test_handlers.py | 51 | ||||
| -rw-r--r-- | passlib/tests/test_utils_handlers.py | 275 | ||||
| -rw-r--r-- | passlib/tests/utils.py | 27 |
4 files changed, 233 insertions, 139 deletions
diff --git a/passlib/tests/test_context.py b/passlib/tests/test_context.py index a7d4caf..c0bd31c 100644 --- a/passlib/tests/test_context.py +++ b/passlib/tests/test_context.py @@ -18,7 +18,7 @@ except ImportError: #pkg from passlib import hash from passlib.context import CryptContext, CryptPolicy, LazyCryptContext -from passlib.exc import PasslibContextWarning +from passlib.exc import PasslibConfigWarning from passlib.utils import tick, to_bytes, to_unicode from passlib.utils.compat import irange, u import passlib.utils.handlers as uh @@ -629,8 +629,8 @@ class CryptContextTest(TestCase): # set below handler min c2 = cc.replace(all__min_rounds=500, all__max_rounds=None, all__default_rounds=500) - self.assertWarningMatches(wlog.pop(), category=PasslibContextWarning) - self.assertWarningMatches(wlog.pop(), category=PasslibContextWarning) + self.assertWarningMatches(wlog.pop(), category=PasslibConfigWarning) + self.assertWarningMatches(wlog.pop(), category=PasslibConfigWarning) self.assertEqual(c2.genconfig(salt="nacl"), "$5$rounds=1000$nacl$") self.assertNoWarnings(wlog) @@ -639,7 +639,7 @@ class CryptContextTest(TestCase): cc.genconfig(rounds=1999, salt="nacl"), '$5$rounds=2000$nacl$', ) - self.assertWarningMatches(wlog.pop(), category=PasslibContextWarning) + self.assertWarningMatches(wlog.pop(), category=PasslibConfigWarning) self.assertNoWarnings(wlog) # equal @@ -661,8 +661,8 @@ class CryptContextTest(TestCase): # set above handler max c2 = cc.replace(all__max_rounds=int(1e9)+500, all__min_rounds=None, all__default_rounds=int(1e9)+500) - self.assertWarningMatches(wlog.pop(), category=PasslibContextWarning) - self.assertWarningMatches(wlog.pop(), category=PasslibContextWarning) + self.assertWarningMatches(wlog.pop(), category=PasslibConfigWarning) + self.assertWarningMatches(wlog.pop(), category=PasslibConfigWarning) self.assertEqual(c2.genconfig(salt="nacl"), "$5$rounds=999999999$nacl$") self.assertNoWarnings(wlog) @@ -672,7 +672,7 @@ class CryptContextTest(TestCase): cc.genconfig(rounds=3001, salt="nacl"), '$5$rounds=3000$nacl$' ) - self.assertWarningMatches(wlog.pop(), category=PasslibContextWarning) + self.assertWarningMatches(wlog.pop(), category=PasslibConfigWarning) self.assertNoWarnings(wlog) # equal @@ -788,11 +788,12 @@ class CryptContextTest(TestCase): c2 = cc.replace(all__vary_rounds="100%") self.assert_rounds_range(c2, "bcrypt", 15, 21) - def assert_rounds_range(self, context, scheme, lower, upper, salt="."*22): + def assert_rounds_range(self, context, scheme, lower, upper): "helper to check vary_rounds covers specified range" # NOTE: this runs enough times the min and max *should* be hit, # though there's a faint chance it will randomly fail. handler = context.policy.get_handler(scheme) + salt = handler.default_salt_chars[0:1] * handler.max_salt_size seen = set() for i in irange(300): h = context.genconfig(scheme, salt=salt) @@ -824,7 +825,7 @@ class CryptContextTest(TestCase): cc.encrypt("password", rounds=1999, salt="nacl"), '$5$rounds=2000$nacl$9/lTZ5nrfPuz8vphznnmHuDGFuvjSNvOEDsGmGfsS97', ) - self.assertWarningMatches(wlog.pop(), category=PasslibContextWarning) + self.assertWarningMatches(wlog.pop(), category=PasslibConfigWarning) self.assertFalse(wlog) self.assertEqual( diff --git a/passlib/tests/test_handlers.py b/passlib/tests/test_handlers.py index 9da90d0..5c94b73 100644 --- a/passlib/tests/test_handlers.py +++ b/passlib/tests/test_handlers.py @@ -110,16 +110,14 @@ class _BCryptTest(HandlerCase): kwds = dict(checksum='8CIhhFCj15KqqFvo/n.Jatx8dJ92f82', salt='VlsfIX9.apXuQBr6tego0.', - rounds=12, ident="2a", strict=True) + rounds=12, ident="2a") handler(**kwds) - kwds['ident'] = None - self.assertRaises(ValueError, handler, **kwds) - - del kwds['strict'] + kwds.update(ident=None) + self.assertRaises(TypeError, handler, **kwds) - kwds['ident'] = 'Q' + kwds.update(use_defaults=True, ident='Q') self.assertRaises(ValueError, handler, **kwds) #=============================================================== @@ -149,7 +147,7 @@ class _BCryptTest(HandlerCase): self.assertWarningMatches(wlog.pop(0), message_re="^encountered a bcrypt hash with incorrectly set padding bits.*", ) - self.assertFalse(wlog) + self.assertNoWarnings(wlog) def check_padding(hash): "check bcrypt hash doesn't have salt padding bits set" @@ -174,12 +172,14 @@ class _BCryptTest(HandlerCase): with catch_warnings(record=True) as wlog: warnings.simplefilter("always") - hash = bcrypt.genconfig(salt="."*21 + "A.") + hash = bcrypt.genconfig(salt="."*21 + "A.", relaxed=True) + self.assertWarningMatches(wlog.pop(0), message_re="salt too large") check_warning(wlog) self.assertEqual(hash, "$2a$12$" + "." * 22) - hash = bcrypt.genconfig(salt="."*23) - self.assertFalse(wlog) + hash = bcrypt.genconfig(salt="."*23, relaxed=True) + self.assertWarningMatches(wlog.pop(0), message_re="salt too large") + self.assertNoWarnings(wlog) self.assertEqual(hash, "$2a$12$" + "." * 22) #=============================================================== @@ -710,14 +710,13 @@ class NTHashTest(HandlerCase): def test_idents(self): handler = self.handler - kwds = dict(checksum='7f8fe03093cc84b267b109625f6bbf4b', ident="3", strict=True) + kwds = dict(checksum='7f8fe03093cc84b267b109625f6bbf4b', ident="3") handler(**kwds) - kwds['ident'] = None - self.assertRaises(ValueError, handler, **kwds) + kwds.update(ident=None) + self.assertRaises(TypeError, handler, **kwds) - del kwds['strict'] - kwds['ident'] = 'Q' + kwds.update(use_defaults=True, ident='Q') self.assertRaises(ValueError, handler, **kwds) #========================================================= @@ -917,14 +916,14 @@ class PHPassTest(HandlerCase): def test_idents(self): handler = self.handler - kwds = dict(checksum='eRo7ud9Fh4E2PdI0S3r.L0', salt='IQRaTwmf', rounds=9, ident="P", strict=True) + kwds = dict(checksum='eRo7ud9Fh4E2PdI0S3r.L0', salt='IQRaTwmf', + rounds=9, ident="P") handler(**kwds) - kwds['ident'] = None - self.assertRaises(ValueError, handler, **kwds) + kwds.update(ident=None) + self.assertRaises(TypeError, handler, **kwds) - del kwds['strict'] - kwds['ident'] = 'Q' + kwds.update(use_defaults=True, ident='Q') self.assertRaises(ValueError, handler, **kwds) #========================================================= @@ -1067,8 +1066,8 @@ class ScramTest(HandlerCase): def test_100_algs(self): "test parsing of 'algs' setting" - def parse(source): - return self.handler(algs=source).algs + def parse(algs, **kwds): + return self.handler(algs=algs, use_defaults=True, **kwds).algs # None -> default list self.assertEqual(parse(None), ["sha-1","sha-256","sha-512"]) @@ -1087,7 +1086,7 @@ class ScramTest(HandlerCase): self.assertRaises(ValueError, parse, ["sha-1","shaxxx-890"]) # alg & checksum mutually exclusive. - self.assertRaises(RuntimeError, self.handler, algs=['sha-1'], + self.assertRaises(RuntimeError, parse, ['sha-1'], checksum={"sha-1": b("\x00"*20)}) def test_101_extract_digest_info(self): @@ -1374,8 +1373,7 @@ class _SHA256CryptTest(HandlerCase): "2bIC" ), ] - def filter_known_config_warnings(self): - warnings.filterwarnings("ignore", "sha256_crypt does not allow less than 1000 rounds: 10", UserWarning) + filter_config_warnings = True # rounds too low, salt too small def test_raw(self): #run some tests on raw backend func to ensure it works right @@ -1448,8 +1446,7 @@ class _SHA512CryptTest(HandlerCase): "hLsPuWGsUSklZt58jaTfF4ZEQpyUNGc0dqbpBYYBaHHrsX." ), ] - def filter_known_config_warnings(self): - warnings.filterwarnings("ignore", "sha512_crypt does not allow less than 1000 rounds: 10", UserWarning) + filter_config_warnings = True # rounds too low, salt too small OsCrypt_SHA512CryptTest = create_backend_case(_SHA512CryptTest, "os_crypt") Builtin_SHA512CryptTest = create_backend_case(_SHA512CryptTest, "builtin") diff --git a/passlib/tests/test_utils_handlers.py b/passlib/tests/test_utils_handlers.py index fe2667a..39791ca 100644 --- a/passlib/tests/test_utils_handlers.py +++ b/passlib/tests/test_utils_handlers.py @@ -13,10 +13,10 @@ import warnings from passlib.hash import ldap_md5, sha256_crypt from passlib.registry import _unload_handler_name as unload_handler_name, \ register_crypt_handler, get_crypt_handler -from passlib.exc import MissingBackendError +from passlib.exc import MissingBackendError, PasslibHashWarning from passlib.utils import getrandstr, JYTHON, rng, to_unicode from passlib.utils.compat import b, bytes, bascii_to_str, str_to_uascii, \ - uascii_to_str, unicode + uascii_to_str, unicode, PY_MAX_25 import passlib.utils.handlers as uh from passlib.tests.utils import HandlerCase, TestCase, catch_warnings, \ dummy_handler_in_registry @@ -25,6 +25,21 @@ from passlib.utils.compat import u log = getLogger(__name__) #========================================================= +# utils +#========================================================= +def _makelang(alphabet, size): + "generate all strings of given size using alphabet" + def helper(size): + if size < 2: + for char in alphabet: + yield char + else: + for char in alphabet: + for tail in helper(size-1): + yield char+tail + return set(helper(size)) + +#========================================================= #test support classes - StaticHandler, GenericHandler, etc #========================================================= class SkeletonTest(TestCase): @@ -95,13 +110,13 @@ class SkeletonTest(TestCase): else: raise ValueError - #check fallback + # check fallback self.assertFalse(d1.identify(None)) self.assertFalse(d1.identify('')) self.assertTrue(d1.identify('a')) self.assertFalse(d1.identify('b')) - #check ident-based + # check ident-based d1.ident = u('!') self.assertFalse(d1.identify(None)) self.assertFalse(d1.identify('')) @@ -109,70 +124,108 @@ class SkeletonTest(TestCase): self.assertFalse(d1.identify('a')) def test_11_norm_checksum(self): - "test GenericHandler.norm_checksum()" + "test GenericHandler checksum handling" + # setup helpers class d1(uh.GenericHandler): name = 'd1' checksum_size = 4 checksum_chars = 'x' - self.assertRaises(ValueError, d1.norm_checksum, 'xxx') - self.assertEqual(d1.norm_checksum('xxxx'), 'xxxx') - self.assertRaises(ValueError, d1.norm_checksum, 'xxxxx') - self.assertRaises(ValueError, d1.norm_checksum, 'xxyx') + + def norm_checksum(*a, **k): + return d1(*a, **k).checksum + + # too small + self.assertRaises(ValueError, norm_checksum, 'xxx') + + # right size + self.assertEqual(norm_checksum('xxxx'), 'xxxx') + + # too large + self.assertRaises(ValueError, norm_checksum, 'xxxxx') + + # wrong chars + self.assertRaises(ValueError, norm_checksum, 'xxyx') def test_20_norm_salt(self): - "test GenericHandler+HasSalt: .norm_salt(), .generate_salt()" - class d1(uh.HasSalt, uh.GenericHandler): - name = 'd1' - setting_kwds = ('salt',) - min_salt_size = 1 - max_salt_size = 3 - default_salt_size = 2 - salt_chars = 'a' - - #check salt=None - self.assertEqual(d1.norm_salt(None), 'aa') - self.assertRaises(ValueError, d1.norm_salt, None, strict=True) - - #check small & large salts - with catch_warnings(): - warnings.filterwarnings("ignore", ".* salt string must be at (least|most) .*", UserWarning) - self.assertEqual(d1.norm_salt('aaaa'), 'aaa') - self.assertRaises(ValueError, d1.norm_salt, '') - self.assertRaises(ValueError, d1.norm_salt, 'aaaa', strict=True) - - #check generate salt (indirectly) - self.assertEqual(len(d1.norm_salt(None)), 2) - self.assertEqual(len(d1.norm_salt(None,salt_size=1)), 1) - self.assertEqual(len(d1.norm_salt(None,salt_size=3)), 3) - self.assertEqual(len(d1.norm_salt(None,salt_size=5)), 3) - self.assertRaises(ValueError, d1.norm_salt, None, salt_size=5, strict=True) - - def test_21_norm_salt(self): - "test GenericHandler+HasSalt: .norm_salt(), .generate_salt() - with no max_salt_size" + "test GenericHandler + HasSalt mixin" + # setup helpers class d1(uh.HasSalt, uh.GenericHandler): name = 'd1' setting_kwds = ('salt',) - min_salt_size = 1 - max_salt_size = None - default_salt_size = 2 - salt_chars = 'a' - - #check salt=None - self.assertEqual(d1.norm_salt(None), 'aa') - self.assertRaises(ValueError, d1.norm_salt, None, strict=True) - - #check small & large salts - self.assertRaises(ValueError, d1.norm_salt, '') - self.assertEqual(d1.norm_salt('aaaa', strict=True), 'aaaa') - - #check generate salt (indirectly) - self.assertEqual(len(d1.norm_salt(None)), 2) - self.assertEqual(len(d1.norm_salt(None,salt_size=1)), 1) - self.assertEqual(len(d1.norm_salt(None,salt_size=3)), 3) - self.assertEqual(len(d1.norm_salt(None,salt_size=5)), 5) + min_salt_size = 2 + max_salt_size = 4 + default_salt_size = 3 + salt_chars = 'ab' + + def norm_salt(**k): + return d1(**k).salt + + def gen_salt(sz, **k): + return d1(use_defaults=True, salt_size=sz, **k).salt + + salts2 = _makelang('ab', 2) + salts3 = _makelang('ab', 3) + salts4 = _makelang('ab', 4) + + # check salt=None + self.assertRaises(TypeError, norm_salt) + self.assertRaises(TypeError, norm_salt, salt=None) + self.assertIn(norm_salt(use_defaults=True), salts3) + + # check explicit salts + with catch_warnings(record=True) as wlog: + + # check too-small salts + self.assertRaises(ValueError, norm_salt, salt='') + self.assertRaises(ValueError, norm_salt, salt='a') + self.assertNoWarnings(wlog) + + # check correct salts + self.assertEqual(norm_salt(salt='ab'), 'ab') + self.assertEqual(norm_salt(salt='aba'), 'aba') + self.assertEqual(norm_salt(salt='abba'), 'abba') + self.assertNoWarnings(wlog) + + # check too-large salts + self.assertRaises(ValueError, norm_salt, salt='aaaabb') + self.assertNoWarnings(wlog) + + self.assertEqual(norm_salt(salt='aaaabb', relaxed=True), 'aaaa') + self.assertWarningMatches(wlog.pop(0), category=PasslibHashWarning) + self.assertNoWarnings(wlog) + + #check generated salts + with catch_warnings(record=True) as wlog: + + # check too-small salt size + self.assertRaises(ValueError, gen_salt, 0) + self.assertRaises(ValueError, gen_salt, 1) + self.assertNoWarnings(wlog) + + # check correct salt size + self.assertIn(gen_salt(2), salts2) + self.assertIn(gen_salt(3), salts3) + self.assertIn(gen_salt(4), salts4) + self.assertNoWarnings(wlog) + + # check too-large salt size + self.assertRaises(ValueError, gen_salt, 5) + self.assertNoWarnings(wlog) + + self.assertIn(gen_salt(5, relaxed=True), salts4) + self.assertWarningMatches(wlog.pop(0), category=PasslibHashWarning) + self.assertNoWarnings(wlog) + + # test with max_salt_size=None + del d1.max_salt_size + with catch_warnings(record=True) as wlog: + self.assertEqual(len(gen_salt(None)), 3) + self.assertEqual(len(gen_salt(5)), 5) + self.assertNoWarnings(wlog) def test_30_norm_rounds(self): - "test GenericHandler+HasRounds: .norm_rounds()" + "test GenericHandler + HasRounds mixin" + # setup helpers class d1(uh.HasRounds, uh.GenericHandler): name = 'd1' setting_kwds = ('rounds',) @@ -180,24 +233,44 @@ class SkeletonTest(TestCase): max_rounds = 3 default_rounds = 2 - #check rounds=None - self.assertEqual(d1.norm_rounds(None), 2) - self.assertRaises(ValueError, d1.norm_rounds, None, strict=True) + def norm_rounds(**k): + return d1(**k).rounds + + # check rounds=None + self.assertRaises(TypeError, norm_rounds) + self.assertRaises(TypeError, norm_rounds, rounds=None) + self.assertEqual(norm_rounds(use_defaults=True), 2) + + # check explicit rounds + with catch_warnings(record=True) as wlog: + # too small + self.assertRaises(ValueError, norm_rounds, rounds=0) + self.assertNoWarnings(wlog) + + self.assertEqual(norm_rounds(rounds=0, relaxed=True), 1) + self.assertWarningMatches(wlog.pop(0), category=PasslibHashWarning) + self.assertNoWarnings(wlog) + + # just right + self.assertEqual(norm_rounds(rounds=1), 1) + self.assertEqual(norm_rounds(rounds=2), 2) + self.assertEqual(norm_rounds(rounds=3), 3) + self.assertNoWarnings(wlog) - #check small & large rounds - with catch_warnings(): - warnings.filterwarnings("ignore", ".* does not allow (less|more) than \d rounds: .*", UserWarning) - self.assertEqual(d1.norm_rounds(0), 1) - self.assertEqual(d1.norm_rounds(4), 3) - self.assertRaises(ValueError, d1.norm_rounds, 0, strict=True) - self.assertRaises(ValueError, d1.norm_rounds, 4, strict=True) + # too large + self.assertRaises(ValueError, norm_rounds, rounds=4) + self.assertNoWarnings(wlog) - #check no default rounds + self.assertEqual(norm_rounds(rounds=4, relaxed=True), 3) + self.assertWarningMatches(wlog.pop(0), category=PasslibHashWarning) + self.assertNoWarnings(wlog) + + # check no default rounds d1.default_rounds = None - self.assertRaises(ValueError, d1.norm_rounds, None) + self.assertRaises(TypeError, norm_rounds, use_defaults=True) def test_40_backends(self): - "test GenericHandler+HasManyBackends" + "test GenericHandler + HasManyBackends mixin" class d1(uh.HasManyBackends, uh.GenericHandler): name = 'd1' setting_kwds = () @@ -225,12 +298,12 @@ class SkeletonTest(TestCase): #test lazy load obj = d1() - self.assertEqual(obj.calc_checksum('s'), 'b') + self.assertEqual(obj._calc_checksum('s'), 'b') #test repeat load d1.set_backend('b') d1.set_backend('any') - self.assertEqual(obj.calc_checksum('s'), 'b') + self.assertEqual(obj._calc_checksum('s'), 'b') #test unavailable self.assertRaises(MissingBackendError, d1.set_backend, 'a') @@ -243,39 +316,42 @@ class SkeletonTest(TestCase): #test explicit self.assertTrue(d1.has_backend()) d1.set_backend('a') - self.assertEqual(obj.calc_checksum('s'), 'a') + self.assertEqual(obj._calc_checksum('s'), 'a') #test unknown backend self.assertRaises(ValueError, d1.set_backend, 'c') self.assertRaises(ValueError, d1.has_backend, 'c') - def test_50_bh_norm_ident(self): - "test GenericHandler+HasManyIdents: .norm_ident() & .identify()" + def test_50_norm_ident(self): + "test GenericHandler + HasManyIdents" + # setup helpers class d1(uh.HasManyIdents, uh.GenericHandler): name = 'd1' setting_kwds = ('ident',) + default_ident = u("!A") ident_values = [ u("!A"), u("!B") ] ident_aliases = { u("A"): u("!A")} - #check ident=None w/ no default - self.assertIs(d1.norm_ident(None), None) - self.assertRaises(ValueError, d1.norm_ident, None, strict=True) + def norm_ident(**k): + return d1(**k).ident + + # check ident=None + self.assertRaises(TypeError, norm_ident) + self.assertRaises(TypeError, norm_ident, ident=None) + self.assertEqual(norm_ident(use_defaults=True), u('!A')) - #check ident=None w/ default - d1.default_ident = u("!A") - self.assertEqual(d1.norm_ident(None), u('!A')) - self.assertRaises(ValueError, d1.norm_ident, None, strict=True) + # check valid idents + self.assertEqual(norm_ident(ident=u('!A')), u('!A')) + self.assertEqual(norm_ident(ident=u('!B')), u('!B')) + self.assertRaises(ValueError, norm_ident, ident=u('!C')) - #check explicit - self.assertEqual(d1.norm_ident(u('!A')), u('!A')) - self.assertEqual(d1.norm_ident(u('!B')), u('!B')) - self.assertRaises(ValueError, d1.norm_ident, u('!C')) + # check aliases + self.assertEqual(norm_ident(ident=u('A')), u('!A')) - #check aliases - self.assertEqual(d1.norm_ident(u('A')), u('!A')) - self.assertRaises(ValueError, d1.norm_ident, u('B')) + # check invalid idents + self.assertRaises(ValueError, norm_ident, ident=u('B')) - #check identify + # check identify is honoring ident system self.assertTrue(d1.identify(u("!Axxx"))) self.assertTrue(d1.identify(u("!Bxxx"))) self.assertFalse(d1.identify(u("!Cxxx"))) @@ -283,6 +359,10 @@ class SkeletonTest(TestCase): self.assertFalse(d1.identify(u(""))) self.assertFalse(d1.identify(None)) + # check default_ident missing is detected. + d1.default_ident = None + self.assertRaises(AssertionError, norm_ident, use_defaults=True) + #========================================================= #eoc #========================================================= @@ -344,7 +424,7 @@ class PrefixWrapperTest(TestCase): d2 = uh.PrefixWrapper("d2", "sha256_crypt", "{XXX}") self.assertIs(d2.setting_kwds, sha256_crypt.setting_kwds) - if PY_25_MAX: # lacks __dir__() support + if PY_MAX_25: # __dir__() support not added until py 2.6 self.assertFalse('max_rounds' in dir(d2)) else: self.assertTrue('max_rounds' in dir(d2)) @@ -444,7 +524,7 @@ class SaltedHash(uh.HasStubChecksum, uh.HasSalt, uh.GenericHandler): raise ValueError("not a salted-example hash") if isinstance(hash, bytes): hash = hash.decode("ascii") - return cls(salt=hash[5:-40], checksum=hash[-40:], strict=True) + return cls(salt=hash[5:-40], checksum=hash[-40:]) _stub_checksum = u('0') * 40 @@ -452,7 +532,7 @@ class SaltedHash(uh.HasStubChecksum, uh.HasSalt, uh.GenericHandler): hash = u("@salt%s%s") % (self.salt, self.checksum or self._stub_checksum) return uascii_to_str(hash) - def calc_checksum(self, secret): + def _calc_checksum(self, secret): if isinstance(secret, unicode): secret = secret.encode("utf-8") data = self.salt.encode("ascii") + secret + self.salt.encode("ascii") @@ -481,9 +561,6 @@ class UnsaltedHashTest(HandlerCase): # behavior, but that's a lot of effort for a non-critical # border case. so just skipping this test instead... self.assertRaises(TypeError, UnsaltedHash, salt='x') - self.assertRaises(ValueError, SaltedHash, checksum=SaltedHash._stub_checksum, salt=None, strict=True) - self.assertRaises(ValueError, SaltedHash, checksum=SaltedHash._stub_checksum, salt='xxx', strict=True) - self.assertRaises(TypeError, UnsaltedHash.genconfig, rounds=1) class SaltedHashTest(HandlerCase): @@ -495,6 +572,12 @@ class SaltedHashTest(HandlerCase): '@salt9f978a9bfe360d069b0c13f2afecd570447407fa7e48'), ] + def test_bad_kwds(self): + self.assertRaises(TypeError, SaltedHash, + checksum=SaltedHash._stub_checksum, salt=None) + self.assertRaises(ValueError, SaltedHash, + checksum=SaltedHash._stub_checksum, salt='xxx') + #========================================================= #EOF #========================================================= diff --git a/passlib/tests/utils.py b/passlib/tests/utils.py index 628c4ee..c4019ab 100644 --- a/passlib/tests/utils.py +++ b/passlib/tests/utils.py @@ -10,6 +10,7 @@ import re import os import sys import tempfile +from passlib.exc import PasslibHashWarning from passlib.utils.compat import PY2, PY27, PY_MIN_32, PY3 try: @@ -870,8 +871,11 @@ class HandlerCase(TestCase): #make sure salt is truncated exactly where it should be. salt = cc * mx c1 = self.do_genconfig(salt=salt) - c2 = self.do_genconfig(salt=salt + cc) - self.assertEqual(c1,c2) + self.assertRaises(ValueError, self.do_genconfig, salt=salt + cc) + if _has_relaxed_setting(handler): + with catch_warnings(record=True): # issues passlibhandlerwarning + c2 = self.do_genconfig(salt=salt + cc, relaxed=True) + self.assertEqual(c1,c2) #if min_salt supports it, check smaller than mx is NOT truncated if handler.min_salt_size < mx: @@ -908,17 +912,17 @@ class HandlerCase(TestCase): #========================================================= #genhash() #========================================================= - filter_known_config_warnings = None + filter_config_warnings = False def test_40_genhash_config(self): "test genhash() against known config strings" if not self.known_correct_configs: raise self.skipTest("no config strings provided") - fk = self.filter_known_config_warnings + fk = self.filter_config_warnings if fk: ctx = catch_warnings() ctx.__enter__() - fk() + warnings.filterwarnings("ignore", category=PasslibHashWarning) for config, secret, hash in self.known_correct_configs: result = self.do_genhash(secret, config) self.assertEqual(result, hash, "config=%r,secret=%r:" % (config,secret)) @@ -1000,8 +1004,9 @@ class HandlerCase(TestCase): # use crypt.crypt() to check handlers that have an 'os_crypt' backend. if _has_possible_crypt_support(handler): possible = True - # NOTE: disabling when self._orig_crypt set, means has_backend - # will return a false positive. + # NOTE: disabling this when self._orig_crypt is set, since that flag + # indicates the current testcase has temporarily hacked os_crypt so + # that has_backend() will return a false positive. if not self._orig_crypt and handler.has_backend("os_crypt"): def check_crypt(secret, hash): from crypt import crypt @@ -1018,6 +1023,8 @@ class HandlerCase(TestCase): # generate a single hash, and verify it using all helpers. secret = b('t\xc3\xa1\xd0\x91\xe2\x84\x93\xc9\x99').decode("utf-8") hash = self.do_encrypt(secret) + if PY2 and isinstance(secret, unicode): + secret = secret.encode("utf-8") for helper in helpers: helper(secret, hash) @@ -1112,6 +1119,12 @@ def _has_possible_crypt_support(handler): 'os_crypt' in handler.backends and \ not hasattr(handler, "orig_prefix") # ignore wrapper classes +def _has_relaxed_setting(handler): + # FIXME: I've been lazy, should probably just add 'relaxed' kwd + # to all handlers that derive from GenericHandler + return 'relaxed' in handler.setting_kwds or issubclass(handler, + uh.GenericHandler) + def create_backend_case(base, name, module="passlib.tests.test_handlers"): "create a test case for specific backend of a multi-backend handler" #get handler, figure out if backend should be tested |
