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":
74 cdef import from "krb5/krb5.h":
77 struct krb5_principal_data:
80 ctypedef _krb5_context krb5_context
81 ctypedef krb5_principal_data * krb5_principal
83 ctypedef long krb5_int32
84 ctypedef krb5_int32 krb5_error_code
85 krb5_error_code krb5_init_context(krb5_context *)
86 krb5_error_code krb5_parse_name(krb5_context, char *, krb5_principal *)
87 krb5_error_code krb5_unparse_name(krb5_context, krb5_principal, char **)
88 krb5_error_code krb5_524_conv_principal(krb5_context, krb5_principal, char *, char *, char *)
89 krb5_error_code krb5_425_conv_principal(krb5_context, char *, char *, char *, krb5_principal *)
90 krb5_error_code krb5_get_host_realm(krb5_context, char *, char ***)
91 void krb5_free_host_realm(krb5_context, char **)
92 void krb5_free_principal(krb5_context, krb5_principal)
93 void krb5_free_context(krb5_context)
96 cdef public afs_int32 flags
97 cdef public afs_int32 id
98 cdef public afs_int32 owner
99 cdef public afs_int32 creator
100 cdef public afs_int32 ngroups
101 cdef public afs_int32 nusers
102 cdef public afs_int32 count
103 cdef public object name
107 return '<PTEntry: %s>' % self.name
109 return '<PTEntry: PTS ID %s>' % self.id
111 cdef int _ptentry_from_c(PTEntry p_entry, prcheckentry * c_entry) except -1:
116 p_entry.flags = c_entry.flags
117 p_entry.id = c_entry.id
118 p_entry.owner = c_entry.owner
119 p_entry.creator = c_entry.creator
120 p_entry.ngroups = c_entry.ngroups
121 p_entry.nusers = c_entry.nusers
122 p_entry.count = c_entry.count
123 p_entry.name = c_entry.name
126 cdef int _ptentry_to_c(prcheckentry * c_entry, PTEntry p_entry) except -1:
131 c_entry.flags = p_entry.flags
132 c_entry.id = p_entry.id
133 c_entry.owner = p_entry.owner
134 c_entry.creator = p_entry.creator
135 c_entry.ngroups = p_entry.ngroups
136 c_entry.nusers = p_entry.nusers
137 c_entry.count = p_entry.count
138 strncpy(c_entry.name, p_entry.name, sizeof(c_entry.name))
143 A PTS object is essentially a handle to talk to the server in a
146 cell defaults to None. If no argument is passed for cell, PTS
147 connects to the home cell.
149 sec is the security level, an integer from 0 to 3:
150 - 0: unauthenticated connection
151 - 1: try authenticated, then fall back to unauthenticated
152 - 2: fail if an authenticated connection can't be established
153 - 3: same as 2, plus encrypt all traffic to the protection
156 The realm attribute is the Kerberos realm against which this cell
159 cdef ubik_client * client
160 cdef readonly object cell
161 cdef readonly object realm
163 def __cinit__(self, cell=None, sec=1):
165 cdef afsconf_dir *cdir
166 cdef afsconf_cell info
167 cdef krb5_context context
168 cdef char ** hrealms = NULL
170 cdef ktc_principal prin
172 cdef rx_securityClass *sc
173 cdef rx_connection *serverconns[MAXSERVERS]
176 initialize_PT_error_table()
187 raise Exception(code, "Error initializing Rx")
189 cdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH)
192 "Error opening configuration directory (%s): %s" % \
193 (AFSDIR_CLIENT_ETC_DIRPATH, strerror(errno)))
194 code = afsconf_GetCellInfo(cdir, c_cell, "afsprot", &info)
197 code = krb5_init_context(&context)
199 code = krb5_get_host_realm(context, info.hostName[0], &hrealms)
201 self.realm = hrealms[0]
202 krb5_free_host_realm(context, hrealms)
203 krb5_free_context(context)
205 self.cell = info.name
208 strncpy(prin.cell, info.name, sizeof(prin.cell))
210 strncpy(prin.name, "afs", sizeof(prin.name))
212 code = ktc_GetToken(&prin, &token, sizeof(token), NULL);
215 # No really - we wanted authentication
223 sc = rxkad_NewClientSecurityObject(level, &token.sessionKey,
224 token.kvno, token.ticketLen,
228 sc = rxnull_NewClientSecurityObject()
232 memset(serverconns, 0, sizeof(serverconns))
233 for 0 <= i < info.numServers:
234 serverconns[i] = rx_NewConnection(info.hostAddr[i].sin_addr.s_addr,
235 info.hostAddr[i].sin_port,
240 code = ubik_ClientInit(serverconns, &self.client)
243 code = rxs_Release(sc)
245 def __dealloc__(self):
246 ubik_ClientDestroy(self.client)
249 def _NameOrId(self, ident):
251 Given an identifier, convert it to a PTS ID by looking up the
252 name if it's a string, or otherwise just converting it to an
255 if isinstance(ident, basestring):
256 return self._NameToId(ident)
260 def _NameToId(self, name):
262 Converts a user or group to an AFS ID.
266 cdef afs_int32 code, id = ANONYMOUSID
270 lids.idlist_val = NULL
271 lnames.namelist_len = 1
272 lnames.namelist_val = <prname *>malloc(PR_MAXNAMELEN)
273 strncpy(lnames.namelist_val[0], name, PR_MAXNAMELEN)
274 code = ubik_PR_NameToID(self.client, 0, &lnames, &lids)
275 if lids.idlist_val is not NULL:
276 id = lids.idlist_val[0]
277 free(lids.idlist_val)
278 if id == ANONYMOUSID:
283 def _IdToName(self, id):
285 Convert an AFS ID to the name of a user or group.
290 cdef char name[PR_MAXNAMELEN]
293 lids.idlist_val = <afs_int32 *>malloc(sizeof(afs_int32))
294 lids.idlist_val[0] = id
295 lnames.namelist_len = 0
296 lnames.namelist_val = NULL
297 code = ubik_PR_IDToName(self.client, 0, &lids, &lnames)
298 if lnames.namelist_val is not NULL:
299 strncpy(name, lnames.namelist_val[0], sizeof(name))
300 free(lnames.namelist_val)
301 if lids.idlist_val is not NULL:
302 free(lids.idlist_val)
308 def _CreateUser(self, name, id=None):
310 Create a new user in the protection database. If an ID is
311 provided, that one will be used.
315 name = name[:PR_MAXNAMELEN].lower()
321 code = ubik_PR_INewEntry(self.client, 0, name, cid, 0)
323 code = ubik_PR_NewEntry(self.client, 0, name, 0, 0, &cid)
328 def _CreateGroup(self, name, owner, id=None):
330 Create a new group in the protection database. If an ID is
331 provided, that one will be used.
333 cdef afs_int32 code, cid
335 name = name[:PR_MAXNAMELEN].lower()
336 oid = self._NameOrId(owner)
340 code = ubik_PR_INewEntry(self.client, 0, name, cid, oid)
342 code = ubik_PR_NewEntry(self.client, 0, name, PRGRP, oid, &cid)
347 def _Delete(self, ident):
349 Delete the protection database entry with the provided
353 cdef afs_int32 id = self._NameOrId(ident)
355 code = ubik_PR_Delete(self.client, 0, id)
358 def _AddToGroup(self, user, group):
360 Add the given user to the given group.
363 cdef afs_int32 uid = self._NameOrId(user), gid = self._NameOrId(group)
365 code = ubik_PR_AddToGroup(self.client, 0, uid, gid)
368 def _RemoveFromGroup(self, user, group):
370 Remove the given user from the given group.
373 cdef afs_int32 uid = self._NameOrId(user), gid = self._NameOrId(group)
375 code = ubik_PR_RemoveFromGroup(self.client, 0, uid, gid)
378 def _ListMembers(self, ident):
380 Get the membership of an entity.
382 If id is a group, this returns the users that are in that
385 If id is a user, this returns the list of groups that user is
388 This returns a list of PTS IDs.
390 cdef afs_int32 code, over
393 cdef object members = []
395 cdef afs_int32 id = self._NameOrId(ident)
398 alist.prlist_val = NULL
400 code = ubik_PR_ListElements(self.client, 0, id, &alist, &over)
402 if alist.prlist_val is not NULL:
403 for i in range(alist.prlist_len):
404 members.append(alist.prlist_val[i])
405 free(alist.prlist_val)
411 def _ListOwned(self, owner):
413 Get all groups owned by an entity.
415 cdef afs_int32 code, over
418 cdef object owned = []
420 cdef afs_int32 oid = self._NameOrId(owner)
423 alist.prlist_val = NULL
425 code = ubik_PR_ListOwned(self.client, 0, oid, &alist, &over)
427 if alist.prlist_val is not NULL:
428 for i in range(alist.prlist_len):
429 owned.append(alist.prlist_val[i])
430 free(alist.prlist_val)
436 def _ListEntry(self, ident):
438 Load a PTEntry instance with information about the provided
442 cdef prcheckentry centry
443 cdef object entry = PTEntry()
445 cdef afs_int32 id = self._NameOrId(ident)
447 code = ubik_PR_ListEntry(self.client, 0, id, ¢ry)
450 _ptentry_from_c(entry, ¢ry)
453 def _ChangeEntry(self, ident, newname=None, newid=None, newoid=None):
455 Change the name, ID, and/or owner of a PTS entity.
457 For any of newname, newid, and newoid which aren't specified
458 or ar None, the value isn't changed.
461 cdef afs_int32 c_newid = 0, c_newoid = 0
462 cdef char * c_newname
464 cdef afs_int32 id = self._NameOrId(ident)
467 newname = self._IdToName(id)
469 if newid is not None:
471 if newoid is not None:
474 code = ubik_PR_ChangeEntry(self.client, 0, id, c_newname, c_newoid, c_newid)
477 def _IsAMemberOf(self, user, group):
479 Return True if the given user is a member of the given group.
484 cdef afs_int32 uid = self._NameOrId(user), gid = self._NameOrId(group)
486 code = ubik_PR_IsAMemberOf(self.client, 0, uid, gid, &flag)
493 Return a tuple of the maximum user ID and the maximum group
494 ID currently assigned.
496 cdef afs_int32 code, uid, gid
498 code = ubik_PR_ListMax(self.client, 0, &uid, &gid)
503 def _SetMaxUserId(self, id):
505 Set the maximum currently assigned user ID (the next
506 automatically assigned UID will be id + 1)
510 code = ubik_PR_SetMax(self.client, 0, id, 0)
513 def _SetMaxGroupId(self, id):
515 Set the maximum currently assigned user ID (the next
516 automatically assigned UID will be id + 1)
520 code = ubik_PR_SetMax(self.client, 0, id, PRGRP)
523 def _ListEntries(self, users=None, groups=None):
525 Return a list of PTEntry instances representing all entries in
528 Returns just users by default, but can return just users, just
532 cdef afs_int32 flag = 0, startindex = 0, nentries, nextstartindex
533 cdef prentries centries
536 cdef object entries = []
538 if groups is None or users is True:
543 while startindex != -1:
544 centries.prentries_val = NULL
545 centries.prentries_len = 0
548 code = ubik_PR_ListEntries(self.client, 0, flag, startindex, ¢ries, &nextstartindex)
549 if centries.prentries_val is not NULL:
550 for i in range(centries.prentries_len):
552 _ptentry_from_c(e, <prcheckentry *>¢ries.prentries_val[i])
554 free(centries.prentries_val)
557 startindex = nextstartindex
561 def _SetFields(self, ident, access=None, groups=None, users=None):
563 Update the fields for an entry.
565 Valid fields are the privacy flags (access), the group quota
566 (groups), or the "foreign user quota" (users), which doesn't
567 actually seem to do anything, but is included for
571 cdef afs_int32 mask = 0, flags = 0, nusers = 0, ngroups = 0
573 cdef afs_int32 id = self._NameOrId(ident)
575 if access is not None:
577 mask |= PR_SF_ALLBITS
578 if groups is not None:
580 mask |= PR_SF_NGROUPS
581 if users is not None:
583 mask |= PR_SF_NGROUPS
585 code = ubik_PR_SetFieldsEntry(self.client, 0, id, mask, flags, ngroups, nusers, 0, 0)