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