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