Example #1
0
def update_settings(**kwds):
    for k, v in iteritems(kwds):
        if v is UNSET:
            if hasattr(settings, k):
                delattr(settings, k)
        else:
            setattr(settings, k, v)
Example #2
0
    def verify(cls, secret, hash, full=False):
        uh.validate_secret(secret)
        self = cls.from_string(hash)
        chkmap = self.checksum
        if not chkmap:
            raise ValueError('expected %s hash, got %s config string instead' % (
             cls.name, cls.name))
        if full:
            correct = failed = False
            for alg, digest in iteritems(chkmap):
                other = self._calc_checksum(secret, alg)
                if len(digest) != len(other):
                    raise ValueError('mis-sized %s digest in scram hash: %r != %r' % (
                     alg, len(digest), len(other)))
                if consteq(other, digest):
                    correct = True
                else:
                    failed = True

            if correct and failed:
                raise ValueError('scram hash verified inconsistently, may be corrupted')
            else:
                return correct
        else:
            for alg in self._verify_algs:
                if alg in chkmap:
                    other = self._calc_checksum(secret, alg)
                    return consteq(other, chkmap[alg])

            raise AssertionError('sha-1 digest not found!')
Example #3
0
 def check_all(self, strict=False):
     same = self._is_same_value
     for path, (orig, expected) in iteritems(self._state):
         if same(self._get_path(path), expected):
             continue
         msg = 'another library has patched resource: %r' % path
         if strict:
             raise RuntimeError(msg)
         else:
             warn(msg, PasslibRuntimeWarning)
Example #4
0
    def safe_summary(self, encoded):
        from django.contrib.auth.hashers import mask_hash
        from django.utils.translation import ugettext_noop as _
        handler = self.passlib_handler
        items = [(_('algorithm'), handler.name)]
        if hasattr(handler, 'parsehash'):
            kwds = handler.parsehash(encoded, sanitize=mask_hash)
            for key, value in iteritems(kwds):
                key = self._translate_kwds.get(key, key)
                items.append((_(key), value))

        return OrderedDict(items)
Example #5
0
    def _init_options(self, source):
        norm_scheme_option = self._norm_scheme_option
        norm_context_option = self._norm_context_option
        self._scheme_options = scheme_options = {}
        self._context_options = context_options = {}
        categories = set()
        for (cat, scheme, key), value in iteritems(source):
            categories.add(cat)
            explicit_scheme = scheme
            if not cat and not scheme and key in _global_settings:
                scheme = 'all'
            if scheme:
                key, value = norm_scheme_option(key, value)
                if scheme == 'all' and key not in _global_settings:
                    warn(
                        "The '%s' option should be configured per-algorithm, and not set globally in the context; This will be an error in Passlib 2.0"
                        % (key, ), PasslibConfigWarning)
                if explicit_scheme == 'all':
                    warn(
                        "The 'all' scheme is deprecated as of Passlib 1.7, and will be removed in Passlib 2.0; Please configure options on a per-algorithm basis.",
                        DeprecationWarning)
                try:
                    category_map = scheme_options[scheme]
                except KeyError:
                    scheme_options[scheme] = {cat: {key: value}}
                else:
                    try:
                        option_map = category_map[cat]
                    except KeyError:
                        category_map[cat] = {key: value}
                    else:
                        option_map[key] = value

            else:
                if cat and key == 'schemes':
                    raise KeyError(
                        "'schemes' context option is not allowed per category")
                key, value = norm_context_option(cat, key, value)
                if key == 'min_verify_time':
                    continue
                try:
                    category_map = context_options[key]
                except KeyError:
                    context_options[key] = {cat: value}
                else:
                    category_map[cat] = value

        categories.discard(None)
        self.categories = tuple(sorted(categories))
        return
Example #6
0
    def _norm_checksum(self, checksum, relaxed=False):
        if not isinstance(checksum, dict):
            raise uh.exc.ExpectedTypeError(checksum, 'dict', 'checksum')
        for alg, digest in iteritems(checksum):
            if alg != norm_hash_name(alg, 'iana'):
                raise ValueError('malformed algorithm name in scram hash: %r' % (
                 alg,))
            if len(alg) > 9:
                raise ValueError('SCRAM limits algorithm names to 9 characters: %r' % (
                 alg,))
            if not isinstance(digest, bytes):
                raise uh.exc.ExpectedTypeError(digest, 'raw bytes', 'digests')

        if 'sha-1' not in checksum:
            raise ValueError('sha-1 must be in algorithm list of scram hash')
        return checksum
Example #7
0
 def load(self, source, update=False, section='passlib', encoding='utf-8'):
     parse_keys = True
     if isinstance(source, unicode_or_bytes_types):
         if PY3:
             source = to_unicode(source, encoding, param='source')
         else:
             source = to_bytes(source,
                               'utf-8',
                               source_encoding=encoding,
                               param='source')
         source = self._parse_ini_stream(
             NativeStringIO(source), section,
             '<string passed to CryptContext.load()>')
     else:
         if isinstance(source, CryptContext):
             source = dict(source._config.iter_config(resolve=True))
             parse_keys = False
         else:
             if not hasattr(source, 'items'):
                 raise ExpectedTypeError(source, 'string or dict', 'source')
     if parse_keys:
         parse = self._parse_config_key
         source = dict(
             (parse(key), value) for key, value in iteritems(source))
     if update and self._config is not None:
         if not source:
             return
         tmp = source
         source = dict(self._config.iter_config(resolve=True))
         source.update(tmp)
     config = _CryptConfig(source)
     self._config = config
     self._reset_dummy_verify()
     self._get_record = config.get_record
     self._identify_record = config.identify_record
     if config.context_kwds:
         self.__dict__.pop('_strip_unused_context_kwds', None)
     else:
         self._strip_unused_context_kwds = None
     return
Example #8
0
class fshp(uh.HasRounds, uh.HasRawSalt, uh.HasRawChecksum, uh.GenericHandler):
    name = 'fshp'
    setting_kwds = ('salt', 'salt_size', 'rounds', 'variant')
    checksum_chars = uh.PADDED_BASE64_CHARS
    ident = u('{FSHP')
    default_salt_size = 16
    max_salt_size = None
    default_rounds = 480000
    min_rounds = 1
    max_rounds = 4294967295L
    rounds_cost = 'linear'
    default_variant = 1
    _variant_info = {0: ('sha1', 20), 
       1: ('sha256', 32), 
       2: ('sha384', 48), 
       3: ('sha512', 64)}
    _variant_aliases = dict([ (unicode(k), k) for k in _variant_info ] + [ (v[0], k) for k, v in iteritems(_variant_info) ])

    @classmethod
    def using(cls, variant=None, **kwds):
        subcls = super(fshp, cls).using(**kwds)
        if variant is not None:
            subcls.default_variant = cls._norm_variant(variant)
        return subcls

    variant = None

    def __init__(self, variant=None, **kwds):
        self.use_defaults = kwds.get('use_defaults')
        if variant is not None:
            variant = self._norm_variant(variant)
        else:
            if self.use_defaults:
                variant = self.default_variant
            else:
                raise TypeError('no variant specified')
        self.variant = variant
        super(fshp, self).__init__(**kwds)
        return

    @classmethod
    def _norm_variant(cls, variant):
        if isinstance(variant, bytes):
            variant = variant.decode('ascii')
        if isinstance(variant, unicode):
            try:
                variant = cls._variant_aliases[variant]
            except KeyError:
                raise ValueError('invalid fshp variant')

        if not isinstance(variant, int):
            raise TypeError('fshp variant must be int or known alias')
        if variant not in cls._variant_info:
            raise ValueError('invalid fshp variant')
        return variant

    @property
    def checksum_alg(self):
        return self._variant_info[self.variant][0]

    @property
    def checksum_size(self):
        return self._variant_info[self.variant][1]

    _hash_regex = re.compile(u('\n            ^\n            \\{FSHP\n            (\\d+)\\| # variant\n            (\\d+)\\| # salt size\n            (\\d+)\\} # rounds\n            ([a-zA-Z0-9+/]+={0,3}) # digest\n            $'), re.X)

    @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)
        variant, salt_size, rounds, data = m.group(1, 2, 3, 4)
        variant = int(variant)
        salt_size = int(salt_size)
        rounds = int(rounds)
        try:
            data = b64decode(data.encode('ascii'))
        except TypeError:
            raise uh.exc.MalformedHashError(cls)

        salt = data[:salt_size]
        chk = data[salt_size:]
        return cls(salt=salt, checksum=chk, rounds=rounds, variant=variant)

    def to_string(self):
        chk = self.checksum
        salt = self.salt
        data = bascii_to_str(b64encode(salt + chk))
        return '{FSHP%d|%d|%d}%s' % (self.variant, len(salt), self.rounds, data)

    def _calc_checksum(self, secret):
        if isinstance(secret, unicode):
            secret = secret.encode('utf-8')
        return pbkdf1(digest=self.checksum_alg, secret=self.salt, salt=secret, rounds=self.rounds, keylen=self.checksum_size)