[2599] | 1 | from afs._util cimport * |
---|
| 2 | from afs._util import pyafs_error |
---|
| 3 | import re |
---|
| 4 | |
---|
| 5 | cdef extern from "afs/ptuser.h": |
---|
| 6 | enum: |
---|
| 7 | PR_MAXNAMELEN |
---|
| 8 | PRGRP |
---|
| 9 | PRUSERS |
---|
| 10 | PRGROUPS |
---|
| 11 | ANONYMOUSID |
---|
| 12 | PR_SF_ALLBITS |
---|
| 13 | PR_SF_NGROUPS |
---|
| 14 | PR_SF_NUSERS |
---|
| 15 | |
---|
| 16 | ctypedef char prname[PR_MAXNAMELEN] |
---|
| 17 | |
---|
| 18 | struct namelist: |
---|
| 19 | unsigned int namelist_len |
---|
| 20 | prname *namelist_val |
---|
| 21 | |
---|
| 22 | struct prlist: |
---|
| 23 | unsigned int prlist_len |
---|
| 24 | afs_int32 *prlist_val |
---|
| 25 | |
---|
| 26 | struct idlist: |
---|
| 27 | unsigned int idlist_len |
---|
| 28 | afs_int32 *idlist_val |
---|
| 29 | |
---|
| 30 | struct prcheckentry: |
---|
| 31 | afs_int32 flags |
---|
| 32 | afs_int32 id |
---|
| 33 | afs_int32 owner |
---|
| 34 | afs_int32 creator |
---|
| 35 | afs_int32 ngroups |
---|
| 36 | afs_int32 nusers |
---|
| 37 | afs_int32 count |
---|
| 38 | char name[PR_MAXNAMELEN] |
---|
| 39 | |
---|
| 40 | struct prlistentries: |
---|
| 41 | afs_int32 flags |
---|
| 42 | afs_int32 id |
---|
| 43 | afs_int32 owner |
---|
| 44 | afs_int32 creator |
---|
| 45 | afs_int32 ngroups |
---|
| 46 | afs_int32 nusers |
---|
| 47 | afs_int32 count |
---|
| 48 | char name[PR_MAXNAMELEN] |
---|
| 49 | |
---|
| 50 | struct prentries: |
---|
| 51 | unsigned int prentries_len |
---|
| 52 | prlistentries *prentries_val |
---|
| 53 | |
---|
| 54 | int ubik_PR_NameToID(ubik_client *, afs_int32, namelist *, idlist *) |
---|
| 55 | int ubik_PR_IDToName(ubik_client *, afs_int32, idlist *, namelist *) |
---|
| 56 | int ubik_PR_INewEntry(ubik_client *, afs_int32, char *, afs_int32, afs_int32) |
---|
| 57 | int ubik_PR_NewEntry(ubik_client *, afs_int32, char *, afs_int32, afs_int32, afs_int32 *) |
---|
| 58 | int ubik_PR_Delete(ubik_client *, afs_int32, afs_int32) |
---|
| 59 | int ubik_PR_AddToGroup(ubik_client *, afs_int32, afs_int32, afs_int32) |
---|
| 60 | int ubik_PR_RemoveFromGroup(ubik_client *, afs_int32, afs_int32, afs_int32) |
---|
| 61 | int ubik_PR_ListElements(ubik_client *, afs_int32, afs_int32, prlist *, afs_int32 *) |
---|
| 62 | int ubik_PR_ListOwned(ubik_client *, afs_int32, afs_int32, prlist *, afs_int32 *) |
---|
| 63 | int ubik_PR_ListEntry(ubik_client *, afs_int32, afs_int32, prcheckentry *) |
---|
| 64 | int ubik_PR_ChangeEntry(ubik_client *, afs_int32, afs_int32, char *, afs_int32, afs_int32) |
---|
| 65 | int ubik_PR_IsAMemberOf(ubik_client *, afs_int32, afs_int32, afs_int32, afs_int32 *) |
---|
| 66 | int ubik_PR_ListMax(ubik_client *, afs_int32, afs_int32 *, afs_int32 *) |
---|
| 67 | int ubik_PR_SetMax(ubik_client *, afs_int32, afs_int32, afs_int32) |
---|
| 68 | int ubik_PR_ListEntries(ubik_client *, afs_int32, afs_int32, afs_int32, prentries *, afs_int32 *) |
---|
| 69 | int ubik_PR_SetFieldsEntry(ubik_client *, afs_int32, afs_int32, afs_int32, afs_int32, afs_int32, afs_int32, afs_int32, afs_int32) |
---|
| 70 | |
---|
| 71 | cdef extern from "afs/pterror.h": |
---|
| 72 | enum: |
---|
| 73 | PRNOENT |
---|
| 74 | |
---|
| 75 | cdef extern from "krb5/krb5.h": |
---|
| 76 | struct _krb5_context: |
---|
| 77 | pass |
---|
| 78 | struct krb5_principal_data: |
---|
| 79 | pass |
---|
| 80 | |
---|
| 81 | ctypedef _krb5_context * krb5_context |
---|
| 82 | ctypedef krb5_principal_data * krb5_principal |
---|
| 83 | |
---|
| 84 | ctypedef long krb5_int32 |
---|
| 85 | ctypedef krb5_int32 krb5_error_code |
---|
| 86 | krb5_error_code krb5_init_context(krb5_context *) |
---|
| 87 | krb5_error_code krb5_parse_name(krb5_context, char *, krb5_principal *) |
---|
| 88 | krb5_error_code krb5_unparse_name(krb5_context, krb5_principal, char **) |
---|
| 89 | krb5_error_code krb5_524_conv_principal(krb5_context, krb5_principal, char *, char *, char *) |
---|
| 90 | krb5_error_code krb5_425_conv_principal(krb5_context, char *, char *, char *, krb5_principal *) |
---|
| 91 | krb5_error_code krb5_get_host_realm(krb5_context, char *, char ***) |
---|
| 92 | void krb5_free_host_realm(krb5_context, char **) |
---|
| 93 | void krb5_free_principal(krb5_context, krb5_principal) |
---|
| 94 | void krb5_free_context(krb5_context) |
---|
| 95 | |
---|
| 96 | cdef class PTEntry: |
---|
| 97 | cdef public afs_int32 flags |
---|
| 98 | cdef public afs_int32 id |
---|
| 99 | cdef public afs_int32 owner |
---|
| 100 | cdef public afs_int32 creator |
---|
| 101 | cdef public afs_int32 ngroups |
---|
| 102 | cdef public afs_int32 nusers |
---|
| 103 | cdef public afs_int32 count |
---|
| 104 | cdef public object name |
---|
| 105 | |
---|
| 106 | def __repr__(self): |
---|
| 107 | if self.name != '': |
---|
| 108 | return '<PTEntry: %s>' % self.name |
---|
| 109 | else: |
---|
| 110 | return '<PTEntry: PTS ID %s>' % self.id |
---|
| 111 | |
---|
| 112 | cdef int _ptentry_from_c(PTEntry p_entry, prcheckentry * c_entry) except -1: |
---|
| 113 | if p_entry is None: |
---|
| 114 | raise TypeError |
---|
| 115 | return -1 |
---|
| 116 | |
---|
| 117 | p_entry.flags = c_entry.flags |
---|
| 118 | p_entry.id = c_entry.id |
---|
| 119 | p_entry.owner = c_entry.owner |
---|
| 120 | p_entry.creator = c_entry.creator |
---|
| 121 | p_entry.ngroups = c_entry.ngroups |
---|
| 122 | p_entry.nusers = c_entry.nusers |
---|
| 123 | p_entry.count = c_entry.count |
---|
| 124 | p_entry.name = c_entry.name |
---|
| 125 | return 0 |
---|
| 126 | |
---|
| 127 | cdef int _ptentry_to_c(prcheckentry * c_entry, PTEntry p_entry) except -1: |
---|
| 128 | if p_entry is None: |
---|
| 129 | raise TypeError |
---|
| 130 | return -1 |
---|
| 131 | |
---|
| 132 | c_entry.flags = p_entry.flags |
---|
| 133 | c_entry.id = p_entry.id |
---|
| 134 | c_entry.owner = p_entry.owner |
---|
| 135 | c_entry.creator = p_entry.creator |
---|
| 136 | c_entry.ngroups = p_entry.ngroups |
---|
| 137 | c_entry.nusers = p_entry.nusers |
---|
| 138 | c_entry.count = p_entry.count |
---|
| 139 | strncpy(c_entry.name, p_entry.name, sizeof(c_entry.name)) |
---|
| 140 | return 0 |
---|
| 141 | |
---|
| 142 | cdef object kname_re = re.compile(r'^([^.].*?)(?<!\\)(?:\.(.*?))?(?<!\\)@([^@]*)$') |
---|
| 143 | |
---|
| 144 | cdef object kname_parse(fullname): |
---|
| 145 | """Parse a krb4-style principal into a name, instance, and realm.""" |
---|
| 146 | cdef object re_match = kname_re.match(fullname) |
---|
| 147 | if not re_match: |
---|
| 148 | return None |
---|
| 149 | else: |
---|
| 150 | princ = re_match.groups() |
---|
| 151 | return tuple([re.sub(r'\\(.)', r'\1', x) if x else x for x in princ]) |
---|
| 152 | |
---|
| 153 | cdef object kname_unparse(name, inst, realm): |
---|
| 154 | """Unparse a name, instance, and realm into a single krb4 |
---|
| 155 | principal string.""" |
---|
| 156 | name = re.sub('r([.\\@])', r'\\\1', name) |
---|
| 157 | inst = re.sub('r([.\\@])', r'\\\1', inst) |
---|
| 158 | realm = re.sub(r'([\\@])', r'\\\1', realm) |
---|
| 159 | if inst: |
---|
| 160 | return '%s.%s@%s' % (name, inst, realm) |
---|
| 161 | else: |
---|
| 162 | return '%s@%s' % (name, realm) |
---|
| 163 | |
---|
| 164 | cdef class PTS: |
---|
| 165 | """ |
---|
| 166 | A PTS object is essentially a handle to talk to the server in a |
---|
| 167 | given cell. |
---|
| 168 | |
---|
| 169 | cell defaults to None. If no argument is passed for cell, PTS |
---|
| 170 | connects to the home cell. |
---|
| 171 | |
---|
| 172 | sec is the security level, an integer from 0 to 3: |
---|
| 173 | - 0: unauthenticated connection |
---|
| 174 | - 1: try authenticated, then fall back to unauthenticated |
---|
| 175 | - 2: fail if an authenticated connection can't be established |
---|
| 176 | - 3: same as 2, plus encrypt all traffic to the protection |
---|
| 177 | server |
---|
| 178 | |
---|
| 179 | The realm attribute is the Kerberos realm against which this cell |
---|
| 180 | authenticates. |
---|
| 181 | """ |
---|
| 182 | cdef ubik_client * client |
---|
| 183 | cdef readonly object cell |
---|
| 184 | cdef readonly object realm |
---|
| 185 | |
---|
| 186 | def __cinit__(self, cell=None, sec=1): |
---|
| 187 | cdef afs_int32 code |
---|
| 188 | cdef afsconf_dir *cdir |
---|
| 189 | cdef afsconf_cell info |
---|
| 190 | cdef krb5_context context |
---|
| 191 | cdef char ** hrealms = NULL |
---|
| 192 | cdef char * c_cell |
---|
| 193 | cdef ktc_principal prin |
---|
| 194 | cdef ktc_token token |
---|
| 195 | cdef rx_securityClass *sc |
---|
| 196 | cdef rx_connection *serverconns[MAXSERVERS] |
---|
| 197 | cdef int i |
---|
| 198 | |
---|
| 199 | initialize_PT_error_table() |
---|
| 200 | |
---|
| 201 | if cell is None: |
---|
| 202 | c_cell = NULL |
---|
| 203 | else: |
---|
| 204 | c_cell = cell |
---|
| 205 | |
---|
| 206 | self.client = NULL |
---|
| 207 | |
---|
| 208 | code = rx_Init(0) |
---|
| 209 | if code != 0: |
---|
| 210 | raise Exception(code, "Error initializing Rx") |
---|
| 211 | |
---|
| 212 | cdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH) |
---|
| 213 | if cdir is NULL: |
---|
| 214 | raise OSError(errno, |
---|
| 215 | "Error opening configuration directory (%s): %s" % \ |
---|
| 216 | (AFSDIR_CLIENT_ETC_DIRPATH, strerror(errno))) |
---|
| 217 | code = afsconf_GetCellInfo(cdir, c_cell, "afsprot", &info) |
---|
| 218 | pyafs_error(code) |
---|
| 219 | |
---|
| 220 | code = krb5_init_context(&context) |
---|
| 221 | pyafs_error(code) |
---|
| 222 | code = krb5_get_host_realm(context, info.hostName[0], &hrealms) |
---|
| 223 | pyafs_error(code) |
---|
| 224 | self.realm = hrealms[0] |
---|
| 225 | krb5_free_host_realm(context, hrealms) |
---|
| 226 | krb5_free_context(context) |
---|
| 227 | |
---|
| 228 | self.cell = info.name |
---|
| 229 | |
---|
| 230 | if sec > 0: |
---|
| 231 | strncpy(prin.cell, info.name, sizeof(prin.cell)) |
---|
| 232 | prin.instance[0] = 0 |
---|
| 233 | strncpy(prin.name, "afs", sizeof(prin.name)) |
---|
| 234 | |
---|
| 235 | code = ktc_GetToken(&prin, &token, sizeof(token), NULL); |
---|
| 236 | if code != 0: |
---|
| 237 | if sec >= 2: |
---|
| 238 | # No really - we wanted authentication |
---|
| 239 | pyafs_error(code) |
---|
| 240 | sec = 0 |
---|
| 241 | else: |
---|
| 242 | if sec == 3: |
---|
| 243 | level = rxkad_crypt |
---|
| 244 | else: |
---|
| 245 | level = rxkad_clear |
---|
| 246 | sc = rxkad_NewClientSecurityObject(level, &token.sessionKey, |
---|
| 247 | token.kvno, token.ticketLen, |
---|
| 248 | token.ticket) |
---|
| 249 | |
---|
| 250 | if sec == 0: |
---|
| 251 | sc = rxnull_NewClientSecurityObject() |
---|
| 252 | else: |
---|
| 253 | sec = 2 |
---|
| 254 | |
---|
| 255 | memset(serverconns, 0, sizeof(serverconns)) |
---|
| 256 | for 0 <= i < info.numServers: |
---|
| 257 | serverconns[i] = rx_NewConnection(info.hostAddr[i].sin_addr.s_addr, |
---|
| 258 | info.hostAddr[i].sin_port, |
---|
| 259 | PRSRV, |
---|
| 260 | sc, |
---|
| 261 | sec) |
---|
| 262 | |
---|
| 263 | code = ubik_ClientInit(serverconns, &self.client) |
---|
| 264 | pyafs_error(code) |
---|
| 265 | |
---|
| 266 | code = rxs_Release(sc) |
---|
| 267 | |
---|
| 268 | def __dealloc__(self): |
---|
| 269 | ubik_ClientDestroy(self.client) |
---|
| 270 | rx_Finalize() |
---|
| 271 | |
---|
| 272 | def _NameOrId(self, ident): |
---|
| 273 | """ |
---|
| 274 | Given an identifier, convert it to a PTS ID by looking up the |
---|
| 275 | name if it's a string, or otherwise just converting it to an |
---|
| 276 | integer. |
---|
| 277 | """ |
---|
| 278 | if isinstance(ident, basestring): |
---|
| 279 | return self._NameToId(ident) |
---|
| 280 | else: |
---|
| 281 | return int(ident) |
---|
| 282 | |
---|
| 283 | def _NameToId(self, name): |
---|
| 284 | """ |
---|
| 285 | Converts a user or group to an AFS ID. |
---|
| 286 | """ |
---|
| 287 | cdef namelist lnames |
---|
| 288 | cdef idlist lids |
---|
| 289 | cdef afs_int32 code, id = ANONYMOUSID |
---|
| 290 | name = name.lower() |
---|
| 291 | |
---|
| 292 | lids.idlist_len = 0 |
---|
| 293 | lids.idlist_val = NULL |
---|
| 294 | lnames.namelist_len = 1 |
---|
| 295 | lnames.namelist_val = <prname *>malloc(PR_MAXNAMELEN) |
---|
| 296 | strncpy(lnames.namelist_val[0], name, PR_MAXNAMELEN) |
---|
| 297 | code = ubik_PR_NameToID(self.client, 0, &lnames, &lids) |
---|
| 298 | if lids.idlist_val is not NULL: |
---|
| 299 | id = lids.idlist_val[0] |
---|
| 300 | free(lids.idlist_val) |
---|
| 301 | if id == ANONYMOUSID: |
---|
| 302 | code = PRNOENT |
---|
| 303 | pyafs_error(code) |
---|
| 304 | return id |
---|
| 305 | |
---|
| 306 | def _IdToName(self, id): |
---|
| 307 | """ |
---|
| 308 | Convert an AFS ID to the name of a user or group. |
---|
| 309 | """ |
---|
| 310 | cdef namelist lnames |
---|
| 311 | cdef idlist lids |
---|
| 312 | cdef afs_int32 code |
---|
| 313 | cdef char name[PR_MAXNAMELEN] |
---|
| 314 | |
---|
| 315 | lids.idlist_len = 1 |
---|
| 316 | lids.idlist_val = <afs_int32 *>malloc(sizeof(afs_int32)) |
---|
| 317 | lids.idlist_val[0] = id |
---|
| 318 | lnames.namelist_len = 0 |
---|
| 319 | lnames.namelist_val = NULL |
---|
| 320 | code = ubik_PR_IDToName(self.client, 0, &lids, &lnames) |
---|
| 321 | if lnames.namelist_val is not NULL: |
---|
| 322 | strncpy(name, lnames.namelist_val[0], sizeof(name)) |
---|
| 323 | free(lnames.namelist_val) |
---|
| 324 | if lids.idlist_val is not NULL: |
---|
| 325 | free(lids.idlist_val) |
---|
| 326 | if name == str(id): |
---|
| 327 | code = PRNOENT |
---|
| 328 | pyafs_error(code) |
---|
| 329 | return name |
---|
| 330 | |
---|
| 331 | def _CreateUser(self, name, id=None): |
---|
| 332 | """ |
---|
| 333 | Create a new user in the protection database. If an ID is |
---|
| 334 | provided, that one will be used. |
---|
| 335 | """ |
---|
| 336 | cdef afs_int32 code |
---|
| 337 | cdef afs_int32 cid |
---|
| 338 | name = name[:PR_MAXNAMELEN].lower() |
---|
| 339 | |
---|
| 340 | if id is not None: |
---|
| 341 | cid = id |
---|
| 342 | |
---|
| 343 | if id is not None: |
---|
| 344 | code = ubik_PR_INewEntry(self.client, 0, name, cid, 0) |
---|
| 345 | else: |
---|
| 346 | code = ubik_PR_NewEntry(self.client, 0, name, 0, 0, &cid) |
---|
| 347 | |
---|
| 348 | pyafs_error(code) |
---|
| 349 | return cid |
---|
| 350 | |
---|
| 351 | def _CreateGroup(self, name, owner, id=None): |
---|
| 352 | """ |
---|
| 353 | Create a new group in the protection database. If an ID is |
---|
| 354 | provided, that one will be used. |
---|
| 355 | """ |
---|
| 356 | cdef afs_int32 code, cid |
---|
| 357 | |
---|
| 358 | name = name[:PR_MAXNAMELEN].lower() |
---|
| 359 | oid = self._NameOrId(owner) |
---|
| 360 | |
---|
| 361 | if id is not None: |
---|
| 362 | cid = id |
---|
| 363 | code = ubik_PR_INewEntry(self.client, 0, name, cid, oid) |
---|
| 364 | else: |
---|
| 365 | code = ubik_PR_NewEntry(self.client, 0, name, PRGRP, oid, &cid) |
---|
| 366 | |
---|
| 367 | pyafs_error(code) |
---|
| 368 | return cid |
---|
| 369 | |
---|
| 370 | def _Delete(self, ident): |
---|
| 371 | """ |
---|
| 372 | Delete the protection database entry with the provided |
---|
| 373 | identifier. |
---|
| 374 | """ |
---|
| 375 | cdef afs_int32 code |
---|
| 376 | cdef afs_int32 id = self._NameOrId(ident) |
---|
| 377 | |
---|
| 378 | code = ubik_PR_Delete(self.client, 0, id) |
---|
| 379 | pyafs_error(code) |
---|
| 380 | |
---|
| 381 | def _AddToGroup(self, user, group): |
---|
| 382 | """ |
---|
| 383 | Add the given user to the given group. |
---|
| 384 | """ |
---|
| 385 | cdef afs_int32 code |
---|
| 386 | cdef afs_int32 uid = self._NameOrId(user), gid = self._NameOrId(group) |
---|
| 387 | |
---|
| 388 | code = ubik_PR_AddToGroup(self.client, 0, uid, gid) |
---|
| 389 | pyafs_error(code) |
---|
| 390 | |
---|
| 391 | def _RemoveFromGroup(self, user, group): |
---|
| 392 | """ |
---|
| 393 | Remove the given user from the given group. |
---|
| 394 | """ |
---|
| 395 | cdef afs_int32 code |
---|
| 396 | cdef afs_int32 uid = self._NameOrId(user), gid = self._NameOrId(group) |
---|
| 397 | |
---|
| 398 | code = ubik_PR_RemoveFromGroup(self.client, 0, uid, gid) |
---|
| 399 | pyafs_error(code) |
---|
| 400 | |
---|
| 401 | def _ListMembers(self, ident): |
---|
| 402 | """ |
---|
| 403 | Get the membership of an entity. |
---|
| 404 | |
---|
| 405 | If id is a group, this returns the users that are in that |
---|
| 406 | group. |
---|
| 407 | |
---|
| 408 | If id is a user, this returns the list of groups that user is |
---|
| 409 | on. |
---|
| 410 | |
---|
| 411 | This returns a list of PTS IDs. |
---|
| 412 | """ |
---|
| 413 | cdef afs_int32 code, over |
---|
| 414 | cdef prlist alist |
---|
| 415 | cdef int i |
---|
| 416 | cdef object members = [] |
---|
| 417 | |
---|
| 418 | cdef afs_int32 id = self._NameOrId(ident) |
---|
| 419 | |
---|
| 420 | alist.prlist_len = 0 |
---|
| 421 | alist.prlist_val = NULL |
---|
| 422 | |
---|
| 423 | code = ubik_PR_ListElements(self.client, 0, id, &alist, &over) |
---|
| 424 | |
---|
| 425 | if alist.prlist_val is not NULL: |
---|
| 426 | for i in range(alist.prlist_len): |
---|
| 427 | members.append(alist.prlist_val[i]) |
---|
| 428 | free(alist.prlist_val) |
---|
| 429 | |
---|
| 430 | pyafs_error(code) |
---|
| 431 | |
---|
| 432 | return members |
---|
| 433 | |
---|
| 434 | def _ListOwned(self, owner): |
---|
| 435 | """ |
---|
| 436 | Get all groups owned by an entity. |
---|
| 437 | """ |
---|
| 438 | cdef afs_int32 code, over |
---|
| 439 | cdef prlist alist |
---|
| 440 | cdef int i |
---|
| 441 | cdef object owned = [] |
---|
| 442 | |
---|
| 443 | cdef afs_int32 oid = self._NameOrId(owner) |
---|
| 444 | |
---|
| 445 | alist.prlist_len = 0 |
---|
| 446 | alist.prlist_val = NULL |
---|
| 447 | |
---|
| 448 | code = ubik_PR_ListOwned(self.client, 0, oid, &alist, &over) |
---|
| 449 | |
---|
| 450 | if alist.prlist_val is not NULL: |
---|
| 451 | for i in range(alist.prlist_len): |
---|
| 452 | owned.append(alist.prlist_val[i]) |
---|
| 453 | free(alist.prlist_val) |
---|
| 454 | |
---|
| 455 | pyafs_error(code) |
---|
| 456 | |
---|
| 457 | return owned |
---|
| 458 | |
---|
| 459 | def _ListEntry(self, ident): |
---|
| 460 | """ |
---|
| 461 | Load a PTEntry instance with information about the provided |
---|
| 462 | entity. |
---|
| 463 | """ |
---|
| 464 | cdef afs_int32 code |
---|
| 465 | cdef prcheckentry centry |
---|
| 466 | cdef object entry = PTEntry() |
---|
| 467 | |
---|
| 468 | cdef afs_int32 id = self._NameOrId(ident) |
---|
| 469 | |
---|
| 470 | code = ubik_PR_ListEntry(self.client, 0, id, ¢ry) |
---|
| 471 | pyafs_error(code) |
---|
| 472 | |
---|
| 473 | _ptentry_from_c(entry, ¢ry) |
---|
| 474 | return entry |
---|
| 475 | |
---|
| 476 | def _ChangeEntry(self, ident, newname=None, newid=None, newoid=None): |
---|
| 477 | """ |
---|
| 478 | Change the name, ID, and/or owner of a PTS entity. |
---|
| 479 | |
---|
| 480 | For any of newname, newid, and newoid which aren't specified |
---|
| 481 | or ar None, the value isn't changed. |
---|
| 482 | """ |
---|
| 483 | cdef afs_int32 code |
---|
| 484 | cdef afs_int32 c_newid = 0, c_newoid = 0 |
---|
| 485 | cdef char * c_newname |
---|
| 486 | |
---|
| 487 | cdef afs_int32 id = self._NameOrId(ident) |
---|
| 488 | |
---|
| 489 | if newname is None: |
---|
| 490 | newname = self._IdToName(id) |
---|
| 491 | c_newname = newname |
---|
| 492 | if newid is not None: |
---|
| 493 | c_newid = newid |
---|
| 494 | if newoid is not None: |
---|
| 495 | c_newoid = newoid |
---|
| 496 | |
---|
| 497 | code = ubik_PR_ChangeEntry(self.client, 0, id, c_newname, c_newoid, c_newid) |
---|
| 498 | pyafs_error(code) |
---|
| 499 | |
---|
| 500 | def _IsAMemberOf(self, user, group): |
---|
| 501 | """ |
---|
| 502 | Return True if the given user is a member of the given group. |
---|
| 503 | """ |
---|
| 504 | cdef afs_int32 code |
---|
| 505 | cdef afs_int32 flag |
---|
| 506 | |
---|
| 507 | cdef afs_int32 uid = self._NameOrId(user), gid = self._NameOrId(group) |
---|
| 508 | |
---|
| 509 | code = ubik_PR_IsAMemberOf(self.client, 0, uid, gid, &flag) |
---|
| 510 | pyafs_error(code) |
---|
| 511 | |
---|
| 512 | return bool(flag) |
---|
| 513 | |
---|
| 514 | def _ListMax(self): |
---|
| 515 | """ |
---|
| 516 | Return a tuple of the maximum user ID and the maximum group |
---|
| 517 | ID currently assigned. |
---|
| 518 | """ |
---|
| 519 | cdef afs_int32 code, uid, gid |
---|
| 520 | |
---|
| 521 | code = ubik_PR_ListMax(self.client, 0, &uid, &gid) |
---|
| 522 | pyafs_error(code) |
---|
| 523 | |
---|
| 524 | return (uid, gid) |
---|
| 525 | |
---|
| 526 | def _SetMaxUserId(self, id): |
---|
| 527 | """ |
---|
| 528 | Set the maximum currently assigned user ID (the next |
---|
| 529 | automatically assigned UID will be id + 1) |
---|
| 530 | """ |
---|
| 531 | cdef afs_int32 code |
---|
| 532 | |
---|
| 533 | code = ubik_PR_SetMax(self.client, 0, id, 0) |
---|
| 534 | pyafs_error(code) |
---|
| 535 | |
---|
| 536 | def _SetMaxGroupId(self, id): |
---|
| 537 | """ |
---|
| 538 | Set the maximum currently assigned user ID (the next |
---|
| 539 | automatically assigned UID will be id + 1) |
---|
| 540 | """ |
---|
| 541 | cdef afs_int32 code |
---|
| 542 | |
---|
| 543 | code = ubik_PR_SetMax(self.client, 0, id, PRGRP) |
---|
| 544 | pyafs_error(code) |
---|
| 545 | |
---|
| 546 | def _ListEntries(self, users=None, groups=None): |
---|
| 547 | """ |
---|
| 548 | Return a list of PTEntry instances representing all entries in |
---|
| 549 | the PRDB. |
---|
| 550 | |
---|
| 551 | Returns just users by default, but can return just users, just |
---|
| 552 | groups, or both. |
---|
| 553 | """ |
---|
| 554 | cdef afs_int32 code |
---|
| 555 | cdef afs_int32 flag = 0, startindex = 0, nentries, nextstartindex |
---|
| 556 | cdef prentries centries |
---|
| 557 | cdef unsigned int i |
---|
| 558 | |
---|
| 559 | cdef object entries = [] |
---|
| 560 | |
---|
| 561 | if groups is None or users is True: |
---|
| 562 | flag |= PRUSERS |
---|
| 563 | if groups: |
---|
| 564 | flag |= PRGROUPS |
---|
| 565 | |
---|
| 566 | while startindex != -1: |
---|
| 567 | centries.prentries_val = NULL |
---|
| 568 | centries.prentries_len = 0 |
---|
| 569 | nextstartindex = -1 |
---|
| 570 | |
---|
| 571 | code = ubik_PR_ListEntries(self.client, 0, flag, startindex, ¢ries, &nextstartindex) |
---|
| 572 | if centries.prentries_val is not NULL: |
---|
| 573 | for i in range(centries.prentries_len): |
---|
| 574 | e = PTEntry() |
---|
| 575 | _ptentry_from_c(e, <prcheckentry *>¢ries.prentries_val[i]) |
---|
| 576 | entries.append(e) |
---|
| 577 | free(centries.prentries_val) |
---|
| 578 | pyafs_error(code) |
---|
| 579 | |
---|
| 580 | startindex = nextstartindex |
---|
| 581 | |
---|
| 582 | return entries |
---|
| 583 | |
---|
| 584 | def _SetFields(self, ident, access=None, groups=None, users=None): |
---|
| 585 | """ |
---|
| 586 | Update the fields for an entry. |
---|
| 587 | |
---|
| 588 | Valid fields are the privacy flags (access), the group quota |
---|
| 589 | (groups), or the "foreign user quota" (users), which doesn't |
---|
| 590 | actually seem to do anything, but is included for |
---|
| 591 | completeness. |
---|
| 592 | """ |
---|
| 593 | cdef afs_int32 code |
---|
| 594 | cdef afs_int32 mask = 0, flags = 0, nusers = 0, ngroups = 0 |
---|
| 595 | |
---|
| 596 | cdef afs_int32 id = self._NameOrId(ident) |
---|
| 597 | |
---|
| 598 | if access is not None: |
---|
| 599 | flags = access |
---|
| 600 | mask |= PR_SF_ALLBITS |
---|
| 601 | if groups is not None: |
---|
| 602 | ngroups = groups |
---|
| 603 | mask |= PR_SF_NGROUPS |
---|
| 604 | if users is not None: |
---|
| 605 | nusers = users |
---|
| 606 | mask |= PR_SF_NGROUPS |
---|
| 607 | |
---|
| 608 | code = ubik_PR_SetFieldsEntry(self.client, 0, id, mask, flags, ngroups, nusers, 0, 0) |
---|
| 609 | pyafs_error(code) |
---|
| 610 | |
---|
| 611 | def _AfsToKrb5(self, afs_name): |
---|
| 612 | """Convert an AFS principal to a Kerberos v5 one.""" |
---|
| 613 | cdef krb5_context ctx = NULL |
---|
| 614 | cdef krb5_principal princ = NULL |
---|
| 615 | cdef krb5_error_code code = 0 |
---|
| 616 | cdef char * krb5_princ = NULL |
---|
| 617 | cdef char *name = NULL, *inst = NULL, *realm = NULL |
---|
| 618 | cdef object pname, pinst, prealm |
---|
| 619 | |
---|
| 620 | if '@' in afs_name: |
---|
| 621 | pname, prealm = afs_name.rsplit('@', 1) |
---|
| 622 | prealm = prealm.upper() |
---|
| 623 | krb4_name = '%s@%s' % (pname, prealm) |
---|
| 624 | else: |
---|
| 625 | krb4_name = '%s@%s' % (afs_name, self.realm) |
---|
| 626 | |
---|
| 627 | pname, pinst, prealm = kname_parse(krb4_name) |
---|
| 628 | if pname: |
---|
| 629 | name = pname |
---|
| 630 | if pinst: |
---|
| 631 | inst = pinst |
---|
| 632 | if prealm: |
---|
| 633 | realm = prealm |
---|
| 634 | |
---|
| 635 | code = krb5_init_context(&ctx) |
---|
| 636 | try: |
---|
| 637 | pyafs_error(code) |
---|
| 638 | |
---|
| 639 | code = krb5_425_conv_principal(ctx, name, inst, realm, &princ) |
---|
| 640 | try: |
---|
| 641 | pyafs_error(code) |
---|
| 642 | |
---|
| 643 | code = krb5_unparse_name(ctx, princ, &krb5_princ) |
---|
| 644 | try: |
---|
| 645 | pyafs_error(code) |
---|
| 646 | |
---|
| 647 | return krb5_princ |
---|
| 648 | finally: |
---|
| 649 | if krb5_princ is not NULL: |
---|
| 650 | free(krb5_princ) |
---|
| 651 | finally: |
---|
| 652 | if princ is not NULL: |
---|
| 653 | krb5_free_principal(ctx, princ) |
---|
| 654 | finally: |
---|
| 655 | if ctx is not NULL: |
---|
| 656 | krb5_free_context(ctx) |
---|
| 657 | |
---|
| 658 | def _Krb5ToAfs(self, krb5_name): |
---|
| 659 | """Convert a Kerberos v5 principal to an AFS one.""" |
---|
| 660 | cdef krb5_context ctx = NULL |
---|
| 661 | cdef krb5_principal k5_princ = NULL |
---|
| 662 | cdef char *k4_name, *k4_inst, *k4_realm |
---|
| 663 | cdef object afs_princ |
---|
| 664 | cdef object afs_name, afs_realm |
---|
| 665 | |
---|
| 666 | k4_name = <char *>malloc(40) |
---|
| 667 | k4_name[0] = '\0' |
---|
| 668 | k4_inst = <char *>malloc(40) |
---|
| 669 | k4_inst[0] = '\0' |
---|
| 670 | k4_realm = <char *>malloc(40) |
---|
| 671 | k4_realm[0] = '\0' |
---|
| 672 | |
---|
| 673 | code = krb5_init_context(&ctx) |
---|
| 674 | try: |
---|
| 675 | pyafs_error(code) |
---|
| 676 | |
---|
| 677 | code = krb5_parse_name(ctx, krb5_name, &k5_princ) |
---|
| 678 | try: |
---|
| 679 | pyafs_error(code) |
---|
| 680 | |
---|
| 681 | code = krb5_524_conv_principal(ctx, k5_princ, k4_name, k4_inst, k4_realm) |
---|
| 682 | pyafs_error(code) |
---|
| 683 | |
---|
| 684 | afs_princ = kname_unparse(k4_name, k4_inst, k4_realm) |
---|
| 685 | afs_name, afs_realm = afs_princ.rsplit('@', 1) |
---|
| 686 | |
---|
| 687 | if k4_realm == self.realm: |
---|
| 688 | return afs_name |
---|
| 689 | else: |
---|
| 690 | return '%s@%s' % (afs_name, afs_realm.lower()) |
---|
| 691 | finally: |
---|
| 692 | if k5_princ is not NULL: |
---|
| 693 | krb5_free_principal(ctx, k5_princ) |
---|
| 694 | finally: |
---|
| 695 | if ctx is not NULL: |
---|
| 696 | krb5_free_context(ctx) |
---|