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