2 from afs import pyafs_error
4 cdef import from "afs/ptuser.h":
15 ctypedef char prname[PR_MAXNAMELEN]
18 unsigned int namelist_len
22 unsigned int prlist_len
26 unsigned int idlist_len
37 char name[PR_MAXNAMELEN]
47 char name[PR_MAXNAMELEN]
50 unsigned int prentries_len
51 prlistentries *prentries_val
53 int ubik_PR_NameToID(ubik_client *, afs_int32, namelist *, idlist *)
54 int ubik_PR_IDToName(ubik_client *, afs_int32, idlist *, namelist *)
55 int ubik_PR_INewEntry(ubik_client *, afs_int32, char *, afs_int32, afs_int32)
56 int ubik_PR_NewEntry(ubik_client *, afs_int32, char *, afs_int32, afs_int32, afs_int32 *)
57 int ubik_PR_Delete(ubik_client *, afs_int32, afs_int32)
58 int ubik_PR_AddToGroup(ubik_client *, afs_int32, afs_int32, afs_int32)
59 int ubik_PR_RemoveFromGroup(ubik_client *, afs_int32, afs_int32, afs_int32)
60 int ubik_PR_ListElements(ubik_client *, afs_int32, afs_int32, prlist *, afs_int32 *)
61 int ubik_PR_ListOwned(ubik_client *, afs_int32, afs_int32, prlist *, afs_int32 *)
62 int ubik_PR_ListEntry(ubik_client *, afs_int32, afs_int32, prcheckentry *)
63 int ubik_PR_ChangeEntry(ubik_client *, afs_int32, afs_int32, char *, afs_int32, afs_int32)
64 int ubik_PR_IsAMemberOf(ubik_client *, afs_int32, afs_int32, afs_int32, afs_int32 *)
65 int ubik_PR_ListMax(ubik_client *, afs_int32, afs_int32 *, afs_int32 *)
66 int ubik_PR_SetMax(ubik_client *, afs_int32, afs_int32, afs_int32)
67 int ubik_PR_ListEntries(ubik_client *, afs_int32, afs_int32, afs_int32, prentries *, afs_int32 *)
68 int ubik_PR_SetFieldsEntry(ubik_client *, afs_int32, afs_int32, afs_int32, afs_int32, afs_int32, afs_int32, afs_int32, afs_int32)
70 cdef import from "afs/pterror.h":
75 cdef public afs_int32 flags
76 cdef public afs_int32 id
77 cdef public afs_int32 owner
78 cdef public afs_int32 creator
79 cdef public afs_int32 ngroups
80 cdef public afs_int32 nusers
81 cdef public afs_int32 count
82 cdef public object name
86 return '<PTEntry: %s>' % self.name
88 return '<PTEntry: PTS ID %s>' % self.id
90 cdef int _ptentry_from_c(PTEntry p_entry, prcheckentry * c_entry) except -1:
95 p_entry.flags = c_entry.flags
96 p_entry.id = c_entry.id
97 p_entry.owner = c_entry.owner
98 p_entry.creator = c_entry.creator
99 p_entry.ngroups = c_entry.ngroups
100 p_entry.nusers = c_entry.nusers
101 p_entry.count = c_entry.count
102 p_entry.name = c_entry.name
105 cdef int _ptentry_to_c(prcheckentry * c_entry, PTEntry p_entry) except -1:
110 c_entry.flags = p_entry.flags
111 c_entry.id = p_entry.id
112 c_entry.owner = p_entry.owner
113 c_entry.creator = p_entry.creator
114 c_entry.ngroups = p_entry.ngroups
115 c_entry.nusers = p_entry.nusers
116 c_entry.count = p_entry.count
117 strncpy(c_entry.name, p_entry.name, sizeof(c_entry.name))
122 A PTS object is essentially a handle to talk to the server in a
125 cell defaults to None. If no argument is passed for cell, PTS
126 connects to the home cell.
128 sec is the security level, an integer from 0 to 3:
129 - 0: unauthenticated connection
130 - 1: try authenticated, then fall back to unauthenticated
131 - 2: fail if an authenticated connection can't be established
132 - 3: same as 2, plus encrypt all traffic to the protection
135 cdef ubik_client * client
136 cdef readonly object cell
138 def __cinit__(self, cell=None, sec=1):
140 cdef afsconf_dir *cdir
141 cdef afsconf_cell info
143 cdef ktc_principal prin
145 cdef rx_securityClass *sc
146 cdef rx_connection *serverconns[MAXSERVERS]
149 initialize_PT_error_table()
160 raise Exception(code, "Error initializing Rx")
162 cdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH)
165 "Error opening configuration directory (%s): %s" % \
166 (AFSDIR_CLIENT_ETC_DIRPATH, strerror(errno)))
167 code = afsconf_GetCellInfo(cdir, c_cell, "afsprot", &info)
170 self.cell = info.name
173 strncpy(prin.cell, info.name, sizeof(prin.cell))
175 strncpy(prin.name, "afs", sizeof(prin.name))
177 code = ktc_GetToken(&prin, &token, sizeof(token), NULL);
180 # No really - we wanted authentication
188 sc = rxkad_NewClientSecurityObject(level, &token.sessionKey,
189 token.kvno, token.ticketLen,
193 sc = rxnull_NewClientSecurityObject()
197 memset(serverconns, 0, sizeof(serverconns))
198 for 0 <= i < info.numServers:
199 serverconns[i] = rx_NewConnection(info.hostAddr[i].sin_addr.s_addr,
200 info.hostAddr[i].sin_port,
205 code = ubik_ClientInit(serverconns, &self.client)
208 code = rxs_Release(sc)
210 def __dealloc__(self):
211 ubik_ClientDestroy(self.client)
214 def _NameOrId(self, ident):
216 Given an identifier, convert it to a PTS ID by looking up the
217 name if it's a string, or otherwise just converting it to an
220 if isinstance(ident, basestring):
221 return self._NameToId(ident)
225 def _NameToId(self, name):
227 Converts a user or group to an AFS ID.
231 cdef afs_int32 code, id = ANONYMOUSID
235 lids.idlist_val = NULL
236 lnames.namelist_len = 1
237 lnames.namelist_val = <prname *>malloc(PR_MAXNAMELEN)
238 strncpy(lnames.namelist_val[0], name, PR_MAXNAMELEN)
239 code = ubik_PR_NameToID(self.client, 0, &lnames, &lids)
240 if lids.idlist_val is not NULL:
241 id = lids.idlist_val[0]
242 free(lids.idlist_val)
243 if id == ANONYMOUSID:
248 def _IdToName(self, id):
250 Convert an AFS ID to the name of a user or group.
255 cdef char name[PR_MAXNAMELEN]
258 lids.idlist_val = <afs_int32 *>malloc(sizeof(afs_int32))
259 lids.idlist_val[0] = id
260 lnames.namelist_len = 0
261 lnames.namelist_val = NULL
262 code = ubik_PR_IDToName(self.client, 0, &lids, &lnames)
263 if lnames.namelist_val is not NULL:
264 strncpy(name, lnames.namelist_val[0], sizeof(name))
265 free(lnames.namelist_val)
266 if lids.idlist_val is not NULL:
267 free(lids.idlist_val)
273 def _CreateUser(self, name, id=None):
275 Create a new user in the protection database. If an ID is
276 provided, that one will be used.
280 name = name[:PR_MAXNAMELEN].lower()
286 code = ubik_PR_INewEntry(self.client, 0, name, cid, 0)
288 code = ubik_PR_NewEntry(self.client, 0, name, 0, 0, &cid)
293 def _CreateGroup(self, name, owner, id=None):
295 Create a new group in the protection database. If an ID is
296 provided, that one will be used.
298 cdef afs_int32 code, cid
300 name = name[:PR_MAXNAMELEN].lower()
301 oid = self._NameOrId(owner)
305 code = ubik_PR_INewEntry(self.client, 0, name, cid, oid)
307 code = ubik_PR_NewEntry(self.client, 0, name, PRGRP, oid, &cid)
312 def _Delete(self, ident):
314 Delete the protection database entry with the provided
318 cdef afs_int32 id = self._NameOrId(ident)
320 code = ubik_PR_Delete(self.client, 0, id)
323 def _AddToGroup(self, user, group):
325 Add the given user to the given group.
328 cdef afs_int32 uid = self._NameOrId(user), gid = self._NameOrId(group)
330 code = ubik_PR_AddToGroup(self.client, 0, uid, gid)
333 def _RemoveFromGroup(self, user, group):
335 Remove the given user from the given group.
338 cdef afs_int32 uid = self._NameOrId(user), gid = self._NameOrId(group)
340 code = ubik_PR_RemoveFromGroup(self.client, 0, uid, gid)
343 def _ListMembers(self, ident):
345 Get the membership of an entity.
347 If id is a group, this returns the users that are in that
350 If id is a user, this returns the list of groups that user is
353 This returns a list of PTS IDs.
355 cdef afs_int32 code, over
358 cdef object members = []
360 cdef afs_int32 id = self._NameOrId(ident)
363 alist.prlist_val = NULL
365 code = ubik_PR_ListElements(self.client, 0, id, &alist, &over)
367 if alist.prlist_val is not NULL:
368 for i in range(alist.prlist_len):
369 members.append(alist.prlist_val[i])
370 free(alist.prlist_val)
376 def _ListOwned(self, owner):
378 Get all groups owned by an entity.
380 cdef afs_int32 code, over
383 cdef object owned = []
385 cdef afs_int32 oid = self._NameOrId(owner)
388 alist.prlist_val = NULL
390 code = ubik_PR_ListOwned(self.client, 0, oid, &alist, &over)
392 if alist.prlist_val is not NULL:
393 for i in range(alist.prlist_len):
394 owned.append(alist.prlist_val[i])
395 free(alist.prlist_val)
401 def _ListEntry(self, ident):
403 Load a PTEntry instance with information about the provided
407 cdef prcheckentry centry
408 cdef object entry = PTEntry()
410 cdef afs_int32 id = self._NameOrId(ident)
412 code = ubik_PR_ListEntry(self.client, 0, id, ¢ry)
415 _ptentry_from_c(entry, ¢ry)
418 def _ChangeEntry(self, ident, newname=None, newid=None, newoid=None):
420 Change the name, ID, and/or owner of a PTS entity.
422 For any of newname, newid, and newoid which aren't specified
423 or ar None, the value isn't changed.
426 cdef afs_int32 c_newid = 0, c_newoid = 0
427 cdef char * c_newname
429 cdef afs_int32 id = self._NameOrId(ident)
432 newname = self._IdToName(id)
434 if newid is not None:
436 if newoid is not None:
439 code = ubik_PR_ChangeEntry(self.client, 0, id, c_newname, c_newoid, c_newid)
442 def _IsAMemberOf(self, user, group):
444 Return True if the given user is a member of the given group.
449 cdef afs_int32 uid = self._NameOrId(user), gid = self._NameOrId(group)
451 code = ubik_PR_IsAMemberOf(self.client, 0, uid, gid, &flag)
458 Return a tuple of the maximum user ID and the maximum group
459 ID currently assigned.
461 cdef afs_int32 code, uid, gid
463 code = ubik_PR_ListMax(self.client, 0, &uid, &gid)
468 def _SetMaxUserId(self, id):
470 Set the maximum currently assigned user ID (the next
471 automatically assigned UID will be id + 1)
475 code = ubik_PR_SetMax(self.client, 0, id, 0)
478 def _SetMaxGroupId(self, id):
480 Set the maximum currently assigned user ID (the next
481 automatically assigned UID will be id + 1)
485 code = ubik_PR_SetMax(self.client, 0, id, PRGRP)
488 def _ListEntries(self, users=None, groups=None):
490 Return a list of PTEntry instances representing all entries in
493 Returns just users by default, but can return just users, just
497 cdef afs_int32 flag = 0, startindex = 0, nentries, nextstartindex
498 cdef prentries centries
501 cdef object entries = []
503 if groups is None or users is True:
508 while startindex != -1:
509 centries.prentries_val = NULL
510 centries.prentries_len = 0
513 code = ubik_PR_ListEntries(self.client, 0, flag, startindex, ¢ries, &nextstartindex)
514 if centries.prentries_val is not NULL:
515 for i in range(centries.prentries_len):
517 _ptentry_from_c(e, <prcheckentry *>¢ries.prentries_val[i])
519 free(centries.prentries_val)
522 startindex = nextstartindex
526 def _SetFields(self, ident, access=None, groups=None, users=None):
528 Update the fields for an entry.
530 Valid fields are the privacy flags (access), the group quota
531 (groups), or the "foreign user quota" (users), which doesn't
532 actually seem to do anything, but is included for
536 cdef afs_int32 mask = 0, flags = 0, nusers = 0, ngroups = 0
538 cdef afs_int32 id = self._NameOrId(ident)
540 if access is not None:
542 mask |= PR_SF_ALLBITS
543 if groups is not None:
545 mask |= PR_SF_NGROUPS
546 if users is not None:
548 mask |= PR_SF_NGROUPS
550 code = ubik_PR_SetFieldsEntry(self.client, 0, id, mask, flags, ngroups, nusers, 0, 0)