def test_12_hash_needs_update(self):
        """test hash_needs_update() method"""
        cc = CryptContext(**self.sample_policy_1)

        # check deprecated scheme
        self.assertTrue(cc.hash_needs_update('9XXD4trGYeGJA'))
        self.assertFalse(
            cc.hash_needs_update('$1$J8HC2RCr$HcmM.7NxB2weSvlw2FgzU0'))

        # check min rounds
        self.assertTrue(
            cc.hash_needs_update(
                '$5$rounds=1999$jD81UCoo.zI.UETs$Y7qSTQ6mTiU9qZB4fRr43wRgQq4V.5AAf7F97Pzxey/'
            ))
        self.assertFalse(
            cc.hash_needs_update(
                '$5$rounds=2000$228SSRje04cnNCaQ$YGV4RYu.5sNiBvorQDlO0WWQjyJVGKBcJXz3OtyQ2u8'
            ))

        # check max rounds
        self.assertFalse(
            cc.hash_needs_update(
                '$5$rounds=3000$fS9iazEwTKi7QPW4$VasgBC8FqlOvD7x2HhABaMXCTh9jwHclPA9j5YQdns.'
            ))
        self.assertTrue(
            cc.hash_needs_update(
                '$5$rounds=3001$QlFHHifXvpFX4PLs$/0ekt7lSs/lOikSerQ0M/1porEHxYq7W/2hdFpxA3fA'
            ))
Beispiel #2
0
 def test_is_crypt_context(self):
     """test is_crypt_context()"""
     from lib.passlib.utils import is_crypt_context
     from lib.passlib.context import CryptContext
     cc = CryptContext(["des_crypt"])
     self.assertTrue(is_crypt_context(cc))
     self.assertFalse(not is_crypt_context(cc))
    def test_01_replace(self):
        """test replace()"""

        cc = CryptContext(["md5_crypt", "bsdi_crypt", "des_crypt"])
        self.assertIs(cc.policy.get_handler(), hash.md5_crypt)

        cc2 = cc.replace()
        self.assertIsNot(cc2, cc)
        # NOTE: was not able to maintain backward compatibility with this...
        ##self.assertIs(cc2.policy, cc.policy)

        cc3 = cc.replace(default="bsdi_crypt")
        self.assertIsNot(cc3, cc)
        # NOTE: was not able to maintain backward compatibility with this...
        ##self.assertIs(cc3.policy, cc.policy)
        self.assertIs(cc3.policy.get_handler(), hash.bsdi_crypt)
Beispiel #4
0
    def __init__(self, context=None, get_user_category=None, **kwds):

        # init log
        self.log = logging.getLogger(__name__ + ".DjangoContextAdapter")

        # init parent, filling in default context object
        if context is None:
            context = CryptContext()
        super(DjangoContextAdapter, self).__init__(context=context, **kwds)

        # setup user category
        if get_user_category:
            assert callable(get_user_category)
            self.get_user_category = get_user_category

        # install lru cache wrappers
        from django.utils.lru_cache import lru_cache
        self.get_hashers = lru_cache()(self.get_hashers)

        # get copy of original make_password
        from django.contrib.auth.hashers import make_password
        if make_password.__module__.startswith("passlib."):
            make_password = _PatchManager.peek_unpatched_func(make_password)
        self._orig_make_password = make_password

        # get other django helpers
        from django.contrib.auth.hashers import is_password_usable
        self.is_password_usable = is_password_usable

        # init manager
        mlog = logging.getLogger(__name__ + ".DjangoContextAdapter._manager")
        self._manager = _PatchManager(log=mlog)
    def test_01_replace(self):
        """test replace()"""

        cc = CryptContext(["md5_crypt", "bsdi_crypt", "des_crypt"])
        self.assertIs(cc.policy.get_handler(), hash.md5_crypt)

        cc2 = cc.replace()
        self.assertIsNot(cc2, cc)
        # NOTE: was not able to maintain backward compatibility with this...
        ##self.assertIs(cc2.policy, cc.policy)

        cc3 = cc.replace(default="bsdi_crypt")
        self.assertIsNot(cc3, cc)
        # NOTE: was not able to maintain backward compatibility with this...
        ##self.assertIs(cc3.policy, cc.policy)
        self.assertIs(cc3.policy.get_handler(), hash.bsdi_crypt)
    def test_02_no_handlers(self):
        """test no handlers"""

        # check constructor...
        cc = CryptContext()
        self.assertRaises(KeyError, cc.identify, 'hash', required=True)
        self.assertRaises(KeyError, cc.hash, 'secret')
        self.assertRaises(KeyError, cc.verify, 'secret', 'hash')

        # check updating policy after the fact...
        cc = CryptContext(['md5_crypt'])
        p = CryptPolicy(schemes=[])
        cc.policy = p

        self.assertRaises(KeyError, cc.identify, 'hash', required=True)
        self.assertRaises(KeyError, cc.hash, 'secret')
        self.assertRaises(KeyError, cc.verify, 'secret', 'hash')
    def test_02_no_handlers(self):
        """test no handlers"""

        # check constructor...
        cc = CryptContext()
        self.assertRaises(KeyError, cc.identify, 'hash', required=True)
        self.assertRaises(KeyError, cc.encrypt, 'secret')
        self.assertRaises(KeyError, cc.verify, 'secret', 'hash')

        # check updating policy after the fact...
        cc = CryptContext(['md5_crypt'])
        p = CryptPolicy(schemes=[])
        cc.policy = p

        self.assertRaises(KeyError, cc.identify, 'hash', required=True)
        self.assertRaises(KeyError, cc.encrypt, 'secret')
        self.assertRaises(KeyError, cc.verify, 'secret', 'hash')
    def test_00_constructor(self):
        """test constructor"""
        # create crypt context using handlers
        cc = CryptContext([hash.md5_crypt, hash.bsdi_crypt, hash.des_crypt])
        c,b,a = cc.policy.iter_handlers()
        self.assertIs(a, hash.des_crypt)
        self.assertIs(b, hash.bsdi_crypt)
        self.assertIs(c, hash.md5_crypt)

        # create context using names
        cc = CryptContext(["md5_crypt", "bsdi_crypt", "des_crypt"])
        c,b,a = cc.policy.iter_handlers()
        self.assertIs(a, hash.des_crypt)
        self.assertIs(b, hash.bsdi_crypt)
        self.assertIs(c, hash.md5_crypt)

        # policy kwd
        policy = cc.policy
        cc = CryptContext(policy=policy)
        self.assertEqual(cc.to_dict(), policy.to_dict())

        cc = CryptContext(policy=policy, default="bsdi_crypt")
        self.assertNotEqual(cc.to_dict(), policy.to_dict())
        self.assertEqual(cc.to_dict(), dict(schemes=["md5_crypt","bsdi_crypt","des_crypt"],
                                            default="bsdi_crypt"))

        self.assertRaises(TypeError, setattr, cc, 'policy', None)
        self.assertRaises(TypeError, CryptContext, policy='x')
    def test_30_nonstring_hash(self):
        """test non-string hash values cause error"""
        #
        # test hash=None or some other non-string causes TypeError
        # and that explicit-scheme code path behaves the same.
        #
        cc = CryptContext(["des_crypt"])
        for hash, kwds in [
                (None, {}),
                (None, {"scheme": "des_crypt"}),
                (1, {}),
                ((), {}),
                ]:

            self.assertRaises(TypeError, cc.hash_needs_update, hash, **kwds)

        cc2 = CryptContext(["mysql323"])
        self.assertRaises(TypeError, cc2.hash_needs_update, None)
    def test_30_nonstring_hash(self):
        """test non-string hash values cause error"""
        warnings.filterwarnings(
            "ignore", ".*needs_update.*'scheme' keyword is deprecated.*")

        #
        # test hash=None or some other non-string causes TypeError
        # and that explicit-scheme code path behaves the same.
        #
        cc = CryptContext(["des_crypt"])
        for hash, kwds in [
            (None, {}),
                # NOTE: 'scheme' kwd is deprecated...
            (None, {
                "scheme": "des_crypt"
            }),
            (1, {}),
            ((), {}),
        ]:

            self.assertRaises(TypeError, cc.hash_needs_update, hash, **kwds)

        cc2 = CryptContext(["mysql323"])
        self.assertRaises(TypeError, cc2.hash_needs_update, None)
    def test_13_config_defaults(self):
        """test PASSLIB_CONFIG default behavior"""
        # check implicit default
        from lib.passlib.ext.django.utils import lib.passlib_DEFAULT
        default = CryptContext.from_string(PASSLIB_DEFAULT)
        self.load_extension()
        self.assert_patched(PASSLIB_DEFAULT)

        # check default preset
        self.load_extension(PASSLIB_CONTEXT="passlib-default", check=False)
        self.assert_patched(PASSLIB_DEFAULT)

        # check explicit string
        self.load_extension(PASSLIB_CONTEXT=PASSLIB_DEFAULT, check=False)
        self.assert_patched(PASSLIB_DEFAULT)
    def test_12_hash_needs_update(self):
        """test hash_needs_update() method"""
        cc = CryptContext(**self.sample_policy_1)

        # check deprecated scheme
        self.assertTrue(cc.hash_needs_update('9XXD4trGYeGJA'))
        self.assertFalse(cc.hash_needs_update('$1$J8HC2RCr$HcmM.7NxB2weSvlw2FgzU0'))

        # check min rounds
        self.assertTrue(cc.hash_needs_update('$5$rounds=1999$jD81UCoo.zI.UETs$Y7qSTQ6mTiU9qZB4fRr43wRgQq4V.5AAf7F97Pzxey/'))
        self.assertFalse(cc.hash_needs_update('$5$rounds=2000$228SSRje04cnNCaQ$YGV4RYu.5sNiBvorQDlO0WWQjyJVGKBcJXz3OtyQ2u8'))

        # check max rounds
        self.assertFalse(cc.hash_needs_update('$5$rounds=3000$fS9iazEwTKi7QPW4$VasgBC8FqlOvD7x2HhABaMXCTh9jwHclPA9j5YQdns.'))
        self.assertTrue(cc.hash_needs_update('$5$rounds=3001$QlFHHifXvpFX4PLs$/0ekt7lSs/lOikSerQ0M/1porEHxYq7W/2hdFpxA3fA'))
Beispiel #13
0
def _init_htpasswd_context():

    # start with schemes built into apache
    schemes = [
        # builtin support added in apache 2.4
        # (https://bz.apache.org/bugzilla/show_bug.cgi?id=49288)
        "bcrypt",

        # support not "builtin" to apache, instead it requires support through host's crypt().
        # adding them here to allow editing htpasswd under windows and then deploying under unix.
        "sha256_crypt",
        "sha512_crypt",
        "des_crypt",

        # apache default as of 2.2.18, and still default in 2.4
        "apr_md5_crypt",

        # NOTE: apache says ONLY intended for transitioning htpasswd <-> ldap
        "ldap_sha1",

        # NOTE: apache says ONLY supported on Windows, Netware, TPF
        "plaintext"
    ]

    # apache can verify anything supported by the native crypt(),
    # though htpasswd tool can only generate a limited set of hashes.
    # (this list may overlap w/ builtin apache schemes)
    schemes.extend(registry.get_supported_os_crypt_schemes())

    # hack to remove dups and sort into preferred order
    preferred = schemes[:3] + ["apr_md5_crypt"] + schemes
    schemes = sorted(set(schemes), key=preferred.index)

    # create context object
    return CryptContext(
        schemes=schemes,

        # NOTE: default will change to "portable" in passlib 2.0
        default=htpasswd_defaults['portable_apache_22'],

        # NOTE: bcrypt "2y" is required, "2b" isn't recognized by libapr (issue 95)
        bcrypt__ident="2y",
    )
    def assert_patched(self, context=None):
        """helper to ensure django HAS been patched, and is using specified config"""
        # make sure we're currently patched
        mod = sys.modules.get("passlib.ext.django.models")
        self.assertTrue(mod and mod._patched, "patch should have been enabled")

        # make sure only the expected objects have been patched
        for obj, attr, source, patched in self._iter_patch_candidates():
            if patched:
                self.assertTrue(source == "passlib.ext.django.models",
                                "obj=%r attr=%r should have been patched: %r" %
                                (obj, attr, source))
            else:
                self.assertFalse(source.startswith("passlib."),
                                "obj=%r attr=%r should not have been patched: %r" %
                                (obj, attr, source))

        # check context matches
        if context is not None:
            context = CryptContext._norm_source(context)
            self.assertEqual(mod.password_context.to_dict(resolve=True),
                             context.to_dict(resolve=True))
Beispiel #15
0
# TODO: update this to support everything in host_context (where available),
#       and note in the documentation that the default is no longer guaranteed to be portable
#       across platforms.
#       c.f. http://httpd.apache.org/docs/2.2/programs/htpasswd.html
htpasswd_context = CryptContext([
    # man page notes supported everywhere; is default on Windows, Netware, TPF
    "apr_md5_crypt",

    # [added in passlib 1.6.3]
    # apache requires host crypt() support; but can generate natively
    # (as of https://bz.apache.org/bugzilla/show_bug.cgi?id=49288)
    "bcrypt",

    # [added in passlib 1.6.3]
    # apache requires host crypt() support; and can't generate natively
    "sha256_crypt",
    "sha512_crypt",

    # man page notes apache does NOT support this on Windows, Netware, TPF
    "des_crypt",

    # man page notes intended only for transitioning htpasswd <-> ldap
    "ldap_sha1",

    # man page notes apache ONLY supports this on Windows, Netware, TPF
    "plaintext"
])

#: scheme that will be used when 'portable' is requested.
portable_scheme = "apr_md5_crypt"
    def test_00_constructor(self):
        """test constructor"""
        # create crypt context using handlers
        cc = CryptContext([hash.md5_crypt, hash.bsdi_crypt, hash.des_crypt])
        c, b, a = cc.policy.iter_handlers()
        self.assertIs(a, hash.des_crypt)
        self.assertIs(b, hash.bsdi_crypt)
        self.assertIs(c, hash.md5_crypt)

        # create context using names
        cc = CryptContext(["md5_crypt", "bsdi_crypt", "des_crypt"])
        c, b, a = cc.policy.iter_handlers()
        self.assertIs(a, hash.des_crypt)
        self.assertIs(b, hash.bsdi_crypt)
        self.assertIs(c, hash.md5_crypt)

        # policy kwd
        policy = cc.policy
        cc = CryptContext(policy=policy)
        self.assertEqual(cc.to_dict(), policy.to_dict())

        cc = CryptContext(policy=policy, default="bsdi_crypt")
        self.assertNotEqual(cc.to_dict(), policy.to_dict())
        self.assertEqual(
            cc.to_dict(),
            dict(schemes=["md5_crypt", "bsdi_crypt", "des_crypt"],
                 default="bsdi_crypt"))

        self.assertRaises(TypeError, setattr, cc, 'policy', None)
        self.assertRaises(TypeError, CryptContext, policy='x')
Beispiel #17
0
# pkg
from lib.passlib.context import CryptContext
from lib.passlib.exc import ExpectedTypeError
from lib.passlib.ext.django.utils import _PatchManager, hasher_to_passlib_name, \
                                     get_passlib_hasher, get_preset_config
from lib.passlib.utils.compat import callable, unicode, bytes
# local
__all__ = ["password_context"]

#=============================================================================
# global attrs
#=============================================================================

# the context object which this patches contrib.auth to use for password hashing.
# configuration controlled by ``settings.PASSLIB_CONFIG``.
password_context = CryptContext()


# function mapping User objects -> passlib user category.
# may be overridden via ``settings.PASSLIB_GET_CATEGORY``.
def _get_category(user):
    """default get_category() implementation"""
    if user.is_superuser:
        return "superuser"
    elif user.is_staff:
        return "staff"
    else:
        return None


# object used to track state of patches applied to django.
 def context(self):
     return CryptContext._norm_source(self.config)