Add ListOwned call.
[invirt/packages/python-afs.git] / afs / _pts.pyx
1 from afs cimport *
2
3 cdef import from "afs/ptuser.h":
4     enum:
5         PR_MAXNAMELEN
6         PRGRP
7         ANONYMOUSID
8
9     ctypedef char prname[PR_MAXNAMELEN]
10
11     struct namelist:
12         unsigned int namelist_len
13         prname *namelist_val
14
15     struct prlist:
16         unsigned int prlist_len
17         afs_int32 *prlist_val
18
19     struct idlist:
20         unsigned int idlist_len
21         afs_int32 *idlist_val
22
23     int ubik_PR_NameToID(ubik_client *, afs_int32, namelist *, idlist *)
24     int ubik_PR_IDToName(ubik_client *, afs_int32, idlist *, namelist *)
25     int ubik_PR_INewEntry(ubik_client *, afs_int32, char *, afs_int32, afs_int32)
26     int ubik_PR_NewEntry(ubik_client *, afs_int32, char *, afs_int32, afs_int32, afs_int32 *)
27     int ubik_PR_Delete(ubik_client *, afs_int32, afs_int32)
28     int ubik_PR_AddToGroup(ubik_client *, afs_int32, afs_int32, afs_int32)
29     int ubik_PR_RemoveFromGroup(ubik_client *, afs_int32, afs_int32, afs_int32)
30     int ubik_PR_ListElements(ubik_client *, afs_int32, afs_int32, prlist *, afs_int32 *)
31     int ubik_PR_ListOwned(ubik_client *, afs_int32, afs_int32, prlist *, afs_int32 *)
32
33 cdef import from "afs/pterror.h":
34     enum:
35         PRNOENT
36         PRTOOMANY
37
38     void initialize_PT_error_table()
39
40 cdef class PTS:
41     cdef ubik_client * client
42
43     def __cinit__(self, cell=None, sec=1):
44         """
45         Open a connection to the protection server. A PTS object is
46         essentially a handle to talk to the server in a given cell.
47
48         cell defaults to None. If no argument is passed for cell, PTS
49         connects to the home cell.
50
51         sec is the security level, an integer from 0 to 3:
52          - 0: unauthenticated connection
53          - 1: try authenticated, then fall back to unauthenticated
54          - 2: fail if an authenticated connection can't be established
55          - 3: same as 2, plus encrypt all traffic to the protection
56            server
57         """
58         cdef afs_int32 code
59         cdef afsconf_dir *cdir
60         cdef afsconf_cell info
61         cdef char * c_cell
62         cdef ktc_principal prin
63         cdef ktc_token token
64         cdef rx_securityClass *sc
65         cdef rx_connection *serverconns[MAXSERVERS]
66         cdef int i
67
68         initialize_PT_error_table()
69
70         if cell is None:
71             c_cell = NULL
72         else:
73             c_cell = cell
74
75         self.client = NULL
76
77         code = rx_Init(0)
78         if code != 0:
79             raise Exception(code, "Error initializing Rx")
80
81         cdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH)
82         if cdir is NULL:
83             raise OSError(errno,
84                           "Error opening configuration directory (%s): %s" % \
85                               (AFSDIR_CLIENT_ETC_DIRPATH, strerror(errno)))
86         code = afsconf_GetCellInfo(cdir, c_cell, "afsprot", &info)
87         if code != 0:
88             raise Exception(code, "GetCellInfo: %s" % afs_error_message(code))
89
90         if sec > 0:
91             strncpy(prin.cell, info.name, sizeof(prin.cell))
92             prin.instance[0] = 0
93             strncpy(prin.name, "afs", sizeof(prin.name))
94
95             code = ktc_GetToken(&prin, &token, sizeof(token), NULL);
96             if code != 0:
97                 if sec >= 2:
98                     # No really - we wanted authentication
99                     raise Exception(code, "Failed to get token for service AFS: %s" % afs_error_message(code))
100                 sec = 0
101             else:
102                 if sec == 3:
103                     level = rxkad_crypt
104                 else:
105                     level = rxkad_clear
106                 sc = rxkad_NewClientSecurityObject(level, &token.sessionKey,
107                                                    token.kvno, token.ticketLen,
108                                                    token.ticket)
109
110         if sec == 0:
111             sc = rxnull_NewClientSecurityObject()
112         else:
113             sec = 2
114
115         memset(serverconns, 0, sizeof(serverconns))
116         for 0 <= i < info.numServers:
117             serverconns[i] = rx_NewConnection(info.hostAddr[i].sin_addr.s_addr,
118                                               info.hostAddr[i].sin_port,
119                                               PRSRV,
120                                               sc,
121                                               sec)
122
123         code = ubik_ClientInit(serverconns, &self.client)
124         if code != 0:
125             raise Exception("Failed to initialize ubik connection to Protection server: %s" % afs_error_message(code))
126
127         code = rxs_Release(sc)
128
129     def __dealloc__(self):
130         ubik_ClientDestroy(self.client)
131         rx_Finalize()
132
133     def NameToId(self, name):
134         """
135         Converts a user or group to an AFS ID.
136         """
137         cdef namelist lnames
138         cdef idlist lids
139         cdef afs_int32 code, id
140         name = name.lower()
141
142         lids.idlist_len = 0
143         lids.idlist_val = NULL
144         lnames.namelist_len = 1
145         lnames.namelist_val = <prname *>malloc(PR_MAXNAMELEN)
146         strncpy(lnames.namelist_val[0], name, PR_MAXNAMELEN)
147         code = ubik_PR_NameToID(self.client, 0, &lnames, &lids)
148         if lids.idlist_val is not NULL:
149             id = lids.idlist_val[0]
150             free(lids.idlist_val)
151         if id == ANONYMOUSID:
152             code = PRNOENT
153         if code != 0:
154             raise Exception("Failed to lookup PTS name: %s" % afs_error_message(code))
155         return id
156
157     def IdToName(self, id):
158         """
159         Convert an AFS ID to the name of a user or group.
160         """
161         cdef namelist lnames
162         cdef idlist lids
163         cdef afs_int32 code
164         cdef char name[PR_MAXNAMELEN]
165
166         lids.idlist_len = 1
167         lids.idlist_val = <afs_int32 *>malloc(sizeof(afs_int32))
168         lids.idlist_val[0] = id
169         lnames.namelist_len = 0
170         lnames.namelist_val = NULL
171         code = ubik_PR_IDToName(self.client, 0, &lids, &lnames)
172         if lnames.namelist_val is not NULL:
173             strncpy(name, lnames.namelist_val[0], sizeof(name))
174             free(lnames.namelist_val)
175         if lids.idlist_val is not NULL:
176             free(lids.idlist_val)
177         if name == str(id):
178             code = PRNOENT
179         if code != 0:
180             raise Exception("Failed to lookup PTS ID: %s" % afs_error_message(code))
181         return name
182
183     def CreateUser(self, name, id=None):
184         """
185         Create a new user in the protection database. If an ID is
186         provided, that one will be used.
187         """
188         cdef afs_int32 code
189         cdef afs_int32 cid
190         name = name[:PR_MAXNAMELEN].lower()
191
192         if id is not None:
193             cid = id
194
195         if id is not None:
196             code = ubik_PR_INewEntry(self.client, 0, name, cid, 0)
197         else:
198             code = ubik_PR_NewEntry(self.client, 0, name, 0, 0, &cid)
199
200         if code != 0:
201             raise Exception("Failed to create user: %s" % afs_error_message(code))
202         return cid
203
204     def CreateGroup(self, name, owner, id=None):
205         """
206         Create a new group in the protection database. If an ID is
207         provided, that one will be used.
208         """
209         cdef afs_int32 code, cid
210
211         name = name[:PR_MAXNAMELEN].lower()
212         oid = self.NameToId(owner)
213
214         if id is not None:
215             cid = id
216             code = ubik_PR_INewEntry(self.client, 0, name, cid, oid)
217         else:
218             code = ubik_PR_NewEntry(self.client, 0, name, PRGRP, oid, &cid)
219
220         if code != 0:
221             raise Exception("Failed to create group: %s" % afs_error_message(code))
222         return cid
223
224     def Delete(self, id):
225         """
226         Delete the protection database entry with the provided ID.
227         """
228         cdef afs_int32 code
229
230         code = ubik_PR_Delete(self.client, 0, id)
231         if code != 0:
232             raise Exception("Failed to delete user: %s" % afs_error_message(code))
233
234     def AddToGroup(self, uid, gid):
235         """
236         Add the user with the given ID to the group with the given ID.
237         """
238         cdef afs_int32 code
239
240         code = ubik_PR_AddToGroup(self.client, 0, uid, gid)
241         if code != 0:
242             raise Exception("Failed to add user to group: %s" % afs_error_message(code))
243
244     def RemoveFromGroup(self, uid, gid):
245         """
246         Remove the user with the given ID from the group with the given ID.
247         """
248         cdef afs_int32 code
249
250         code = ubik_PR_RemoveFromGroup(self.client, 0, uid, gid)
251         if code != 0:
252             raise Exception("Failed to remove user from group: %s" % afs_error_message(code))
253
254     def ListMembers(self, id):
255         """
256         Get the membership of an entity.
257
258         If id is a group ID, this returns the users that are in that
259         group.
260
261         If id is a user ID, this returns the list of groups that user
262         is on.
263
264         This returns a list of PTS IDs.
265         """
266         cdef afs_int32 code, over
267         cdef prlist alist
268         cdef int i
269         cdef object members = []
270
271         alist.prlist_len = 0
272         alist.prlist_val = NULL
273
274         code = ubik_PR_ListElements(self.client, 0, id, &alist, &over)
275
276         if alist.prlist_val is not NULL:
277             for i in range(alist.prlist_len):
278                 members.append(alist.prlist_val[i])
279             free(alist.prlist_val)
280
281         if over:
282             code = PRTOOMANY
283         if code != 0:
284             raise Exception("Failed to get group membership: %s" % afs_error_message(code))
285
286         return members
287
288     def ListOwned(self, oid):
289         """
290         Get all groups owned by an entity.
291         """
292         cdef afs_int32 code, over
293         cdef prlist alist
294         cdef int i
295         cdef object owned = []
296
297         alist.prlist_len = 0
298         alist.prlist_val = NULL
299
300         code = ubik_PR_ListOwned(self.client, 0, oid, &alist, &over)
301
302         if alist.prlist_val is not NULL:
303             for i in range(alist.prlist_len):
304                 owned.append(alist.prlist_val[i])
305             free(alist.prlist_val)
306
307         if over:
308             code = PRTOOMANY
309         if code != 0:
310             raise Exception("Failed to get owned entities: %s" % afs_error_message(code))
311
312         return owned