This file is indexed.

/usr/share/pyshared/ZEO/auth/base.py is in python-zodb 1:3.9.7-2.

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
##############################################################################
#
# Copyright (c) 2003 Zope Foundation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
"""Base classes for defining an authentication protocol.

Database -- abstract base class for password database
Client -- abstract base class for authentication client
"""

import os
from ZEO.hash import sha1

class Client:
    # Subclass should override to list the names of methods that
    # will be called on the server.
    extensions = []

    def __init__(self, stub):
        self.stub = stub
        for m in self.extensions:
            setattr(self.stub, m, self.stub.extensionMethod(m))

def sort(L):
    """Sort a list in-place and return it."""
    L.sort()
    return L

class Database:
    """Abstracts a password database.

    This class is used both in the authentication process (via
    get_password()) and by client scripts that manage the password
    database file.

    The password file is a simple, colon-separated text file mapping
    usernames to password hashes. The hashes are SHA hex digests
    produced from the password string.
    """
    realm = None
    def __init__(self, filename, realm=None):
        """Creates a new Database

        filename: a string containing the full pathname of
            the password database file. Must be readable by the user
            running ZEO. Must be writeable by any client script that
            accesses the database.

        realm: the realm name (a string)
        """
        self._users = {}
        self.filename = filename
        self.load()
        if realm:
            if self.realm and self.realm != realm:
                raise ValueError("Specified realm %r differs from database "
                                 "realm %r" % (realm or '', self.realm))
            else:
                self.realm = realm

    def save(self, fd=None):
        filename = self.filename

        if not fd:
            fd = open(filename, 'w')
        if self.realm:
            print >> fd, "realm", self.realm

        for username in sort(self._users.keys()):
            print >> fd, "%s: %s" % (username, self._users[username])

    def load(self):
        filename = self.filename
        if not filename:
            return

        if not os.path.exists(filename):
            return

        fd = open(filename)
        L = fd.readlines()

        if not L:
            return

        if L[0].startswith("realm "):
            line = L.pop(0).strip()
            self.realm = line[len("realm "):]

        for line in L:
            username, hash = line.strip().split(":", 1)
            self._users[username] = hash.strip()

    def _store_password(self, username, password):
        self._users[username] = self.hash(password)

    def get_password(self, username):
        """Returns password hash for specified username.

        Callers must check for LookupError, which is raised in
        the case of a non-existent user specified."""
        if not self._users.has_key(username):
            raise LookupError("No such user: %s" % username)
        return self._users[username]

    def hash(self, s):
        return sha1(s).hexdigest()

    def add_user(self, username, password):
        if self._users.has_key(username):
            raise LookupError("User %s already exists" % username)
        self._store_password(username, password)

    def del_user(self, username):
        if not self._users.has_key(username):
            raise LookupError("No such user: %s" % username)
        del self._users[username]

    def change_password(self, username, password):
        if not self._users.has_key(username):
            raise LookupError("No such user: %s" % username)
        self._store_password(username, password)