diff options
| author | Eli Collins <elic@assurancetechnologies.com> | 2011-03-15 01:40:03 -0400 |
|---|---|---|
| committer | Eli Collins <elic@assurancetechnologies.com> | 2011-03-15 01:40:03 -0400 |
| commit | 2d2f1d0f53e79945288db8d05baf6a4cf07fdd66 (patch) | |
| tree | 48e6c58decb3a42245af5d0465083fa4e6df879a | |
| parent | 1d0a05a785795bd85708d49c7dfa27fbaf4a03c7 (diff) | |
| download | passlib-2d2f1d0f53e79945288db8d05baf6a4cf07fdd66.tar.gz | |
added ldap's {MD5} {SHA} {SMD5} {SSHA} formats (still needs docs & UTs)
| -rw-r--r-- | passlib/base.py | 4 | ||||
| -rw-r--r-- | passlib/drivers/ldap.py | 122 |
2 files changed, 126 insertions, 0 deletions
diff --git a/passlib/base.py b/passlib/base.py index fc8e8ee..76935bb 100644 --- a/passlib/base.py +++ b/passlib/base.py @@ -98,6 +98,10 @@ _driver_locations = { "hex_sha1": ("passlib.drivers.digests", "hex_sha1"), "hex_sha256": ("passlib.drivers.digests", "hex_sha256"), "hex_sha512": ("passlib.drivers.digests", "hex_sha512"), + "ldap_md5": ("passlib.drivers.ldap", "ldap_md5"), + "ldap_sha1": ("passlib.drivers.ldap", "ldap_sha1"), + "ldap_salted_md5": ("passlib.drivers.ldap", "ldap_salted_md5"), + "ldap_salted_sha1": ("passlib.drivers.ldap", "ldap_salted_sha1"), "md5_crypt": ("passlib.drivers.md5_crypt", "md5_crypt"), "mysql323": ("passlib.drivers.mysql", "mysql323"), "mysql41": ("passlib.drivers.mysql", "mysql41"), diff --git a/passlib/drivers/ldap.py b/passlib/drivers/ldap.py new file mode 100644 index 0000000..f242567 --- /dev/null +++ b/passlib/drivers/ldap.py @@ -0,0 +1,122 @@ +"""passlib.drivers.digests - plain hash digests +""" +#========================================================= +#imports +#========================================================= +#core +from hashlib import md5, sha1 +import logging; log = logging.getLogger(__name__) +import re +from warnings import warn +#site +#libs +from passlib.utils.drivers import ExtHash, BaseHash +#pkg +#local +__all__ = [ + "ldap_md5", + "ldap_sha1", + "ldap_salted_md5", + "ldap_salted_sha1", +] + +#========================================================= +#ldap helpers +#========================================================= +#reference - http://www.openldap.org/doc/admin24/security.html + +class _Base64DigestHelper(BaseHash): + "helper for ldap_md5 / ldap_sha1" + + #_ident + #_hash + #_pat + + @classmethod + def identify(cls, hash): + return bool(hash and cls._pat.match(hash)) + + @classmethod + def genhash(cls, secret, hash): + if secret is None: + raise TypeError, "no secret provided" + if isinstance(secret, unicode): + secret = secret.encode("utf-8") + if hash is not None and not cls.identify(hash): + raise ValueError, "not a %s hash" % (cls.name,) + return cls._ident + cls._hash(secret).digest().encode("base64").strip() + +class _SaltedBase64DigestHelper(ExtHash): + "helper for ldap_salted_md5 / ldap_salted_sha1" + setting_kwds = ("salt",) + + #_ident + #_hash + #_pat + #_default_chk + min_salt_chars = max_salt_chars = 4 + salt_charset = ''.join(chr(x) for x in xrange(256)) + + @classmethod + def identify(cls, hash): + return bool(hash and cls._pat.match(hash)) + + @classmethod + def from_string(cls, hash): + if not hash: + raise ValueError, "no hash specified" + m = cls._pat.match(hash) + if not m: + raise ValueError, "not a %s hash" % (cls.name,) + tmp = m.group("tmp").decode("base64") + chk, salt = tmp[:-4], tmp[-4:] + return cls(checksum=chk, salt=salt, strict=True) + + def to_string(self): + return self._ident + ((self.checksum or self._default_chk) + self.salt).encode("base64").strip() + + def calc_checksum(self, secret): + if secret is None: + raise TypeError, "no secret provided" + if isinstance(secret, unicode): + secret = secret.encode("utf-8") + return self._hash(secret + self.salt).digest() + +#========================================================= +#implementations +#========================================================= +class ldap_md5(_Base64DigestHelper): + name = "ldap_md5" + setting_kwds = () + + _ident = "{MD5}" + _hash = hashlib.md5 + _pat = re.compile(r"^\{MD5\}(?P<chk>[+/a-zA-Z0-9]{22}==)$") + +class ldap_sha1(_Base64DigestHelper): + name = "ldap_sha1" + setting_kwds = () + + _ident = "{SHA}" + _hash = hashlib.sha1 + _pat = re.compile(r"^\{SHA\}(?P<chk>[+/a-zA-Z0-9]{27}=)$") + +class ldap_salted_md5(_SaltedBase64DigestHelper): + name = "ldap_salted_md5" + _ident = "{SMD5}" + _hash = hashlib.md5 + _pat = re.compile(r"^\{SMD5\}(?P<tmp>[+/a-zA-Z0-9]{27}=)$") + _default_chk = '\x00' * 16 + +class ldap_salted_sha1(_SaltedBase64DigestHelper): + name = "ldap_salted_sha1" + _ident = "{SSHA}" + _hash = hashlib.sha1 + _pat = re.compile(r"^\{SSHA\}(?P<tmp>[+/a-zA-Z0-9]{32})$") + _default_chk = '\x00' * 20 + +#TODO: support {CRYPT} somehow (adapt per host?) + +#========================================================= +#eof +#========================================================= |
