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