This file is indexed.

/usr/share/pyshared/passlib/handlers/sha1_crypt.py is in python-passlib 1.5.3-0ubuntu1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
"""passlib.handlers.sha1_crypt
"""

#=========================================================
#imports
#=========================================================

#core
from hmac import new as hmac
from hashlib import sha1
import re
import logging; log = logging.getLogger(__name__)
from warnings import warn
#site
#libs
from passlib.utils import h64, handlers as uh, safe_os_crypt, classproperty, \
    to_hash_str, to_unicode, bytes, b
from passlib.utils.pbkdf2 import hmac_sha1
#pkg
#local
__all__ = [
]
#=========================================================
#sha1-crypt
#=========================================================
class sha1_crypt(uh.HasManyBackends, uh.HasRounds, uh.HasSalt, uh.GenericHandler):
    """This class implements the SHA1-Crypt password hash, and follows the :ref:`password-hash-api`.

    It supports a variable-length salt, and a variable number of rounds.

    The :meth:`encrypt()` and :meth:`genconfig` methods accept the following optional keywords:

    :param salt:
        Optional salt string.
        If not specified, an 8 character one will be autogenerated (this is recommended).
        If specified, it must be 0-64 characters, drawn from the regexp range ``[./0-9A-Za-z]``.

    :param salt_size:
        Optional number of bytes to use when autogenerating new salts.
        Defaults to 8 bytes, but can be any value between 0 and 64.

    :param rounds:
        Optional number of rounds to use.
        Defaults to 40000, must be between 1 and 4294967295, inclusive.

    It will use the first available of two possible backends:

    * stdlib :func:`crypt()`, if the host OS supports sha1-crypt (NetBSD).
    * a pure python implementation of sha1-crypt

    You can see which backend is in use by calling the :meth:`get_backend()` method.
    """

    #=========================================================
    #class attrs
    #=========================================================
    #--GenericHandler--
    name = "sha1_crypt"
    setting_kwds = ("salt", "salt_size", "rounds")
    ident = u"$sha1$"
    checksum_size = 28
    checksum_chars = uh.H64_CHARS

    #--HasSalt--
    default_salt_size = 8
    min_salt_size = 0
    max_salt_size = 64
    salt_chars = uh.H64_CHARS

    #--HasRounds--
    default_rounds = 40000 #current passlib default
    min_rounds = 1 #really, this should be higher.
    max_rounds = 4294967295 # 32-bit integer limit
    rounds_cost = "linear"

    #=========================================================
    #formatting
    #=========================================================

    @classmethod
    def from_string(cls, hash):
        rounds, salt, chk = uh.parse_mc3(hash, cls.ident, cls.name)
        if rounds.startswith("0"):
            raise ValueError("invalid sha1-crypt hash (zero-padded rounds)")
        return cls(
            rounds=int(rounds),
            salt=salt,
            checksum=chk,
            strict=bool(chk),
        )

    def to_string(self, native=True):
        out = u"$sha1$%d$%s" % (self.rounds, self.salt)
        if self.checksum:
            out += u"$" + self.checksum
        return to_hash_str(out) if native else out

    #=========================================================
    #backend
    #=========================================================
    backends = ("os_crypt", "builtin")

    _has_backend_builtin = True

    @classproperty
    def _has_backend_os_crypt(cls):
        h = u'$sha1$1$Wq3GL2Vp$C8U25GvfHS8qGHimExLaiSFlGkAe'
        return bool(safe_os_crypt and safe_os_crypt(u"test",h)[1]==h)

    def _calc_checksum_builtin(self, secret):
        if isinstance(secret, unicode):
            secret = secret.encode("utf-8")
        rounds = self.rounds
            #NOTE: this uses a different format than the hash...
        result = u"%s$sha1$%s" % (self.salt, rounds)
        result = result.encode("ascii")
        r = 0
        while r < rounds:
            result = hmac_sha1(secret, result)
            r += 1
        return h64.encode_transposed_bytes(result, self._chk_offsets).decode("ascii")

    _chk_offsets = [
        2,1,0,
        5,4,3,
        8,7,6,
        11,10,9,
        14,13,12,
        17,16,15,
        0,19,18,
    ]

    def _calc_checksum_os_crypt(self, secret):
        ok, hash = safe_os_crypt(secret, self.to_string(native=False))
        if ok:
            return hash[hash.rindex("$")+1:]
        else:
            return self._calc_checksum_builtin(secret)

    #=========================================================
    #eoc
    #=========================================================

#=========================================================
#eof
#=========================================================