File: passwd.py

package info (click to toggle)
codeville 0.8.0-2
  • links: PTS
  • area: main
  • in suites: jessie, jessie-kfreebsd, wheezy
  • size: 1,148 kB
  • ctags: 1,088
  • sloc: python: 10,335; ansic: 89; sh: 62; makefile: 25
file content (124 lines) | stat: -rw-r--r-- 3,529 bytes parent folder | download | duplicates (5)
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
# Written by Ross Cohen
# see LICENSE.txt for license information

import binascii
from entropy import random_string
from os import chmod, fdopen, path, remove, rename, stat
import SRP
from sys import platform
from tempfile import mkstemp

if platform != 'win32':
    from os import lchown

class Passwd:
    def __init__(self, pw_file, create=False, uid=-1):
        self.users = {}
        self.pw_file = pw_file
        self.pw_dir = path.split(pw_file)[0]
        self.modtime = 0
        if create:
            h = open(self.pw_file, 'a')
            if uid != -1:
                lchown(self.pw_file, uid, -1)
            chmod(self.pw_file, 0600)
            h.close()
        self._read()

    def get(self, user):
        self._read()
        if not self.users.has_key(user):
            raise KeyError
        info = self.users[user]
        if not info.has_key('secret'):
            info['secret'] = random_string(20)
        return info

    def add(self, user, password):
        self._read()
        if self.users.has_key(user):
            raise ValueError, 'User exists'
        s, v = SRP.new_passwd(user, password)
        self.users[user] = {'s': s, 'v': v}
        self._dump()

    def set(self, user, password):
        self._read()
        if not self.users.has_key(user):
            raise ValueError, 'No such user'
        s, v = SRP.new_passwd(user, password)
        self.users[user] = {'s': s, 'v': v}
        self._dump()

    def define(self, user, v, s):
        self._read()
        if not self.users.has_key(user):
            raise ValueError, 'No such user'
        self.users[user] = {'s': s, 'v': v}
        self._dump()

    def delete(self, user):
        self._read()
        try:
            del self.users[user]
        except KeyError:
            raise ValueError, 'No such user'
        self._dump()

    def _read(self):
        h = open(self.pw_file, 'rU')

        modtime = path.getmtime(self.pw_file)
        if self.modtime == modtime:
            return
        self.modtime = modtime

        l, used = None, {}
        while l != '':
            l = h.readline()
            if l.strip() == '':
                continue

            try:
                user, salt, verifier, garbage = l.split(':', 3)
                salt = binascii.unhexlify(salt)
            except ValueError:
                print 'garbage in passwd file'
                raise ValueError

            if not self.users.has_key(user):
                self.users[user] = {'s': salt, 'v': long(verifier)}
            else:
                self.users[user]['s'] = salt
                self.users[user]['v'] = long(verifier)

            used[user] = 1

        h.close()

        # remove the deleted entries
        for user in self.users.keys():
            if not used.has_key(user):
                del self.users[user]

        self.modtime = path.getmtime(self.pw_file)

    def _dump(self):
        text = []
        for user, pw in self.users.items():
            text.append('%s:%s:%d:\n' % (user, binascii.hexlify(pw['s']), pw['v']))
        text.sort()

        fd, fname = mkstemp('', 'cdv', self.pw_dir)
        h = fdopen(fd, 'w')
        h.writelines(text)
        h.close()

        if platform != 'win32':
            statinfo = stat(self.pw_file)
            lchown(fname, statinfo.st_uid, statinfo.st_gid)
        chmod(fname, 0600)
        if platform == 'win32':
            remove(self.pw_file)
        rename(fname, self.pw_file)
        self.modtime = path.getmtime(self.pw_file)