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