mirror of
https://gitlab.com/MoonTestUse1/AdministrationItDepartmens.git
synced 2025-08-14 00:25:46 +02:00
Initial commit
This commit is contained in:
269
venv/Lib/site-packages/passlib/handlers/misc.py
Normal file
269
venv/Lib/site-packages/passlib/handlers/misc.py
Normal file
@@ -0,0 +1,269 @@
|
||||
"""passlib.handlers.misc - misc generic handlers
|
||||
"""
|
||||
#=============================================================================
|
||||
# imports
|
||||
#=============================================================================
|
||||
# core
|
||||
import sys
|
||||
import logging; log = logging.getLogger(__name__)
|
||||
from warnings import warn
|
||||
# site
|
||||
# pkg
|
||||
from passlib.utils import to_native_str, str_consteq
|
||||
from passlib.utils.compat import unicode, u, unicode_or_bytes_types
|
||||
import passlib.utils.handlers as uh
|
||||
# local
|
||||
__all__ = [
|
||||
"unix_disabled",
|
||||
"unix_fallback",
|
||||
"plaintext",
|
||||
]
|
||||
|
||||
#=============================================================================
|
||||
# handler
|
||||
#=============================================================================
|
||||
class unix_fallback(uh.ifc.DisabledHash, uh.StaticHandler):
|
||||
"""This class provides the fallback behavior for unix shadow files, and follows the :ref:`password-hash-api`.
|
||||
|
||||
This class does not implement a hash, but instead provides fallback
|
||||
behavior as found in /etc/shadow on most unix variants.
|
||||
If used, should be the last scheme in the context.
|
||||
|
||||
* this class will positively identify all hash strings.
|
||||
* for security, passwords will always hash to ``!``.
|
||||
* it rejects all passwords if the hash is NOT an empty string (``!`` or ``*`` are frequently used).
|
||||
* by default it rejects all passwords if the hash is an empty string,
|
||||
but if ``enable_wildcard=True`` is passed to verify(),
|
||||
all passwords will be allowed through if the hash is an empty string.
|
||||
|
||||
.. deprecated:: 1.6
|
||||
This has been deprecated due to its "wildcard" feature,
|
||||
and will be removed in Passlib 1.8. Use :class:`unix_disabled` instead.
|
||||
"""
|
||||
name = "unix_fallback"
|
||||
context_kwds = ("enable_wildcard",)
|
||||
|
||||
@classmethod
|
||||
def identify(cls, hash):
|
||||
if isinstance(hash, unicode_or_bytes_types):
|
||||
return True
|
||||
else:
|
||||
raise uh.exc.ExpectedStringError(hash, "hash")
|
||||
|
||||
def __init__(self, enable_wildcard=False, **kwds):
|
||||
warn("'unix_fallback' is deprecated, "
|
||||
"and will be removed in Passlib 1.8; "
|
||||
"please use 'unix_disabled' instead.",
|
||||
DeprecationWarning)
|
||||
super(unix_fallback, self).__init__(**kwds)
|
||||
self.enable_wildcard = enable_wildcard
|
||||
|
||||
def _calc_checksum(self, secret):
|
||||
if self.checksum:
|
||||
# NOTE: hash will generally be "!", but we want to preserve
|
||||
# it in case it's something else, like "*".
|
||||
return self.checksum
|
||||
else:
|
||||
return u("!")
|
||||
|
||||
@classmethod
|
||||
def verify(cls, secret, hash, enable_wildcard=False):
|
||||
uh.validate_secret(secret)
|
||||
if not isinstance(hash, unicode_or_bytes_types):
|
||||
raise uh.exc.ExpectedStringError(hash, "hash")
|
||||
elif hash:
|
||||
return False
|
||||
else:
|
||||
return enable_wildcard
|
||||
|
||||
_MARKER_CHARS = u("*!")
|
||||
_MARKER_BYTES = b"*!"
|
||||
|
||||
class unix_disabled(uh.ifc.DisabledHash, uh.MinimalHandler):
|
||||
"""This class provides disabled password behavior for unix shadow files,
|
||||
and follows the :ref:`password-hash-api`.
|
||||
|
||||
This class does not implement a hash, but instead matches the "disabled account"
|
||||
strings found in ``/etc/shadow`` on most Unix variants. "encrypting" a password
|
||||
will simply return the disabled account marker. It will reject all passwords,
|
||||
no matter the hash string. The :meth:`~passlib.ifc.PasswordHash.hash`
|
||||
method supports one optional keyword:
|
||||
|
||||
:type marker: str
|
||||
:param marker:
|
||||
Optional marker string which overrides the platform default
|
||||
used to indicate a disabled account.
|
||||
|
||||
If not specified, this will default to ``"*"`` on BSD systems,
|
||||
and use the Linux default ``"!"`` for all other platforms.
|
||||
(:attr:`!unix_disabled.default_marker` will contain the default value)
|
||||
|
||||
.. versionadded:: 1.6
|
||||
This class was added as a replacement for the now-deprecated
|
||||
:class:`unix_fallback` class, which had some undesirable features.
|
||||
"""
|
||||
name = "unix_disabled"
|
||||
setting_kwds = ("marker",)
|
||||
context_kwds = ()
|
||||
|
||||
_disable_prefixes = tuple(str(_MARKER_CHARS))
|
||||
|
||||
# TODO: rename attr to 'marker'...
|
||||
if 'bsd' in sys.platform: # pragma: no cover -- runtime detection
|
||||
default_marker = u("*")
|
||||
else:
|
||||
# use the linux default for other systems
|
||||
# (glibc also supports adding old hash after the marker
|
||||
# so it can be restored later).
|
||||
default_marker = u("!")
|
||||
|
||||
@classmethod
|
||||
def using(cls, marker=None, **kwds):
|
||||
subcls = super(unix_disabled, cls).using(**kwds)
|
||||
if marker is not None:
|
||||
if not cls.identify(marker):
|
||||
raise ValueError("invalid marker: %r" % marker)
|
||||
subcls.default_marker = marker
|
||||
return subcls
|
||||
|
||||
@classmethod
|
||||
def identify(cls, hash):
|
||||
# NOTE: technically, anything in the /etc/shadow password field
|
||||
# which isn't valid crypt() output counts as "disabled".
|
||||
# but that's rather ambiguous, and it's hard to predict what
|
||||
# valid output is for unknown crypt() implementations.
|
||||
# so to be on the safe side, we only match things *known*
|
||||
# to be disabled field indicators, and will add others
|
||||
# as they are found. things beginning w/ "$" should *never* match.
|
||||
#
|
||||
# things currently matched:
|
||||
# * linux uses "!"
|
||||
# * bsd uses "*"
|
||||
# * linux may use "!" + hash to disable but preserve original hash
|
||||
# * linux counts empty string as "any password";
|
||||
# this code recognizes it, but treats it the same as "!"
|
||||
if isinstance(hash, unicode):
|
||||
start = _MARKER_CHARS
|
||||
elif isinstance(hash, bytes):
|
||||
start = _MARKER_BYTES
|
||||
else:
|
||||
raise uh.exc.ExpectedStringError(hash, "hash")
|
||||
return not hash or hash[0] in start
|
||||
|
||||
@classmethod
|
||||
def verify(cls, secret, hash):
|
||||
uh.validate_secret(secret)
|
||||
if not cls.identify(hash): # handles typecheck
|
||||
raise uh.exc.InvalidHashError(cls)
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def hash(cls, secret, **kwds):
|
||||
if kwds:
|
||||
uh.warn_hash_settings_deprecation(cls, kwds)
|
||||
return cls.using(**kwds).hash(secret)
|
||||
uh.validate_secret(secret)
|
||||
marker = cls.default_marker
|
||||
assert marker and cls.identify(marker)
|
||||
return to_native_str(marker, param="marker")
|
||||
|
||||
@uh.deprecated_method(deprecated="1.7", removed="2.0")
|
||||
@classmethod
|
||||
def genhash(cls, secret, config, marker=None):
|
||||
if not cls.identify(config):
|
||||
raise uh.exc.InvalidHashError(cls)
|
||||
elif config:
|
||||
# preserve the existing str,since it might contain a disabled password hash ("!" + hash)
|
||||
uh.validate_secret(secret)
|
||||
return to_native_str(config, param="config")
|
||||
else:
|
||||
if marker is not None:
|
||||
cls = cls.using(marker=marker)
|
||||
return cls.hash(secret)
|
||||
|
||||
@classmethod
|
||||
def disable(cls, hash=None):
|
||||
out = cls.hash("")
|
||||
if hash is not None:
|
||||
hash = to_native_str(hash, param="hash")
|
||||
if cls.identify(hash):
|
||||
# extract original hash, so that we normalize marker
|
||||
hash = cls.enable(hash)
|
||||
if hash:
|
||||
out += hash
|
||||
return out
|
||||
|
||||
@classmethod
|
||||
def enable(cls, hash):
|
||||
hash = to_native_str(hash, param="hash")
|
||||
for prefix in cls._disable_prefixes:
|
||||
if hash.startswith(prefix):
|
||||
orig = hash[len(prefix):]
|
||||
if orig:
|
||||
return orig
|
||||
else:
|
||||
raise ValueError("cannot restore original hash")
|
||||
raise uh.exc.InvalidHashError(cls)
|
||||
|
||||
class plaintext(uh.MinimalHandler):
|
||||
"""This class stores passwords in plaintext, and follows the :ref:`password-hash-api`.
|
||||
|
||||
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 is subclassed by ldap_plaintext
|
||||
|
||||
name = "plaintext"
|
||||
setting_kwds = ()
|
||||
context_kwds = ("encoding",)
|
||||
default_encoding = "utf-8"
|
||||
|
||||
@classmethod
|
||||
def identify(cls, hash):
|
||||
if isinstance(hash, unicode_or_bytes_types):
|
||||
return True
|
||||
else:
|
||||
raise uh.exc.ExpectedStringError(hash, "hash")
|
||||
|
||||
@classmethod
|
||||
def hash(cls, secret, encoding=None):
|
||||
uh.validate_secret(secret)
|
||||
if not encoding:
|
||||
encoding = cls.default_encoding
|
||||
return to_native_str(secret, encoding, "secret")
|
||||
|
||||
@classmethod
|
||||
def verify(cls, secret, hash, encoding=None):
|
||||
if not encoding:
|
||||
encoding = cls.default_encoding
|
||||
hash = to_native_str(hash, encoding, "hash")
|
||||
if not cls.identify(hash):
|
||||
raise uh.exc.InvalidHashError(cls)
|
||||
return str_consteq(cls.hash(secret, encoding), hash)
|
||||
|
||||
@uh.deprecated_method(deprecated="1.7", removed="2.0")
|
||||
@classmethod
|
||||
def genconfig(cls):
|
||||
return cls.hash("")
|
||||
|
||||
@uh.deprecated_method(deprecated="1.7", removed="2.0")
|
||||
@classmethod
|
||||
def genhash(cls, secret, config, encoding=None):
|
||||
# NOTE: 'config' is ignored, as this hash has no salting / etc
|
||||
if not cls.identify(config):
|
||||
raise uh.exc.InvalidHashError(cls)
|
||||
return cls.hash(secret, encoding=encoding)
|
||||
|
||||
#=============================================================================
|
||||
# eof
|
||||
#=============================================================================
|
Reference in New Issue
Block a user