You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					360 lines
				
				13 KiB
			
		
		
			
		
	
	
					360 lines
				
				13 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								"""passlib.handlers.digests - plain hash digests
							 | 
						||
| 
								 | 
							
								"""
							 | 
						||
| 
								 | 
							
								#=============================================================================
							 | 
						||
| 
								 | 
							
								# imports
							 | 
						||
| 
								 | 
							
								#=============================================================================
							 | 
						||
| 
								 | 
							
								# core
							 | 
						||
| 
								 | 
							
								from base64 import b64encode, b64decode
							 | 
						||
| 
								 | 
							
								from hashlib import md5, sha1, sha256, sha512
							 | 
						||
| 
								 | 
							
								import logging; log = logging.getLogger(__name__)
							 | 
						||
| 
								 | 
							
								import re
							 | 
						||
| 
								 | 
							
								# site
							 | 
						||
| 
								 | 
							
								# pkg
							 | 
						||
| 
								 | 
							
								from passlib.handlers.misc import plaintext
							 | 
						||
| 
								 | 
							
								from passlib.utils import unix_crypt_schemes, to_unicode
							 | 
						||
| 
								 | 
							
								from passlib.utils.compat import uascii_to_str, unicode, u
							 | 
						||
| 
								 | 
							
								from passlib.utils.decor import classproperty
							 | 
						||
| 
								 | 
							
								import passlib.utils.handlers as uh
							 | 
						||
| 
								 | 
							
								# local
							 | 
						||
| 
								 | 
							
								__all__ = [
							 | 
						||
| 
								 | 
							
								    "ldap_plaintext",
							 | 
						||
| 
								 | 
							
								    "ldap_md5",
							 | 
						||
| 
								 | 
							
								    "ldap_sha1",
							 | 
						||
| 
								 | 
							
								    "ldap_salted_md5",
							 | 
						||
| 
								 | 
							
								    "ldap_salted_sha1",
							 | 
						||
| 
								 | 
							
								    "ldap_salted_sha256",
							 | 
						||
| 
								 | 
							
								    "ldap_salted_sha512",
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    ##"get_active_ldap_crypt_schemes",
							 | 
						||
| 
								 | 
							
								    "ldap_des_crypt",
							 | 
						||
| 
								 | 
							
								    "ldap_bsdi_crypt",
							 | 
						||
| 
								 | 
							
								    "ldap_md5_crypt",
							 | 
						||
| 
								 | 
							
								    "ldap_sha1_crypt",
							 | 
						||
| 
								 | 
							
								    "ldap_bcrypt",
							 | 
						||
| 
								 | 
							
								    "ldap_sha256_crypt",
							 | 
						||
| 
								 | 
							
								    "ldap_sha512_crypt",
							 | 
						||
| 
								 | 
							
								]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#=============================================================================
							 | 
						||
| 
								 | 
							
								# ldap helpers
							 | 
						||
| 
								 | 
							
								#=============================================================================
							 | 
						||
| 
								 | 
							
								class _Base64DigestHelper(uh.StaticHandler):
							 | 
						||
| 
								 | 
							
								    """helper for ldap_md5 / ldap_sha1"""
							 | 
						||
| 
								 | 
							
								    # XXX: could combine this with hex digests in digests.py
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    ident = None # required - prefix identifier
							 | 
						||
| 
								 | 
							
								    _hash_func = None # required - hash function
							 | 
						||
| 
								 | 
							
								    _hash_regex = None # required - regexp to recognize hash
							 | 
						||
| 
								 | 
							
								    checksum_chars = uh.PADDED_BASE64_CHARS
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @classproperty
							 | 
						||
| 
								 | 
							
								    def _hash_prefix(cls):
							 | 
						||
| 
								 | 
							
								        """tell StaticHandler to strip ident from checksum"""
							 | 
						||
| 
								 | 
							
								        return cls.ident
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def _calc_checksum(self, secret):
							 | 
						||
| 
								 | 
							
								        if isinstance(secret, unicode):
							 | 
						||
| 
								 | 
							
								            secret = secret.encode("utf-8")
							 | 
						||
| 
								 | 
							
								        chk = self._hash_func(secret).digest()
							 | 
						||
| 
								 | 
							
								        return b64encode(chk).decode("ascii")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class _SaltedBase64DigestHelper(uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHandler):
							 | 
						||
| 
								 | 
							
								    """helper for ldap_salted_md5 / ldap_salted_sha1"""
							 | 
						||
| 
								 | 
							
								    setting_kwds = ("salt", "salt_size")
							 | 
						||
| 
								 | 
							
								    checksum_chars = uh.PADDED_BASE64_CHARS
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    ident = None # required - prefix identifier
							 | 
						||
| 
								 | 
							
								    _hash_func = None # required - hash function
							 | 
						||
| 
								 | 
							
								    _hash_regex = None # required - regexp to recognize hash
							 | 
						||
| 
								 | 
							
								    min_salt_size = max_salt_size = 4
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # NOTE: openldap implementation uses 4 byte salt,
							 | 
						||
| 
								 | 
							
								    # but it's been reported (issue 30) that some servers use larger salts.
							 | 
						||
| 
								 | 
							
								    # the semi-related rfc3112 recommends support for up to 16 byte salts.
							 | 
						||
| 
								 | 
							
								    min_salt_size = 4
							 | 
						||
| 
								 | 
							
								    default_salt_size = 4
							 | 
						||
| 
								 | 
							
								    max_salt_size = 16
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @classmethod
							 | 
						||
| 
								 | 
							
								    def from_string(cls, hash):
							 | 
						||
| 
								 | 
							
								        hash = to_unicode(hash, "ascii", "hash")
							 | 
						||
| 
								 | 
							
								        m = cls._hash_regex.match(hash)
							 | 
						||
| 
								 | 
							
								        if not m:
							 | 
						||
| 
								 | 
							
								            raise uh.exc.InvalidHashError(cls)
							 | 
						||
| 
								 | 
							
								        try:
							 | 
						||
| 
								 | 
							
								            data = b64decode(m.group("tmp").encode("ascii"))
							 | 
						||
| 
								 | 
							
								        except TypeError:
							 | 
						||
| 
								 | 
							
								            raise uh.exc.MalformedHashError(cls)
							 | 
						||
| 
								 | 
							
								        cs = cls.checksum_size
							 | 
						||
| 
								 | 
							
								        assert cs
							 | 
						||
| 
								 | 
							
								        return cls(checksum=data[:cs], salt=data[cs:])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def to_string(self):
							 | 
						||
| 
								 | 
							
								        data = self.checksum + self.salt
							 | 
						||
| 
								 | 
							
								        hash = self.ident + b64encode(data).decode("ascii")
							 | 
						||
| 
								 | 
							
								        return uascii_to_str(hash)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def _calc_checksum(self, secret):
							 | 
						||
| 
								 | 
							
								        if isinstance(secret, unicode):
							 | 
						||
| 
								 | 
							
								            secret = secret.encode("utf-8")
							 | 
						||
| 
								 | 
							
								        return self._hash_func(secret + self.salt).digest()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#=============================================================================
							 | 
						||
| 
								 | 
							
								# implementations
							 | 
						||
| 
								 | 
							
								#=============================================================================
							 | 
						||
| 
								 | 
							
								class ldap_md5(_Base64DigestHelper):
							 | 
						||
| 
								 | 
							
								    """This class stores passwords using LDAP's plain MD5 format, and follows the :ref:`password-hash-api`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    The :meth:`~passlib.ifc.PasswordHash.hash` and :meth:`~passlib.ifc.PasswordHash.genconfig` methods have no optional keywords.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    name = "ldap_md5"
							 | 
						||
| 
								 | 
							
								    ident = u("{MD5}")
							 | 
						||
| 
								 | 
							
								    _hash_func = md5
							 | 
						||
| 
								 | 
							
								    _hash_regex = re.compile(u(r"^\{MD5\}(?P<chk>[+/a-zA-Z0-9]{22}==)$"))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class ldap_sha1(_Base64DigestHelper):
							 | 
						||
| 
								 | 
							
								    """This class stores passwords using LDAP's plain SHA1 format, and follows the :ref:`password-hash-api`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    The :meth:`~passlib.ifc.PasswordHash.hash` and :meth:`~passlib.ifc.PasswordHash.genconfig` methods have no optional keywords.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    name = "ldap_sha1"
							 | 
						||
| 
								 | 
							
								    ident = u("{SHA}")
							 | 
						||
| 
								 | 
							
								    _hash_func = sha1
							 | 
						||
| 
								 | 
							
								    _hash_regex = re.compile(u(r"^\{SHA\}(?P<chk>[+/a-zA-Z0-9]{27}=)$"))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class ldap_salted_md5(_SaltedBase64DigestHelper):
							 | 
						||
| 
								 | 
							
								    """This class stores passwords using LDAP's salted MD5 format, and follows the :ref:`password-hash-api`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    It supports a 4-16 byte salt.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    The :meth:`~passlib.ifc.PasswordHash.using` method accepts the following optional keywords:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    :type salt: bytes
							 | 
						||
| 
								 | 
							
								    :param salt:
							 | 
						||
| 
								 | 
							
								        Optional salt string.
							 | 
						||
| 
								 | 
							
								        If not specified, one will be autogenerated (this is recommended).
							 | 
						||
| 
								 | 
							
								        If specified, it may be any 4-16 byte string.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    :type salt_size: int
							 | 
						||
| 
								 | 
							
								    :param salt_size:
							 | 
						||
| 
								 | 
							
								        Optional number of bytes to use when autogenerating new salts.
							 | 
						||
| 
								 | 
							
								        Defaults to 4 bytes for compatibility with the LDAP spec,
							 | 
						||
| 
								 | 
							
								        but some systems use larger salts, and Passlib supports
							 | 
						||
| 
								 | 
							
								        any value between 4-16.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    :type relaxed: bool
							 | 
						||
| 
								 | 
							
								    :param relaxed:
							 | 
						||
| 
								 | 
							
								        By default, providing an invalid value for one of the other
							 | 
						||
| 
								 | 
							
								        keywords will result in a :exc:`ValueError`. If ``relaxed=True``,
							 | 
						||
| 
								 | 
							
								        and the error can be corrected, a :exc:`~passlib.exc.PasslibHashWarning`
							 | 
						||
| 
								 | 
							
								        will be issued instead. Correctable errors include
							 | 
						||
| 
								 | 
							
								        ``salt`` strings that are too long.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        .. versionadded:: 1.6
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    .. versionchanged:: 1.6
							 | 
						||
| 
								 | 
							
								        This format now supports variable length salts, instead of a fix 4 bytes.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    name = "ldap_salted_md5"
							 | 
						||
| 
								 | 
							
								    ident = u("{SMD5}")
							 | 
						||
| 
								 | 
							
								    checksum_size = 16
							 | 
						||
| 
								 | 
							
								    _hash_func = md5
							 | 
						||
| 
								 | 
							
								    _hash_regex = re.compile(u(r"^\{SMD5\}(?P<tmp>[+/a-zA-Z0-9]{27,}={0,2})$"))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class ldap_salted_sha1(_SaltedBase64DigestHelper):
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    This class stores passwords using LDAP's "Salted SHA1" format,
							 | 
						||
| 
								 | 
							
								    and follows the :ref:`password-hash-api`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    It supports a 4-16 byte salt.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    The :meth:`~passlib.ifc.PasswordHash.using` method accepts the following optional keywords:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    :type salt: bytes
							 | 
						||
| 
								 | 
							
								    :param salt:
							 | 
						||
| 
								 | 
							
								        Optional salt string.
							 | 
						||
| 
								 | 
							
								        If not specified, one will be autogenerated (this is recommended).
							 | 
						||
| 
								 | 
							
								        If specified, it may be any 4-16 byte string.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    :type salt_size: int
							 | 
						||
| 
								 | 
							
								    :param salt_size:
							 | 
						||
| 
								 | 
							
								        Optional number of bytes to use when autogenerating new salts.
							 | 
						||
| 
								 | 
							
								        Defaults to 4 bytes for compatibility with the LDAP spec,
							 | 
						||
| 
								 | 
							
								        but some systems use larger salts, and Passlib supports
							 | 
						||
| 
								 | 
							
								        any value between 4-16.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    :type relaxed: bool
							 | 
						||
| 
								 | 
							
								    :param relaxed:
							 | 
						||
| 
								 | 
							
								        By default, providing an invalid value for one of the other
							 | 
						||
| 
								 | 
							
								        keywords will result in a :exc:`ValueError`. If ``relaxed=True``,
							 | 
						||
| 
								 | 
							
								        and the error can be corrected, a :exc:`~passlib.exc.PasslibHashWarning`
							 | 
						||
| 
								 | 
							
								        will be issued instead. Correctable errors include
							 | 
						||
| 
								 | 
							
								        ``salt`` strings that are too long.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        .. versionadded:: 1.6
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    .. versionchanged:: 1.6
							 | 
						||
| 
								 | 
							
								        This format now supports variable length salts, instead of a fix 4 bytes.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    name = "ldap_salted_sha1"
							 | 
						||
| 
								 | 
							
								    ident = u("{SSHA}")
							 | 
						||
| 
								 | 
							
								    checksum_size = 20
							 | 
						||
| 
								 | 
							
								    _hash_func = sha1
							 | 
						||
| 
								 | 
							
								    # NOTE: 32 = ceil((20 + 4) * 4/3)
							 | 
						||
| 
								 | 
							
								    _hash_regex = re.compile(u(r"^\{SSHA\}(?P<tmp>[+/a-zA-Z0-9]{32,}={0,2})$"))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class ldap_salted_sha256(_SaltedBase64DigestHelper):
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    This class stores passwords using LDAP's "Salted SHA2-256" format,
							 | 
						||
| 
								 | 
							
								    and follows the :ref:`password-hash-api`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    It supports a 4-16 byte salt.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    The :meth:`~passlib.ifc.PasswordHash.using` method accepts the following optional keywords:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    :type salt: bytes
							 | 
						||
| 
								 | 
							
								    :param salt:
							 | 
						||
| 
								 | 
							
								        Optional salt string.
							 | 
						||
| 
								 | 
							
								        If not specified, one will be autogenerated (this is recommended).
							 | 
						||
| 
								 | 
							
								        If specified, it may be any 4-16 byte string.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    :type salt_size: int
							 | 
						||
| 
								 | 
							
								    :param salt_size:
							 | 
						||
| 
								 | 
							
								        Optional number of bytes to use when autogenerating new salts.
							 | 
						||
| 
								 | 
							
								        Defaults to 8 bytes for compatibility with the LDAP spec,
							 | 
						||
| 
								 | 
							
								        but Passlib supports any value between 4-16.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    :type relaxed: bool
							 | 
						||
| 
								 | 
							
								    :param relaxed:
							 | 
						||
| 
								 | 
							
								        By default, providing an invalid value for one of the other
							 | 
						||
| 
								 | 
							
								        keywords will result in a :exc:`ValueError`. If ``relaxed=True``,
							 | 
						||
| 
								 | 
							
								        and the error can be corrected, a :exc:`~passlib.exc.PasslibHashWarning`
							 | 
						||
| 
								 | 
							
								        will be issued instead. Correctable errors include
							 | 
						||
| 
								 | 
							
								        ``salt`` strings that are too long.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    .. versionadded:: 1.7.3
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    name = "ldap_salted_sha256"
							 | 
						||
| 
								 | 
							
								    ident = u("{SSHA256}")
							 | 
						||
| 
								 | 
							
								    checksum_size = 32
							 | 
						||
| 
								 | 
							
								    default_salt_size = 8
							 | 
						||
| 
								 | 
							
								    _hash_func = sha256
							 | 
						||
| 
								 | 
							
								    # NOTE: 48 = ceil((32 + 4) * 4/3)
							 | 
						||
| 
								 | 
							
								    _hash_regex = re.compile(u(r"^\{SSHA256\}(?P<tmp>[+/a-zA-Z0-9]{48,}={0,2})$"))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class ldap_salted_sha512(_SaltedBase64DigestHelper):
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    This class stores passwords using LDAP's "Salted SHA2-512" format,
							 | 
						||
| 
								 | 
							
								    and follows the :ref:`password-hash-api`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    It supports a 4-16 byte salt.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    The :meth:`~passlib.ifc.PasswordHash.using` method accepts the following optional keywords:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    :type salt: bytes
							 | 
						||
| 
								 | 
							
								    :param salt:
							 | 
						||
| 
								 | 
							
								        Optional salt string.
							 | 
						||
| 
								 | 
							
								        If not specified, one will be autogenerated (this is recommended).
							 | 
						||
| 
								 | 
							
								        If specified, it may be any 4-16 byte string.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    :type salt_size: int
							 | 
						||
| 
								 | 
							
								    :param salt_size:
							 | 
						||
| 
								 | 
							
								        Optional number of bytes to use when autogenerating new salts.
							 | 
						||
| 
								 | 
							
								        Defaults to 8 bytes for compatibility with the LDAP spec,
							 | 
						||
| 
								 | 
							
								        but Passlib supports any value between 4-16.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    :type relaxed: bool
							 | 
						||
| 
								 | 
							
								    :param relaxed:
							 | 
						||
| 
								 | 
							
								        By default, providing an invalid value for one of the other
							 | 
						||
| 
								 | 
							
								        keywords will result in a :exc:`ValueError`. If ``relaxed=True``,
							 | 
						||
| 
								 | 
							
								        and the error can be corrected, a :exc:`~passlib.exc.PasslibHashWarning`
							 | 
						||
| 
								 | 
							
								        will be issued instead. Correctable errors include
							 | 
						||
| 
								 | 
							
								        ``salt`` strings that are too long.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    .. versionadded:: 1.7.3
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    name = "ldap_salted_sha512"
							 | 
						||
| 
								 | 
							
								    ident = u("{SSHA512}")
							 | 
						||
| 
								 | 
							
								    checksum_size = 64
							 | 
						||
| 
								 | 
							
								    default_salt_size = 8
							 | 
						||
| 
								 | 
							
								    _hash_func = sha512
							 | 
						||
| 
								 | 
							
								    # NOTE: 91 = ceil((64 + 4) * 4/3)
							 | 
						||
| 
								 | 
							
								    _hash_regex = re.compile(u(r"^\{SSHA512\}(?P<tmp>[+/a-zA-Z0-9]{91,}={0,2})$"))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class ldap_plaintext(plaintext):
							 | 
						||
| 
								 | 
							
								    """This class stores passwords in plaintext, and follows the :ref:`password-hash-api`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    This class acts much like the generic :class:`!passlib.hash.plaintext` handler,
							 | 
						||
| 
								 | 
							
								    except that it will identify a hash only if it does NOT begin with the ``{XXX}`` identifier prefix
							 | 
						||
| 
								 | 
							
								    used by RFC2307 passwords.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    The :meth:`~passlib.ifc.PasswordHash.hash`, :meth:`~passlib.ifc.PasswordHash.genhash`, and :meth:`~passlib.ifc.PasswordHash.verify` methods all require the
							 | 
						||
| 
								 | 
							
								    following additional contextual keyword:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    :type encoding: str
							 | 
						||
| 
								 | 
							
								    :param encoding:
							 | 
						||
| 
								 | 
							
								        This controls the character encoding to use (defaults to ``utf-8``).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        This encoding will be used to encode :class:`!unicode` passwords
							 | 
						||
| 
								 | 
							
								        under Python 2, and decode :class:`!bytes` hashes under Python 3.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    .. versionchanged:: 1.6
							 | 
						||
| 
								 | 
							
								        The ``encoding`` keyword was added.
							 | 
						||
| 
								 | 
							
								    """
							 | 
						||
| 
								 | 
							
								    # NOTE: this subclasses plaintext, since all it does differently
							 | 
						||
| 
								 | 
							
								    # is override identify()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    name = "ldap_plaintext"
							 | 
						||
| 
								 | 
							
								    _2307_pat = re.compile(u(r"^\{\w+\}.*$"))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @uh.deprecated_method(deprecated="1.7", removed="2.0")
							 | 
						||
| 
								 | 
							
								    @classmethod
							 | 
						||
| 
								 | 
							
								    def genconfig(cls):
							 | 
						||
| 
								 | 
							
								        # Overridding plaintext.genconfig() since it returns "",
							 | 
						||
| 
								 | 
							
								        # but have to return non-empty value due to identify() below
							 | 
						||
| 
								 | 
							
								        return "!"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @classmethod
							 | 
						||
| 
								 | 
							
								    def identify(cls, hash):
							 | 
						||
| 
								 | 
							
								        # NOTE: identifies all strings EXCEPT those with {XXX} prefix
							 | 
						||
| 
								 | 
							
								        hash = uh.to_unicode_for_identify(hash)
							 | 
						||
| 
								 | 
							
								        return bool(hash) and cls._2307_pat.match(hash) is None
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#=============================================================================
							 | 
						||
| 
								 | 
							
								# {CRYPT} wrappers
							 | 
						||
| 
								 | 
							
								# the following are wrappers around the base crypt algorithms,
							 | 
						||
| 
								 | 
							
								# which add the ldap required {CRYPT} prefix
							 | 
						||
| 
								 | 
							
								#=============================================================================
							 | 
						||
| 
								 | 
							
								ldap_crypt_schemes = [ 'ldap_' + name for name in unix_crypt_schemes ]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								def _init_ldap_crypt_handlers():
							 | 
						||
| 
								 | 
							
								    # NOTE: I don't like to implicitly modify globals() like this,
							 | 
						||
| 
								 | 
							
								    #       but don't want to write out all these handlers out either :)
							 | 
						||
| 
								 | 
							
								    g = globals()
							 | 
						||
| 
								 | 
							
								    for wname in unix_crypt_schemes:
							 | 
						||
| 
								 | 
							
								        name = 'ldap_' + wname
							 | 
						||
| 
								 | 
							
								        g[name] = uh.PrefixWrapper(name, wname, prefix=u("{CRYPT}"), lazy=True)
							 | 
						||
| 
								 | 
							
								    del g
							 | 
						||
| 
								 | 
							
								_init_ldap_crypt_handlers()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								##_lcn_host = None
							 | 
						||
| 
								 | 
							
								##def get_host_ldap_crypt_schemes():
							 | 
						||
| 
								 | 
							
								##    global _lcn_host
							 | 
						||
| 
								 | 
							
								##    if _lcn_host is None:
							 | 
						||
| 
								 | 
							
								##        from passlib.hosts import host_context
							 | 
						||
| 
								 | 
							
								##        schemes = host_context.schemes()
							 | 
						||
| 
								 | 
							
								##        _lcn_host = [
							 | 
						||
| 
								 | 
							
								##            "ldap_" + name
							 | 
						||
| 
								 | 
							
								##            for name in unix_crypt_names
							 | 
						||
| 
								 | 
							
								##            if name in schemes
							 | 
						||
| 
								 | 
							
								##        ]
							 | 
						||
| 
								 | 
							
								##    return _lcn_host
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#=============================================================================
							 | 
						||
| 
								 | 
							
								# eof
							 | 
						||
| 
								 | 
							
								#=============================================================================
							 |