1 | from afs._util cimport * |
---|
2 | from afs._util import pyafs_error |
---|
3 | import re |
---|
4 | |
---|
5 | cdef extern from "afs/ptuser.h": |
---|
6 | enum: |
---|
7 | PR_MAXNAMELEN |
---|
8 | PRGRP |
---|
9 | PRUSERS |
---|
10 | PRGROUPS |
---|
11 | ANONYMOUSID |
---|
12 | PR_SF_ALLBITS |
---|
13 | PR_SF_NGROUPS |
---|
14 | PR_SF_NUSERS |
---|
15 | |
---|
16 | ctypedef char prname[PR_MAXNAMELEN] |
---|
17 | |
---|
18 | struct namelist: |
---|
19 | unsigned int namelist_len |
---|
20 | prname *namelist_val |
---|
21 | |
---|
22 | struct prlist: |
---|
23 | unsigned int prlist_len |
---|
24 | afs_int32 *prlist_val |
---|
25 | |
---|
26 | struct idlist: |
---|
27 | unsigned int idlist_len |
---|
28 | afs_int32 *idlist_val |
---|
29 | |
---|
30 | struct prcheckentry: |
---|
31 | afs_int32 flags |
---|
32 | afs_int32 id |
---|
33 | afs_int32 owner |
---|
34 | afs_int32 creator |
---|
35 | afs_int32 ngroups |
---|
36 | afs_int32 nusers |
---|
37 | afs_int32 count |
---|
38 | char name[PR_MAXNAMELEN] |
---|
39 | |
---|
40 | struct prlistentries: |
---|
41 | afs_int32 flags |
---|
42 | afs_int32 id |
---|
43 | afs_int32 owner |
---|
44 | afs_int32 creator |
---|
45 | afs_int32 ngroups |
---|
46 | afs_int32 nusers |
---|
47 | afs_int32 count |
---|
48 | char name[PR_MAXNAMELEN] |
---|
49 | |
---|
50 | struct prentries: |
---|
51 | unsigned int prentries_len |
---|
52 | prlistentries *prentries_val |
---|
53 | |
---|
54 | int ubik_PR_NameToID(ubik_client *, afs_int32, namelist *, idlist *) |
---|
55 | int ubik_PR_IDToName(ubik_client *, afs_int32, idlist *, namelist *) |
---|
56 | int ubik_PR_INewEntry(ubik_client *, afs_int32, char *, afs_int32, afs_int32) |
---|
57 | int ubik_PR_NewEntry(ubik_client *, afs_int32, char *, afs_int32, afs_int32, afs_int32 *) |
---|
58 | int ubik_PR_Delete(ubik_client *, afs_int32, afs_int32) |
---|
59 | int ubik_PR_AddToGroup(ubik_client *, afs_int32, afs_int32, afs_int32) |
---|
60 | int ubik_PR_RemoveFromGroup(ubik_client *, afs_int32, afs_int32, afs_int32) |
---|
61 | int ubik_PR_ListElements(ubik_client *, afs_int32, afs_int32, prlist *, afs_int32 *) |
---|
62 | int ubik_PR_ListOwned(ubik_client *, afs_int32, afs_int32, prlist *, afs_int32 *) |
---|
63 | int ubik_PR_ListEntry(ubik_client *, afs_int32, afs_int32, prcheckentry *) |
---|
64 | int ubik_PR_ChangeEntry(ubik_client *, afs_int32, afs_int32, char *, afs_int32, afs_int32) |
---|
65 | int ubik_PR_IsAMemberOf(ubik_client *, afs_int32, afs_int32, afs_int32, afs_int32 *) |
---|
66 | int ubik_PR_ListMax(ubik_client *, afs_int32, afs_int32 *, afs_int32 *) |
---|
67 | int ubik_PR_SetMax(ubik_client *, afs_int32, afs_int32, afs_int32) |
---|
68 | int ubik_PR_ListEntries(ubik_client *, afs_int32, afs_int32, afs_int32, prentries *, afs_int32 *) |
---|
69 | int ubik_PR_SetFieldsEntry(ubik_client *, afs_int32, afs_int32, afs_int32, afs_int32, afs_int32, afs_int32, afs_int32, afs_int32) |
---|
70 | |
---|
71 | cdef extern from "afs/pterror.h": |
---|
72 | enum: |
---|
73 | PRNOENT |
---|
74 | |
---|
75 | cdef extern from "krb5/krb5.h": |
---|
76 | struct _krb5_context: |
---|
77 | pass |
---|
78 | struct krb5_principal_data: |
---|
79 | pass |
---|
80 | |
---|
81 | ctypedef _krb5_context * krb5_context |
---|
82 | ctypedef krb5_principal_data * krb5_principal |
---|
83 | |
---|
84 | ctypedef long krb5_int32 |
---|
85 | ctypedef krb5_int32 krb5_error_code |
---|
86 | krb5_error_code krb5_init_context(krb5_context *) |
---|
87 | krb5_error_code krb5_parse_name(krb5_context, char *, krb5_principal *) |
---|
88 | krb5_error_code krb5_unparse_name(krb5_context, krb5_principal, char **) |
---|
89 | krb5_error_code krb5_524_conv_principal(krb5_context, krb5_principal, char *, char *, char *) |
---|
90 | krb5_error_code krb5_425_conv_principal(krb5_context, char *, char *, char *, krb5_principal *) |
---|
91 | krb5_error_code krb5_get_host_realm(krb5_context, char *, char ***) |
---|
92 | void krb5_free_host_realm(krb5_context, char **) |
---|
93 | void krb5_free_principal(krb5_context, krb5_principal) |
---|
94 | void krb5_free_context(krb5_context) |
---|
95 | |
---|
96 | cdef class PTEntry: |
---|
97 | cdef public afs_int32 flags |
---|
98 | cdef public afs_int32 id |
---|
99 | cdef public afs_int32 owner |
---|
100 | cdef public afs_int32 creator |
---|
101 | cdef public afs_int32 ngroups |
---|
102 | cdef public afs_int32 nusers |
---|
103 | cdef public afs_int32 count |
---|
104 | cdef public object name |
---|
105 | |
---|
106 | def __repr__(self): |
---|
107 | if self.name != '': |
---|
108 | return '<PTEntry: %s>' % self.name |
---|
109 | else: |
---|
110 | return '<PTEntry: PTS ID %s>' % self.id |
---|
111 | |
---|
112 | cdef int _ptentry_from_c(PTEntry p_entry, prcheckentry * c_entry) except -1: |
---|
113 | if p_entry is None: |
---|
114 | raise TypeError |
---|
115 | return -1 |
---|
116 | |
---|
117 | p_entry.flags = c_entry.flags |
---|
118 | p_entry.id = c_entry.id |
---|
119 | p_entry.owner = c_entry.owner |
---|
120 | p_entry.creator = c_entry.creator |
---|
121 | p_entry.ngroups = c_entry.ngroups |
---|
122 | p_entry.nusers = c_entry.nusers |
---|
123 | p_entry.count = c_entry.count |
---|
124 | p_entry.name = c_entry.name |
---|
125 | return 0 |
---|
126 | |
---|
127 | cdef int _ptentry_to_c(prcheckentry * c_entry, PTEntry p_entry) except -1: |
---|
128 | if p_entry is None: |
---|
129 | raise TypeError |
---|
130 | return -1 |
---|
131 | |
---|
132 | c_entry.flags = p_entry.flags |
---|
133 | c_entry.id = p_entry.id |
---|
134 | c_entry.owner = p_entry.owner |
---|
135 | c_entry.creator = p_entry.creator |
---|
136 | c_entry.ngroups = p_entry.ngroups |
---|
137 | c_entry.nusers = p_entry.nusers |
---|
138 | c_entry.count = p_entry.count |
---|
139 | strncpy(c_entry.name, p_entry.name, sizeof(c_entry.name)) |
---|
140 | return 0 |
---|
141 | |
---|
142 | cdef object kname_re = re.compile(r'^([^.].*?)(?<!\\)(?:\.(.*?))?(?<!\\)@([^@]*)$') |
---|
143 | |
---|
144 | cdef object kname_parse(fullname): |
---|
145 | """Parse a krb4-style principal into a name, instance, and realm.""" |
---|
146 | cdef object re_match = kname_re.match(fullname) |
---|
147 | if not re_match: |
---|
148 | return None |
---|
149 | else: |
---|
150 | princ = re_match.groups() |
---|
151 | return tuple([re.sub(r'\\(.)', r'\1', x) if x else x for x in princ]) |
---|
152 | |
---|
153 | cdef object kname_unparse(name, inst, realm): |
---|
154 | """Unparse a name, instance, and realm into a single krb4 |
---|
155 | principal string.""" |
---|
156 | name = re.sub('r([.\\@])', r'\\\1', name) |
---|
157 | inst = re.sub('r([.\\@])', r'\\\1', inst) |
---|
158 | realm = re.sub(r'([\\@])', r'\\\1', realm) |
---|
159 | if inst: |
---|
160 | return '%s.%s@%s' % (name, inst, realm) |
---|
161 | else: |
---|
162 | return '%s@%s' % (name, realm) |
---|
163 | |
---|
164 | cdef class PTS: |
---|
165 | """ |
---|
166 | A PTS object is essentially a handle to talk to the server in a |
---|
167 | given cell. |
---|
168 | |
---|
169 | cell defaults to None. If no argument is passed for cell, PTS |
---|
170 | connects to the home cell. |
---|
171 | |
---|
172 | sec is the security level, an integer from 0 to 3: |
---|
173 | - 0: unauthenticated connection |
---|
174 | - 1: try authenticated, then fall back to unauthenticated |
---|
175 | - 2: fail if an authenticated connection can't be established |
---|
176 | - 3: same as 2, plus encrypt all traffic to the protection |
---|
177 | server |
---|
178 | |
---|
179 | The realm attribute is the Kerberos realm against which this cell |
---|
180 | authenticates. |
---|
181 | """ |
---|
182 | cdef ubik_client * client |
---|
183 | cdef readonly object cell |
---|
184 | cdef readonly object realm |
---|
185 | |
---|
186 | def __cinit__(self, cell=None, sec=1): |
---|
187 | cdef afs_int32 code |
---|
188 | cdef afsconf_dir *cdir |
---|
189 | cdef afsconf_cell info |
---|
190 | cdef krb5_context context |
---|
191 | cdef char ** hrealms = NULL |
---|
192 | cdef char * c_cell |
---|
193 | cdef ktc_principal prin |
---|
194 | cdef ktc_token token |
---|
195 | cdef rx_securityClass *sc |
---|
196 | cdef rx_connection *serverconns[MAXSERVERS] |
---|
197 | cdef int i |
---|
198 | |
---|
199 | initialize_PT_error_table() |
---|
200 | |
---|
201 | if cell is None: |
---|
202 | c_cell = NULL |
---|
203 | else: |
---|
204 | c_cell = cell |
---|
205 | |
---|
206 | self.client = NULL |
---|
207 | |
---|
208 | code = rx_Init(0) |
---|
209 | if code != 0: |
---|
210 | raise Exception(code, "Error initializing Rx") |
---|
211 | |
---|
212 | cdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH) |
---|
213 | if cdir is NULL: |
---|
214 | raise OSError(errno, |
---|
215 | "Error opening configuration directory (%s): %s" % \ |
---|
216 | (AFSDIR_CLIENT_ETC_DIRPATH, strerror(errno))) |
---|
217 | code = afsconf_GetCellInfo(cdir, c_cell, "afsprot", &info) |
---|
218 | pyafs_error(code) |
---|
219 | |
---|
220 | code = krb5_init_context(&context) |
---|
221 | pyafs_error(code) |
---|
222 | code = krb5_get_host_realm(context, info.hostName[0], &hrealms) |
---|
223 | pyafs_error(code) |
---|
224 | self.realm = hrealms[0] |
---|
225 | krb5_free_host_realm(context, hrealms) |
---|
226 | krb5_free_context(context) |
---|
227 | |
---|
228 | self.cell = info.name |
---|
229 | |
---|
230 | if sec > 0: |
---|
231 | strncpy(prin.cell, info.name, sizeof(prin.cell)) |
---|
232 | prin.instance[0] = 0 |
---|
233 | strncpy(prin.name, "afs", sizeof(prin.name)) |
---|
234 | |
---|
235 | code = ktc_GetToken(&prin, &token, sizeof(token), NULL); |
---|
236 | if code != 0: |
---|
237 | if sec >= 2: |
---|
238 | # No really - we wanted authentication |
---|
239 | pyafs_error(code) |
---|
240 | sec = 0 |
---|
241 | else: |
---|
242 | if sec == 3: |
---|
243 | level = rxkad_crypt |
---|
244 | else: |
---|
245 | level = rxkad_clear |
---|
246 | sc = rxkad_NewClientSecurityObject(level, &token.sessionKey, |
---|
247 | token.kvno, token.ticketLen, |
---|
248 | token.ticket) |
---|
249 | |
---|
250 | if sec == 0: |
---|
251 | sc = rxnull_NewClientSecurityObject() |
---|
252 | else: |
---|
253 | sec = 2 |
---|
254 | |
---|
255 | memset(serverconns, 0, sizeof(serverconns)) |
---|
256 | for 0 <= i < info.numServers: |
---|
257 | serverconns[i] = rx_NewConnection(info.hostAddr[i].sin_addr.s_addr, |
---|
258 | info.hostAddr[i].sin_port, |
---|
259 | PRSRV, |
---|
260 | sc, |
---|
261 | sec) |
---|
262 | |
---|
263 | code = ubik_ClientInit(serverconns, &self.client) |
---|
264 | pyafs_error(code) |
---|
265 | |
---|
266 | code = rxs_Release(sc) |
---|
267 | |
---|
268 | def __dealloc__(self): |
---|
269 | ubik_ClientDestroy(self.client) |
---|
270 | rx_Finalize() |
---|
271 | |
---|
272 | def _NameOrId(self, ident): |
---|
273 | """ |
---|
274 | Given an identifier, convert it to a PTS ID by looking up the |
---|
275 | name if it's a string, or otherwise just converting it to an |
---|
276 | integer. |
---|
277 | """ |
---|
278 | if isinstance(ident, basestring): |
---|
279 | return self._NameToId(ident) |
---|
280 | else: |
---|
281 | return int(ident) |
---|
282 | |
---|
283 | def _NameToId(self, name): |
---|
284 | """ |
---|
285 | Converts a user or group to an AFS ID. |
---|
286 | """ |
---|
287 | cdef namelist lnames |
---|
288 | cdef idlist lids |
---|
289 | cdef afs_int32 code, id = ANONYMOUSID |
---|
290 | name = name.lower() |
---|
291 | |
---|
292 | lids.idlist_len = 0 |
---|
293 | lids.idlist_val = NULL |
---|
294 | lnames.namelist_len = 1 |
---|
295 | lnames.namelist_val = <prname *>malloc(PR_MAXNAMELEN) |
---|
296 | strncpy(lnames.namelist_val[0], name, PR_MAXNAMELEN) |
---|
297 | code = ubik_PR_NameToID(self.client, 0, &lnames, &lids) |
---|
298 | if lids.idlist_val is not NULL: |
---|
299 | id = lids.idlist_val[0] |
---|
300 | free(lids.idlist_val) |
---|
301 | if id == ANONYMOUSID: |
---|
302 | code = PRNOENT |
---|
303 | pyafs_error(code) |
---|
304 | return id |
---|
305 | |
---|
306 | def _IdToName(self, id): |
---|
307 | """ |
---|
308 | Convert an AFS ID to the name of a user or group. |
---|
309 | """ |
---|
310 | cdef namelist lnames |
---|
311 | cdef idlist lids |
---|
312 | cdef afs_int32 code |
---|
313 | cdef char name[PR_MAXNAMELEN] |
---|
314 | |
---|
315 | lids.idlist_len = 1 |
---|
316 | lids.idlist_val = <afs_int32 *>malloc(sizeof(afs_int32)) |
---|
317 | lids.idlist_val[0] = id |
---|
318 | lnames.namelist_len = 0 |
---|
319 | lnames.namelist_val = NULL |
---|
320 | code = ubik_PR_IDToName(self.client, 0, &lids, &lnames) |
---|
321 | if lnames.namelist_val is not NULL: |
---|
322 | strncpy(name, lnames.namelist_val[0], sizeof(name)) |
---|
323 | free(lnames.namelist_val) |
---|
324 | if lids.idlist_val is not NULL: |
---|
325 | free(lids.idlist_val) |
---|
326 | if name == str(id): |
---|
327 | code = PRNOENT |
---|
328 | pyafs_error(code) |
---|
329 | return name |
---|
330 | |
---|
331 | def _CreateUser(self, name, id=None): |
---|
332 | """ |
---|
333 | Create a new user in the protection database. If an ID is |
---|
334 | provided, that one will be used. |
---|
335 | """ |
---|
336 | cdef afs_int32 code |
---|
337 | cdef afs_int32 cid |
---|
338 | name = name[:PR_MAXNAMELEN].lower() |
---|
339 | |
---|
340 | if id is not None: |
---|
341 | cid = id |
---|
342 | |
---|
343 | if id is not None: |
---|
344 | code = ubik_PR_INewEntry(self.client, 0, name, cid, 0) |
---|
345 | else: |
---|
346 | code = ubik_PR_NewEntry(self.client, 0, name, 0, 0, &cid) |
---|
347 | |
---|
348 | pyafs_error(code) |
---|
349 | return cid |
---|
350 | |
---|
351 | def _CreateGroup(self, name, owner, id=None): |
---|
352 | """ |
---|
353 | Create a new group in the protection database. If an ID is |
---|
354 | provided, that one will be used. |
---|
355 | """ |
---|
356 | cdef afs_int32 code, cid |
---|
357 | |
---|
358 | name = name[:PR_MAXNAMELEN].lower() |
---|
359 | oid = self._NameOrId(owner) |
---|
360 | |
---|
361 | if id is not None: |
---|
362 | cid = id |
---|
363 | code = ubik_PR_INewEntry(self.client, 0, name, cid, oid) |
---|
364 | else: |
---|
365 | code = ubik_PR_NewEntry(self.client, 0, name, PRGRP, oid, &cid) |
---|
366 | |
---|
367 | pyafs_error(code) |
---|
368 | return cid |
---|
369 | |
---|
370 | def _Delete(self, ident): |
---|
371 | """ |
---|
372 | Delete the protection database entry with the provided |
---|
373 | identifier. |
---|
374 | """ |
---|
375 | cdef afs_int32 code |
---|
376 | cdef afs_int32 id = self._NameOrId(ident) |
---|
377 | |
---|
378 | code = ubik_PR_Delete(self.client, 0, id) |
---|
379 | pyafs_error(code) |
---|
380 | |
---|
381 | def _AddToGroup(self, user, group): |
---|
382 | """ |
---|
383 | Add the given user to the given group. |
---|
384 | """ |
---|
385 | cdef afs_int32 code |
---|
386 | cdef afs_int32 uid = self._NameOrId(user), gid = self._NameOrId(group) |
---|
387 | |
---|
388 | code = ubik_PR_AddToGroup(self.client, 0, uid, gid) |
---|
389 | pyafs_error(code) |
---|
390 | |
---|
391 | def _RemoveFromGroup(self, user, group): |
---|
392 | """ |
---|
393 | Remove the given user from the given group. |
---|
394 | """ |
---|
395 | cdef afs_int32 code |
---|
396 | cdef afs_int32 uid = self._NameOrId(user), gid = self._NameOrId(group) |
---|
397 | |
---|
398 | code = ubik_PR_RemoveFromGroup(self.client, 0, uid, gid) |
---|
399 | pyafs_error(code) |
---|
400 | |
---|
401 | def _ListMembers(self, ident): |
---|
402 | """ |
---|
403 | Get the membership of an entity. |
---|
404 | |
---|
405 | If id is a group, this returns the users that are in that |
---|
406 | group. |
---|
407 | |
---|
408 | If id is a user, this returns the list of groups that user is |
---|
409 | on. |
---|
410 | |
---|
411 | This returns a list of PTS IDs. |
---|
412 | """ |
---|
413 | cdef afs_int32 code, over |
---|
414 | cdef prlist alist |
---|
415 | cdef int i |
---|
416 | cdef object members = [] |
---|
417 | |
---|
418 | cdef afs_int32 id = self._NameOrId(ident) |
---|
419 | |
---|
420 | alist.prlist_len = 0 |
---|
421 | alist.prlist_val = NULL |
---|
422 | |
---|
423 | code = ubik_PR_ListElements(self.client, 0, id, &alist, &over) |
---|
424 | |
---|
425 | if alist.prlist_val is not NULL: |
---|
426 | for i in range(alist.prlist_len): |
---|
427 | members.append(alist.prlist_val[i]) |
---|
428 | free(alist.prlist_val) |
---|
429 | |
---|
430 | pyafs_error(code) |
---|
431 | |
---|
432 | return members |
---|
433 | |
---|
434 | def _ListOwned(self, owner): |
---|
435 | """ |
---|
436 | Get all groups owned by an entity. |
---|
437 | """ |
---|
438 | cdef afs_int32 code, over |
---|
439 | cdef prlist alist |
---|
440 | cdef int i |
---|
441 | cdef object owned = [] |
---|
442 | |
---|
443 | cdef afs_int32 oid = self._NameOrId(owner) |
---|
444 | |
---|
445 | alist.prlist_len = 0 |
---|
446 | alist.prlist_val = NULL |
---|
447 | |
---|
448 | code = ubik_PR_ListOwned(self.client, 0, oid, &alist, &over) |
---|
449 | |
---|
450 | if alist.prlist_val is not NULL: |
---|
451 | for i in range(alist.prlist_len): |
---|
452 | owned.append(alist.prlist_val[i]) |
---|
453 | free(alist.prlist_val) |
---|
454 | |
---|
455 | pyafs_error(code) |
---|
456 | |
---|
457 | return owned |
---|
458 | |
---|
459 | def _ListEntry(self, ident): |
---|
460 | """ |
---|
461 | Load a PTEntry instance with information about the provided |
---|
462 | entity. |
---|
463 | """ |
---|
464 | cdef afs_int32 code |
---|
465 | cdef prcheckentry centry |
---|
466 | cdef object entry = PTEntry() |
---|
467 | |
---|
468 | cdef afs_int32 id = self._NameOrId(ident) |
---|
469 | |
---|
470 | code = ubik_PR_ListEntry(self.client, 0, id, ¢ry) |
---|
471 | pyafs_error(code) |
---|
472 | |
---|
473 | _ptentry_from_c(entry, ¢ry) |
---|
474 | return entry |
---|
475 | |
---|
476 | def _ChangeEntry(self, ident, newname=None, newid=None, newoid=None): |
---|
477 | """ |
---|
478 | Change the name, ID, and/or owner of a PTS entity. |
---|
479 | |
---|
480 | For any of newname, newid, and newoid which aren't specified |
---|
481 | or ar None, the value isn't changed. |
---|
482 | """ |
---|
483 | cdef afs_int32 code |
---|
484 | cdef afs_int32 c_newid = 0, c_newoid = 0 |
---|
485 | cdef char * c_newname |
---|
486 | |
---|
487 | cdef afs_int32 id = self._NameOrId(ident) |
---|
488 | |
---|
489 | if newname is None: |
---|
490 | newname = self._IdToName(id) |
---|
491 | c_newname = newname |
---|
492 | if newid is not None: |
---|
493 | c_newid = newid |
---|
494 | if newoid is not None: |
---|
495 | c_newoid = newoid |
---|
496 | |
---|
497 | code = ubik_PR_ChangeEntry(self.client, 0, id, c_newname, c_newoid, c_newid) |
---|
498 | pyafs_error(code) |
---|
499 | |
---|
500 | def _IsAMemberOf(self, user, group): |
---|
501 | """ |
---|
502 | Return True if the given user is a member of the given group. |
---|
503 | """ |
---|
504 | cdef afs_int32 code |
---|
505 | cdef afs_int32 flag |
---|
506 | |
---|
507 | cdef afs_int32 uid = self._NameOrId(user), gid = self._NameOrId(group) |
---|
508 | |
---|
509 | code = ubik_PR_IsAMemberOf(self.client, 0, uid, gid, &flag) |
---|
510 | pyafs_error(code) |
---|
511 | |
---|
512 | return bool(flag) |
---|
513 | |
---|
514 | def _ListMax(self): |
---|
515 | """ |
---|
516 | Return a tuple of the maximum user ID and the maximum group |
---|
517 | ID currently assigned. |
---|
518 | """ |
---|
519 | cdef afs_int32 code, uid, gid |
---|
520 | |
---|
521 | code = ubik_PR_ListMax(self.client, 0, &uid, &gid) |
---|
522 | pyafs_error(code) |
---|
523 | |
---|
524 | return (uid, gid) |
---|
525 | |
---|
526 | def _SetMaxUserId(self, id): |
---|
527 | """ |
---|
528 | Set the maximum currently assigned user ID (the next |
---|
529 | automatically assigned UID will be id + 1) |
---|
530 | """ |
---|
531 | cdef afs_int32 code |
---|
532 | |
---|
533 | code = ubik_PR_SetMax(self.client, 0, id, 0) |
---|
534 | pyafs_error(code) |
---|
535 | |
---|
536 | def _SetMaxGroupId(self, id): |
---|
537 | """ |
---|
538 | Set the maximum currently assigned user ID (the next |
---|
539 | automatically assigned UID will be id + 1) |
---|
540 | """ |
---|
541 | cdef afs_int32 code |
---|
542 | |
---|
543 | code = ubik_PR_SetMax(self.client, 0, id, PRGRP) |
---|
544 | pyafs_error(code) |
---|
545 | |
---|
546 | def _ListEntries(self, users=None, groups=None): |
---|
547 | """ |
---|
548 | Return a list of PTEntry instances representing all entries in |
---|
549 | the PRDB. |
---|
550 | |
---|
551 | Returns just users by default, but can return just users, just |
---|
552 | groups, or both. |
---|
553 | """ |
---|
554 | cdef afs_int32 code |
---|
555 | cdef afs_int32 flag = 0, startindex = 0, nentries, nextstartindex |
---|
556 | cdef prentries centries |
---|
557 | cdef unsigned int i |
---|
558 | |
---|
559 | cdef object entries = [] |
---|
560 | |
---|
561 | if groups is None or users is True: |
---|
562 | flag |= PRUSERS |
---|
563 | if groups: |
---|
564 | flag |= PRGROUPS |
---|
565 | |
---|
566 | while startindex != -1: |
---|
567 | centries.prentries_val = NULL |
---|
568 | centries.prentries_len = 0 |
---|
569 | nextstartindex = -1 |
---|
570 | |
---|
571 | code = ubik_PR_ListEntries(self.client, 0, flag, startindex, ¢ries, &nextstartindex) |
---|
572 | if centries.prentries_val is not NULL: |
---|
573 | for i in range(centries.prentries_len): |
---|
574 | e = PTEntry() |
---|
575 | _ptentry_from_c(e, <prcheckentry *>¢ries.prentries_val[i]) |
---|
576 | entries.append(e) |
---|
577 | free(centries.prentries_val) |
---|
578 | pyafs_error(code) |
---|
579 | |
---|
580 | startindex = nextstartindex |
---|
581 | |
---|
582 | return entries |
---|
583 | |
---|
584 | def _SetFields(self, ident, access=None, groups=None, users=None): |
---|
585 | """ |
---|
586 | Update the fields for an entry. |
---|
587 | |
---|
588 | Valid fields are the privacy flags (access), the group quota |
---|
589 | (groups), or the "foreign user quota" (users), which doesn't |
---|
590 | actually seem to do anything, but is included for |
---|
591 | completeness. |
---|
592 | """ |
---|
593 | cdef afs_int32 code |
---|
594 | cdef afs_int32 mask = 0, flags = 0, nusers = 0, ngroups = 0 |
---|
595 | |
---|
596 | cdef afs_int32 id = self._NameOrId(ident) |
---|
597 | |
---|
598 | if access is not None: |
---|
599 | flags = access |
---|
600 | mask |= PR_SF_ALLBITS |
---|
601 | if groups is not None: |
---|
602 | ngroups = groups |
---|
603 | mask |= PR_SF_NGROUPS |
---|
604 | if users is not None: |
---|
605 | nusers = users |
---|
606 | mask |= PR_SF_NGROUPS |
---|
607 | |
---|
608 | code = ubik_PR_SetFieldsEntry(self.client, 0, id, mask, flags, ngroups, nusers, 0, 0) |
---|
609 | pyafs_error(code) |
---|
610 | |
---|
611 | def _AfsToKrb5(self, afs_name): |
---|
612 | """Convert an AFS principal to a Kerberos v5 one.""" |
---|
613 | cdef krb5_context ctx = NULL |
---|
614 | cdef krb5_principal princ = NULL |
---|
615 | cdef krb5_error_code code = 0 |
---|
616 | cdef char * krb5_princ = NULL |
---|
617 | cdef char *name = NULL, *inst = NULL, *realm = NULL |
---|
618 | cdef object pname, pinst, prealm |
---|
619 | |
---|
620 | if '@' in afs_name: |
---|
621 | pname, prealm = afs_name.rsplit('@', 1) |
---|
622 | prealm = prealm.upper() |
---|
623 | krb4_name = '%s@%s' % (pname, prealm) |
---|
624 | else: |
---|
625 | krb4_name = '%s@%s' % (afs_name, self.realm) |
---|
626 | |
---|
627 | pname, pinst, prealm = kname_parse(krb4_name) |
---|
628 | if pname: |
---|
629 | name = pname |
---|
630 | if pinst: |
---|
631 | inst = pinst |
---|
632 | if prealm: |
---|
633 | realm = prealm |
---|
634 | |
---|
635 | code = krb5_init_context(&ctx) |
---|
636 | try: |
---|
637 | pyafs_error(code) |
---|
638 | |
---|
639 | code = krb5_425_conv_principal(ctx, name, inst, realm, &princ) |
---|
640 | try: |
---|
641 | pyafs_error(code) |
---|
642 | |
---|
643 | code = krb5_unparse_name(ctx, princ, &krb5_princ) |
---|
644 | try: |
---|
645 | pyafs_error(code) |
---|
646 | |
---|
647 | return krb5_princ |
---|
648 | finally: |
---|
649 | if krb5_princ is not NULL: |
---|
650 | free(krb5_princ) |
---|
651 | finally: |
---|
652 | if princ is not NULL: |
---|
653 | krb5_free_principal(ctx, princ) |
---|
654 | finally: |
---|
655 | if ctx is not NULL: |
---|
656 | krb5_free_context(ctx) |
---|
657 | |
---|
658 | def _Krb5ToAfs(self, krb5_name): |
---|
659 | """Convert a Kerberos v5 principal to an AFS one.""" |
---|
660 | cdef krb5_context ctx = NULL |
---|
661 | cdef krb5_principal k5_princ = NULL |
---|
662 | cdef char *k4_name, *k4_inst, *k4_realm |
---|
663 | cdef object afs_princ |
---|
664 | cdef object afs_name, afs_realm |
---|
665 | |
---|
666 | k4_name = <char *>malloc(40) |
---|
667 | k4_name[0] = '\0' |
---|
668 | k4_inst = <char *>malloc(40) |
---|
669 | k4_inst[0] = '\0' |
---|
670 | k4_realm = <char *>malloc(40) |
---|
671 | k4_realm[0] = '\0' |
---|
672 | |
---|
673 | code = krb5_init_context(&ctx) |
---|
674 | try: |
---|
675 | pyafs_error(code) |
---|
676 | |
---|
677 | code = krb5_parse_name(ctx, krb5_name, &k5_princ) |
---|
678 | try: |
---|
679 | pyafs_error(code) |
---|
680 | |
---|
681 | code = krb5_524_conv_principal(ctx, k5_princ, k4_name, k4_inst, k4_realm) |
---|
682 | pyafs_error(code) |
---|
683 | |
---|
684 | afs_princ = kname_unparse(k4_name, k4_inst, k4_realm) |
---|
685 | afs_name, afs_realm = afs_princ.rsplit('@', 1) |
---|
686 | |
---|
687 | if k4_realm == self.realm: |
---|
688 | return afs_name |
---|
689 | else: |
---|
690 | return '%s@%s' % (afs_name, afs_realm.lower()) |
---|
691 | finally: |
---|
692 | if k5_princ is not NULL: |
---|
693 | krb5_free_principal(ctx, k5_princ) |
---|
694 | finally: |
---|
695 | if ctx is not NULL: |
---|
696 | krb5_free_context(ctx) |
---|