summaryrefslogtreecommitdiffstats
path: root/scripts/update-ldap
blob: 02b9b0fc915e20b46dceb9733c2e4b436613e1be (plain)
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
#!/usr/bin/python3

# Author: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
# Date: 2014-08-30
# License: GPLv3+

# For doing keyring-maint tasks with debian LDAP

import ldap
import getpass
import sys

if sys.argv.__len__() != 2 or sys.argv[1] in ['-h', '--help', 'help']:
    print('''Usage: update-ldap <FILENAME>

FILENAME should be a simple text file, utf8 encoded, where each line
is a key replacement with three fields separated by a single space:

uid oldfpr newfpr
''')
    exit(1)



class debldap:
    def __init__(self):
        self.l = ldap.initialize("ldaps://db.debian.org")

    def auth(self, uid, password):
        self.l.simple_bind_s("uid={uid},ou=users,dc=debian,dc=org".format(uid=uid),password)

    def changefpr(self, uid, oldfpr, newfpr):
        dn = "uid={uid},ou=users,dc=debian,dc=org".format(uid=uid)
        objs = self.l.search_s(dn, ldap.SCOPE_SUBTREE, "objectclass=*")
        if not objs:
            raise BaseException("No objects found matching {dn}".format(dn=dn))
        for o in objs:
            if o[0] != dn:
                raise BaseException("Weird/unexpected dn {new} (expected {old})".format(new=o[0], old=dn))
            fprs = o[1]['keyFingerPrint']
            if fprs != [oldfpr.encode('ascii')]:
                raise BaseException("old fingerprint was {found}, but we expected {oldfpr}".format(found=fprs, oldfpr=oldfpr))
            self.l.modify_s(dn, [(ldap.MOD_REPLACE, 'keyFingerPrint', [newfpr.encode('ascii')])])



f = open(sys.argv[1])

x = debldap()
username = getpass.getuser()

try:
    passwd = getpass.getpass('Debian LDAP password for {user}: '.format(user=username))
    x.auth(username, passwd)
    bound = True
except BaseException as e:
    print("Failed to authenticate: {m}".format(m=e.message))
    exit(1)

errors = []
lineno = 0
successes = 0
for line in f:
    lineno += 1
    user = '<unknown>'
    try:
        data = line.strip('\n').split(' ')
        if data.__len__() != 3:
            raise BaseException("ignoring malformed line: {line}\n".format(lineno=lineno, line=line))
        user = data[0]
        x.changefpr(user, data[1], data[2])
        successes += 1
    except BaseException as e:
        print("{lineno}: {user}: {message}".format(lineno=lineno, user=user,message=str(e.message).strip()))
        errors.append((lineno, e))


print("{errors} errors, {successes} successfully processed".format(successes=successes, errors=errors.__len__()))

if errors:
    exit(1)