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