If the ACL for a locker isn't accessible, assume it's empty (closes #82)
[invirt/packages/invirt-web.git] / code / getafsgroups.py
1 #!/usr/bin/python
2 import pprint
3 import subprocess
4
5 # import ldap
6 # l = ldap.open("W92-130-LDAP-2.mit.edu")
7 # # ldap.mit.edu is 1/2 broken right now so we're going to the working backend
8 # l.simple_bind_s("", "")
9
10 # def getLdapGroups(user):
11 #     """
12 #     getLdapGroups(user): returns a generator for the list of LDAP groups containing user
13 #     """
14 #     for user_data in l.search_s("ou=affiliates,dc=mit,dc=edu", ldap.SCOPE_ONELEVEL, "uid=" + user, []):
15 #         for group_data in l.search_s("ou=groups,dc=mit,dc=edu", ldap.SCOPE_ONELEVEL, "uniqueMember="+user_data[0], ['cn']):
16 #             yield group_data[1]['cn'][0]
17
18 # def checkLdapGroups(user, group):
19 #     """
20 #     checkLdapGroups(user, group): returns True if and only if user is in LDAP group group
21 #     """
22 #     for result_data in l.search_s("ou=affiliates,dc=mit,dc=edu", ldap.SCOPE_ONELEVEL, "uid=" + user, []):
23 #         if l.search_s("ou=groups,dc=mit,dc=edu", ldap.SCOPE_ONELEVEL, "(&(cn=" + group + ")(uniqueMember="+result_data[0] + "))", []) != []:
24 #             return True
25 #     return False
26
27 class AfsProcessError(Exception):
28     pass
29
30 def getAfsGroupMembers(group, cell):
31     p = subprocess.Popen(["pts", "membership", "-noauth", group, '-c', cell], 
32                          stdout=subprocess.PIPE, stderr=subprocess.PIPE)
33     err = p.stderr.read()
34     if err: #Error code doesn't reveal missing groups, but stderr does
35         raise AfsProcessError(err)
36     return [line.strip() for line in p.stdout.readlines()[1:]]
37
38 def getLockerPath(locker):
39     if '/' in locker or locker in ['.', '..']:
40         raise AfsProcessError("Locker '%s' is invalid." % locker)
41     return '/mit/' + locker
42
43 def getCell(locker):
44     p = subprocess.Popen(["fs", "whichcell", getLockerPath(locker)], 
45                          stdout=subprocess.PIPE, stderr=subprocess.PIPE)
46     if p.wait():
47         raise AfsProcessError(p.stderr.read())
48     return p.stdout.read().split()[-1][1:-1]
49
50 def getLockerAcl(locker):
51     try:
52         p = subprocess.Popen(["fs", "listacl", getLockerPath(locker)], 
53                              stdout=subprocess.PIPE, stderr=subprocess.PIPE)
54         if p.wait():
55             raise AfsProcessError(p.stderr.read())
56     except AfsProcessError, e:
57         if e.message.startswith("fs: You don't have the required access rights on"):
58             return []
59         raise
60     lines = p.stdout.readlines()
61     values = []
62     for line in lines[1:]:
63         fields = line.split()
64         if fields[0] == 'Negative':
65             break
66         if 'a' in fields[1]:
67             values.append(fields[0])
68     return values
69
70 def notLockerOwner(user, locker):
71     """
72     notLockerOwner(user, locker) returns false if and only if user administers locker.
73
74     If the user does not own the locker, returns the string reason for
75     the failure.
76     """
77     try:
78         cell = getCell(locker)
79         values = getLockerAcl(locker)
80     except AfsProcessError, e:
81         return str(e)
82
83     for entry in values:
84         if entry == user or (entry[0:6] == "system" and
85                                 user in getAfsGroupMembers(entry, cell)):
86             return False
87     return "You don't have admin bits on " + getLockerPath(locker)
88
89
90 if __name__ == "__main__":
91 #    print list(getldapgroups("tabbott"))
92     print "tabbott" in getAfsGroupMembers("system:debathena", 'athena.mit.edu')
93     print "tabbott" in getAfsGroupMembers("system:debathena", 'sipb.mit.edu')
94     print "tabbott" in getAfsGroupMembers("system:debathena-root", 'athena.mit.edu')
95     print "tabbott" in getAfsGroupMembers("system:hmmt-request", 'athena.mit.edu')
96     print notLockerOwner("tabbott", "tabbott")
97     print notLockerOwner("tabbott", "debathena")
98     print notLockerOwner("tabbott", "sipb")
99     print notLockerOwner("tabbott", "lsc")
100     print notLockerOwner("tabbott", "scripts")
101     print notLockerOwner("ecprice", "hmmt")