Commit | Line | Data |
---|---|---|
805e021f CE |
1 | /* |
2 | * Copyright 2000, International Business Machines Corporation and others. | |
3 | * All Rights Reserved. | |
4 | * | |
5 | * This software has been released under the terms of the IBM Public | |
6 | * License. For details, see the LICENSE file in the top-level source | |
7 | * directory or online at http://www.openafs.org/dl/license10.html | |
8 | */ | |
9 | ||
10 | /* | |
11 | * (3) function addToGroup | |
12 | * | |
13 | * 1. Eliminate the code that tests for adding groups | |
14 | * to groups. This is an error in normal AFS. | |
15 | * 2. If adding a group to a group call AddToSGEntry | |
16 | * to add the id of the group it's a member of. | |
17 | * | |
18 | * (4) function Delete | |
19 | * | |
20 | * 1. Print a messsage if an error is returned from | |
21 | * FindByID() and PTDEBUG is defined. | |
22 | * 2. If removing a group from a group call | |
23 | * RemoveFromSGEntry to remove the id of the | |
24 | * group it's a member of. | |
25 | * 3. Remove supergroup continuation records. | |
26 | * | |
27 | * (5) function RemoveFromGroup | |
28 | * | |
29 | * 1. Eliminate the code that tests for adding groups | |
30 | * to groups. This is an error in normal AFS. | |
31 | * 2. If removing a group from a group call | |
32 | * RemoveFromSGEntry to remove the id of the | |
33 | * group it's a member of. | |
34 | * | |
35 | * (6) Add new functions PR_ListSuperGroups and | |
36 | * listSuperGroups. | |
37 | * | |
38 | * (7) function isAMemberOf | |
39 | * | |
40 | * 1. Allow groups to be members of groups. | |
41 | * | |
42 | * Transarc does not currently use opcodes past 520, but | |
43 | * they *could* decide at any time to use more opcodes. | |
44 | * If they did, then one part of our local mods, | |
45 | * ListSupergroups, would break. I've therefore | |
46 | * renumbered it to 530, and put logic in to enable the | |
47 | * old opcode to work (for now). | |
48 | */ | |
49 | ||
50 | #include <afsconfig.h> | |
51 | #include <afs/param.h> | |
52 | #include <afs/stds.h> | |
53 | ||
54 | #include <roken.h> | |
55 | #include <afs/opr.h> | |
56 | ||
57 | #include <ctype.h> | |
58 | ||
59 | #include <lock.h> | |
60 | #include <afs/afsutil.h> | |
61 | #include <ubik.h> | |
62 | #include <rx/xdr.h> | |
63 | #include <rx/rx.h> | |
64 | #include <rx/rxkad.h> | |
65 | #include <afs/auth.h> | |
66 | #include <afs/cellconfig.h> | |
67 | ||
68 | #include "ptserver.h" | |
69 | #include "pterror.h" | |
70 | #include "ptprototypes.h" | |
71 | #include "afs/audit.h" | |
72 | ||
73 | extern int restricted; | |
74 | extern int restrict_anonymous; | |
75 | extern struct ubik_dbase *dbase; | |
76 | extern int pr_noAuth; | |
77 | extern int prp_group_default; | |
78 | extern int prp_user_default; | |
79 | extern struct afsconf_dir *prdir; | |
80 | ||
81 | static afs_int32 iNewEntry(struct rx_call *call, char aname[], afs_int32 aid, | |
82 | afs_int32 oid, afs_int32 *cid); | |
83 | static afs_int32 newEntry(struct rx_call *call, char aname[], afs_int32 flag, | |
84 | afs_int32 oid, afs_int32 *aid, afs_int32 *cid); | |
85 | static afs_int32 whereIsIt(struct rx_call *call, afs_int32 aid, afs_int32 *apos, | |
86 | afs_int32 *cid); | |
87 | static afs_int32 dumpEntry(struct rx_call *call, afs_int32 apos, | |
88 | struct prdebugentry *aentry, afs_int32 *cid); | |
89 | static afs_int32 addToGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid, | |
90 | afs_int32 *cid); | |
91 | static afs_int32 nameToID(struct rx_call *call, namelist *aname, idlist *aid); | |
92 | static afs_int32 idToName(struct rx_call *call, idlist *aid, namelist *aname, afs_int32 *cid); | |
93 | static afs_int32 Delete(struct rx_call *call, afs_int32 aid, afs_int32 *cid); | |
94 | static afs_int32 UpdateEntry(struct rx_call *call, afs_int32 aid, char *name, | |
95 | struct PrUpdateEntry *uentry, afs_int32 *cid); | |
96 | static afs_int32 removeFromGroup(struct rx_call *call, afs_int32 aid, | |
97 | afs_int32 gid, afs_int32 *cid); | |
98 | static afs_int32 getCPS(struct rx_call *call, afs_int32 aid, prlist *alist, | |
99 | afs_int32 *over, afs_int32 *cid); | |
100 | static afs_int32 getCPS2(struct rx_call *call, afs_int32 aid, afs_uint32 ahost, | |
101 | prlist *alist, afs_int32 *over, afs_int32 *cid); | |
102 | static afs_int32 getHostCPS(struct rx_call *call, afs_uint32 ahost, | |
103 | prlist *alist, afs_int32 *over, afs_int32 *cid); | |
104 | static afs_int32 listMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid, afs_int32 *cid); | |
105 | static afs_int32 setMax(struct rx_call *call, afs_int32 aid, afs_int32 gflag, | |
106 | afs_int32 *cid); | |
107 | static afs_int32 listEntry(struct rx_call *call, afs_int32 aid, | |
108 | struct prcheckentry *aentry, afs_int32 *cid); | |
109 | static afs_int32 listEntries(struct rx_call *call, afs_int32 flag, | |
110 | afs_int32 startindex, prentries *bulkentries, | |
111 | afs_int32 *nextstartindex, afs_int32 *cid); | |
112 | static afs_int32 put_prentries(struct prentry *tentry, prentries *bulkentries); | |
113 | static afs_int32 changeEntry(struct rx_call *call, afs_int32 aid, char *name, | |
114 | afs_int32 oid, afs_int32 newid, afs_int32 *cid); | |
115 | static afs_int32 setFieldsEntry(struct rx_call *call, afs_int32 id, | |
116 | afs_int32 mask, afs_int32 flags, | |
117 | afs_int32 ngroups, afs_int32 nusers, | |
118 | afs_int32 spare1, afs_int32 spare2, | |
119 | afs_int32 *cid); | |
120 | static afs_int32 listElements(struct rx_call *call, afs_int32 aid, | |
121 | prlist *alist, afs_int32 *over, afs_int32 *cid); | |
122 | #if defined(SUPERGROUPS) | |
123 | static afs_int32 listSuperGroups(struct rx_call *call, afs_int32 aid, | |
124 | prlist *alist, afs_int32 *over, | |
125 | afs_int32 *cid); | |
126 | #endif | |
127 | static afs_int32 listOwned(struct rx_call *call, afs_int32 aid, prlist *alist, | |
128 | afs_int32 *lastP, afs_int32 *cid); | |
129 | static afs_int32 isAMemberOf(struct rx_call *call, afs_int32 uid, afs_int32 gid, | |
130 | afs_int32 *flag, afs_int32 *cid); | |
131 | static afs_int32 addWildCards(struct ubik_trans *tt, prlist *alist, | |
132 | afs_uint32 host); | |
133 | static afs_int32 WhoIsThisWithName(struct rx_call *acall, | |
134 | struct ubik_trans *at, afs_int32 *aid, | |
135 | char *aname); | |
136 | ||
137 | /* when we abort, the ubik cachedVersion will be reset, so we'll read in the | |
138 | * header on the next call. | |
139 | * Abort the transaction and return the code. | |
140 | */ | |
141 | #define ABORT_WITH(tt,code) return(ubik_AbortTrans(tt),code) | |
142 | ||
143 | static int | |
144 | CreateOK(struct ubik_trans *ut, afs_int32 cid, afs_int32 oid, afs_int32 flag, | |
145 | int admin) | |
146 | { | |
147 | if (restricted && !admin) | |
148 | return 0; | |
149 | ||
150 | if (flag & PRFOREIGN) { | |
151 | /* Foreign users are recognized by the '@' sign and | |
152 | * not by the PRFOREIGN flag. | |
153 | */ | |
154 | return 0; | |
155 | } else if (flag & PRGRP) { | |
156 | /* Allow anonymous group creation only if owner specified | |
157 | * and running noAuth. | |
158 | */ | |
159 | if (cid == ANONYMOUSID) { | |
160 | if ((oid == 0) || !pr_noAuth) | |
161 | return 0; | |
162 | } | |
163 | } else { /* creating a user */ | |
164 | if (oid == ANONYMOUSID) | |
165 | return 0; | |
166 | if (!admin && !pr_noAuth) | |
167 | return 0; | |
168 | } | |
169 | return 1; /* OK! */ | |
170 | } | |
171 | ||
172 | afs_int32 | |
173 | WhoIsThis(struct rx_call *acall, struct ubik_trans *at, afs_int32 *aid) | |
174 | { | |
175 | int code = WhoIsThisWithName(acall, at, aid, NULL); | |
176 | if (code == 2 && *aid == ANONYMOUSID) | |
177 | return PRNOENT; | |
178 | return code; | |
179 | } | |
180 | ||
181 | static int | |
182 | WritePreamble(struct ubik_trans **tt) | |
183 | { | |
184 | int code; | |
185 | ||
186 | code = Initdb(); | |
187 | if (code) | |
188 | return code; | |
189 | ||
190 | code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, tt); | |
191 | if (code) | |
192 | return code; | |
193 | ||
194 | code = ubik_SetLock(*tt, 1, 1, LOCKWRITE); | |
195 | if (code) | |
196 | goto out; | |
197 | ||
198 | code = read_DbHeader(*tt); | |
199 | ||
200 | out: | |
201 | if (code) | |
202 | ubik_AbortTrans(*tt); | |
203 | ||
204 | return code; | |
205 | } | |
206 | ||
207 | static int | |
208 | ReadPreamble(struct ubik_trans **tt) | |
209 | { | |
210 | int code; | |
211 | ||
212 | code = Initdb(); | |
213 | if (code) | |
214 | return code; | |
215 | ||
216 | code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, tt); | |
217 | if (code) | |
218 | return code; | |
219 | ||
220 | code = ubik_SetLock(*tt, 1, 1, LOCKREAD); | |
221 | if (code) | |
222 | goto out; | |
223 | ||
224 | code = read_DbHeader(*tt); | |
225 | ||
226 | out: | |
227 | if (code) | |
228 | ubik_AbortTrans(*tt); | |
229 | ||
230 | return code; | |
231 | } | |
232 | ||
233 | afs_int32 | |
234 | SPR_INewEntry(struct rx_call *call, char aname[], afs_int32 aid, afs_int32 oid) | |
235 | { | |
236 | afs_int32 code; | |
237 | afs_int32 cid = ANONYMOUSID; | |
238 | ||
239 | code = iNewEntry(call, aname, aid, oid, &cid); | |
240 | osi_auditU(call, PTS_INewEntEvent, code, AUD_ID, aid, AUD_STR, aname, | |
241 | AUD_ID, oid, AUD_END); | |
242 | ViceLog(5, ("PTS_INewEntry: code %d cid %d aid %d aname %s oid %d\n", code, cid, aid, aname, oid)); | |
243 | return code; | |
244 | } | |
245 | ||
246 | static afs_int32 | |
247 | iNewEntry(struct rx_call *call, char aname[], afs_int32 aid, afs_int32 oid, | |
248 | afs_int32 *cid) | |
249 | { | |
250 | /* used primarily for conversion - not intended to be used as usual means | |
251 | * of entering people into the database. */ | |
252 | struct ubik_trans *tt; | |
253 | afs_int32 code; | |
254 | afs_int32 gflag = 0; | |
255 | int admin; | |
256 | ||
257 | stolower(aname); | |
258 | ||
259 | code = WritePreamble(&tt); | |
260 | if (code) | |
261 | return code; | |
262 | ||
263 | code = WhoIsThis(call, tt, cid); | |
264 | if (code) | |
265 | ABORT_WITH(tt, PRPERM); | |
266 | admin = IsAMemberOf(tt, *cid, SYSADMINID); | |
267 | ||
268 | /* first verify the id is good */ | |
269 | if (aid == 0) | |
270 | ABORT_WITH(tt, PRPERM); | |
271 | if (aid < 0) { | |
272 | gflag |= PRGRP; | |
273 | /* only sysadmin can reuse a group id */ | |
274 | if (!admin && !pr_noAuth && (aid != ntohl(cheader.maxGroup) - 1)) | |
275 | ABORT_WITH(tt, PRPERM); | |
276 | } | |
277 | if (FindByID(tt, aid)) | |
278 | ABORT_WITH(tt, PRIDEXIST); | |
279 | ||
280 | /* check a few other things */ | |
281 | if (!CreateOK(tt, *cid, oid, gflag, admin)) | |
282 | ABORT_WITH(tt, PRPERM); | |
283 | ||
284 | code = CreateEntry(tt, aname, &aid, 1, gflag, oid, *cid); | |
285 | if (code != PRSUCCESS) | |
286 | ABORT_WITH(tt, code); | |
287 | ||
288 | /* finally, commit transaction */ | |
289 | code = ubik_EndTrans(tt); | |
290 | if (code) | |
291 | return code; | |
292 | return PRSUCCESS; | |
293 | } | |
294 | ||
295 | ||
296 | afs_int32 | |
297 | SPR_NewEntry(struct rx_call *call, char aname[], afs_int32 flag, afs_int32 oid, | |
298 | afs_int32 *aid) | |
299 | { | |
300 | afs_int32 code; | |
301 | afs_int32 cid = ANONYMOUSID; | |
302 | ||
303 | code = newEntry(call, aname, flag, oid, aid, &cid); | |
304 | osi_auditU(call, PTS_NewEntEvent, code, AUD_ID, *aid, AUD_STR, aname, | |
305 | AUD_ID, oid, AUD_END); | |
306 | ViceLog(5, ("PTS_NewEntry: code %d cid %d aid %d aname %s oid %d\n", code, cid, *aid, aname, oid)); | |
307 | return code; | |
308 | } | |
309 | ||
310 | static afs_int32 | |
311 | newEntry(struct rx_call *call, char aname[], afs_int32 flag, afs_int32 oid, | |
312 | afs_int32 *aid, afs_int32 *cid) | |
313 | { | |
314 | afs_int32 code; | |
315 | struct ubik_trans *tt; | |
316 | int admin; | |
317 | int foreign = 0; | |
318 | char cname[PR_MAXNAMELEN]; | |
319 | stolower(aname); | |
320 | ||
321 | code = WritePreamble(&tt); | |
322 | if (code) | |
323 | return code; | |
324 | ||
325 | /* this is for cross-cell self registration. It is not added in the | |
326 | * SPR_INewEntry because we want self-registration to only do | |
327 | * automatic id assignment. | |
328 | */ | |
329 | code = WhoIsThisWithName(call, tt, cid, cname); | |
330 | if (code && code != 2) | |
331 | ABORT_WITH(tt, PRPERM); | |
332 | admin = IsAMemberOf(tt, *cid, SYSADMINID); | |
333 | if (code == 2 /* foreign cell request */) { | |
334 | foreign = 1; | |
335 | ||
336 | if (!restricted && (strcmp(aname, cname) == 0)) { | |
337 | /* can't autoregister while providing an owner id */ | |
338 | if (oid != 0) | |
339 | ABORT_WITH(tt, PRPERM); | |
340 | ||
341 | admin = 1; | |
342 | oid = SYSADMINID; | |
343 | } | |
344 | } | |
345 | if (!CreateOK(tt, *cid, oid, flag, admin)) | |
346 | ABORT_WITH(tt, PRPERM); | |
347 | ||
348 | code = CreateEntry(tt, aname, aid, 0, flag, oid, *cid); | |
349 | /* | |
350 | * If this was an autoregistration then be sure to audit log | |
351 | * the proper id as the creator. | |
352 | */ | |
353 | if (foreign && code == 0 && *aid > 0) | |
354 | *cid = *aid; | |
355 | if (code != PRSUCCESS) | |
356 | ABORT_WITH(tt, code); | |
357 | ||
358 | code = ubik_EndTrans(tt); | |
359 | if (code) | |
360 | return code; | |
361 | return PRSUCCESS; | |
362 | } | |
363 | ||
364 | ||
365 | ||
366 | afs_int32 | |
367 | SPR_WhereIsIt(struct rx_call *call, afs_int32 aid, afs_int32 *apos) | |
368 | { | |
369 | afs_int32 code; | |
370 | afs_int32 cid = ANONYMOUSID; | |
371 | ||
372 | code = whereIsIt(call, aid, apos, &cid); | |
373 | osi_auditU(call, PTS_WheIsItEvent, code, AUD_ID, aid, AUD_LONG, *apos, | |
374 | AUD_END); | |
375 | ViceLog(125, ("PTS_WhereIsIt: code %d cid %d aid %d apos %d\n", code, cid, aid, *apos)); | |
376 | return code; | |
377 | } | |
378 | ||
379 | static afs_int32 | |
380 | whereIsIt(struct rx_call *call, afs_int32 aid, afs_int32 *apos, afs_int32 *cid) | |
381 | { | |
382 | afs_int32 code; | |
383 | struct ubik_trans *tt; | |
384 | afs_int32 temp; | |
385 | ||
386 | code = ReadPreamble(&tt); | |
387 | if (code) | |
388 | return code; | |
389 | ||
390 | code = WhoIsThis(call, tt, cid); | |
391 | if (code) | |
392 | ABORT_WITH(tt, PRPERM); | |
393 | if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID) | |
394 | ABORT_WITH(tt, PRPERM); | |
395 | ||
396 | temp = FindByID(tt, aid); | |
397 | if (!temp) | |
398 | ABORT_WITH(tt, PRNOENT); | |
399 | *apos = temp; | |
400 | code = ubik_EndTrans(tt); | |
401 | if (code) | |
402 | return code; | |
403 | return PRSUCCESS; | |
404 | } | |
405 | ||
406 | ||
407 | afs_int32 | |
408 | SPR_DumpEntry(struct rx_call *call, afs_int32 apos, | |
409 | struct prdebugentry *aentry) | |
410 | { | |
411 | afs_int32 code; | |
412 | afs_int32 cid = ANONYMOUSID; | |
413 | ||
414 | code = dumpEntry(call, apos, aentry, &cid); | |
415 | osi_auditU(call, PTS_DmpEntEvent, code, AUD_LONG, apos, AUD_END); | |
416 | ViceLog(125, ("PTS_DumpEntry: code %d cid %d apos %d\n", code, cid, apos)); | |
417 | return code; | |
418 | } | |
419 | ||
420 | static afs_int32 | |
421 | dumpEntry(struct rx_call *call, afs_int32 apos, struct prdebugentry *aentry, | |
422 | afs_int32 *cid) | |
423 | { | |
424 | afs_int32 code; | |
425 | struct ubik_trans *tt; | |
426 | ||
427 | code = ReadPreamble(&tt); | |
428 | if (code) | |
429 | return code; | |
430 | ||
431 | code = WhoIsThis(call, tt, cid); | |
432 | if (code) | |
433 | ABORT_WITH(tt, PRPERM); | |
434 | code = pr_ReadEntry(tt, 0, apos, (struct prentry *)aentry); | |
435 | if (code) | |
436 | ABORT_WITH(tt, code); | |
437 | ||
438 | if (!AccessOK(tt, *cid, 0, PRP_STATUS_MEM, 0)) | |
439 | ABORT_WITH(tt, PRPERM); | |
440 | ||
441 | /* Since prdebugentry is in the form of a prentry not a coentry, we will | |
442 | * return the coentry slots in network order where the string is. */ | |
443 | #if 0 | |
444 | if (aentry->flags & PRCONT) { /* wrong type, get coentry instead */ | |
445 | code = pr_ReadCoEntry(tt, 0, apos, aentry); | |
446 | if (code) | |
447 | ABORT_WITH(tt, code); | |
448 | } | |
449 | #endif | |
450 | code = ubik_EndTrans(tt); | |
451 | if (code) | |
452 | return code; | |
453 | return PRSUCCESS; | |
454 | } | |
455 | ||
456 | afs_int32 | |
457 | SPR_AddToGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid) | |
458 | { | |
459 | afs_int32 code; | |
460 | afs_int32 cid = ANONYMOUSID; | |
461 | ||
462 | code = addToGroup(call, aid, gid, &cid); | |
463 | osi_auditU(call, PTS_AdToGrpEvent, code, AUD_ID, gid, AUD_ID, aid, | |
464 | AUD_END); | |
465 | ViceLog(5, ("PTS_AddToGroup: code %d cid %d gid %d aid %d\n", code, cid, gid, aid)); | |
466 | return code; | |
467 | } | |
468 | ||
469 | static afs_int32 | |
470 | addToGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid, afs_int32 *cid) | |
471 | { | |
472 | afs_int32 code; | |
473 | struct ubik_trans *tt; | |
474 | afs_int32 tempu; | |
475 | afs_int32 tempg; | |
476 | struct prentry tentry; | |
477 | struct prentry uentry; | |
478 | ||
479 | if (gid == ANYUSERID || gid == AUTHUSERID) | |
480 | return PRPERM; | |
481 | if (aid == ANONYMOUSID) | |
482 | return PRPERM; | |
483 | ||
484 | code = WritePreamble(&tt); | |
485 | if (code) | |
486 | return code; | |
487 | ||
488 | code = WhoIsThis(call, tt, cid); | |
489 | if (code) | |
490 | ABORT_WITH(tt, PRPERM); | |
491 | tempu = FindByID(tt, aid); | |
492 | if (!tempu) | |
493 | ABORT_WITH(tt, PRNOENT); | |
494 | memset(&uentry, 0, sizeof(uentry)); | |
495 | code = pr_ReadEntry(tt, 0, tempu, &uentry); | |
496 | if (code != 0) | |
497 | ABORT_WITH(tt, code); | |
498 | ||
499 | #if !defined(SUPERGROUPS) | |
500 | /* we don't allow groups as members of groups at present */ | |
501 | if (uentry.flags & PRGRP) | |
502 | ABORT_WITH(tt, PRNOTUSER); | |
503 | #endif | |
504 | ||
505 | tempg = FindByID(tt, gid); | |
506 | if (!tempg) | |
507 | ABORT_WITH(tt, PRNOENT); | |
508 | code = pr_ReadEntry(tt, 0, tempg, &tentry); | |
509 | if (code != 0) | |
510 | ABORT_WITH(tt, code); | |
511 | /* make sure that this is a group */ | |
512 | if (!(tentry.flags & PRGRP)) | |
513 | ABORT_WITH(tt, PRNOTGROUP); | |
514 | if (!AccessOK(tt, *cid, &tentry, PRP_ADD_MEM, PRP_ADD_ANY)) | |
515 | ABORT_WITH(tt, PRPERM); | |
516 | ||
517 | code = AddToEntry(tt, &tentry, tempg, aid); | |
518 | if (code != PRSUCCESS) | |
519 | ABORT_WITH(tt, code); | |
520 | ||
521 | #if defined(SUPERGROUPS) | |
522 | if (uentry.flags & PRGRP) | |
523 | code = AddToSGEntry(tt, &uentry, tempu, gid); /* mod group to be in sg */ | |
524 | else | |
525 | #endif | |
526 | /* now, modify the user's entry as well */ | |
527 | code = AddToEntry(tt, &uentry, tempu, gid); | |
528 | if (code != PRSUCCESS) | |
529 | ABORT_WITH(tt, code); | |
530 | code = ubik_EndTrans(tt); | |
531 | if (code) | |
532 | return code; | |
533 | return PRSUCCESS; | |
534 | } | |
535 | ||
536 | afs_int32 | |
537 | SPR_NameToID(struct rx_call *call, namelist *aname, idlist *aid) | |
538 | { | |
539 | afs_int32 code; | |
540 | ||
541 | code = nameToID(call, aname, aid); | |
542 | osi_auditU(call, PTS_NmToIdEvent, code, AUD_END); | |
543 | ViceLog(125, ("PTS_NameToID: code %d\n", code)); | |
544 | return code; | |
545 | } | |
546 | ||
547 | static afs_int32 | |
548 | nameToID(struct rx_call *call, namelist *aname, idlist *aid) | |
549 | { | |
550 | afs_int32 code; | |
551 | struct ubik_trans *tt; | |
552 | afs_int32 i; | |
553 | int size; | |
554 | int count = 0; | |
555 | ||
556 | /* Initialize return struct */ | |
557 | aid->idlist_len = 0; | |
558 | aid->idlist_val = NULL; | |
559 | ||
560 | size = aname->namelist_len; | |
561 | if (size == 0) | |
562 | return 0; | |
563 | if (size < 0) | |
564 | return PRTOOMANY; | |
565 | ||
566 | aid->idlist_val = malloc(size * sizeof(afs_int32)); | |
567 | if (!aid->idlist_val) | |
568 | return PRNOMEM; | |
569 | ||
570 | code = ReadPreamble(&tt); | |
571 | if (code) | |
572 | return code; | |
573 | ||
574 | for (i = 0; i < aname->namelist_len; i++) { | |
575 | char vname[256]; | |
576 | char *nameinst, *cell; | |
577 | afs_int32 islocal = 1; | |
578 | ||
579 | strncpy(vname, aname->namelist_val[i], sizeof(vname)); | |
580 | vname[sizeof(vname)-1] ='\0'; | |
581 | ||
582 | nameinst = vname; | |
583 | cell = strchr(vname, '@'); | |
584 | if (cell) { | |
585 | *cell = '\0'; | |
586 | cell++; | |
587 | } | |
588 | ||
589 | if (cell && *cell) { | |
590 | code = afsconf_IsLocalRealmMatch(prdir, &islocal, nameinst, NULL, cell); | |
591 | ViceLog(125, | |
592 | ("PTS_NameToID: afsconf_IsLocalRealmMatch(); code=%d, nameinst=%s, cell=%s\n", | |
593 | code, nameinst, cell)); | |
594 | } | |
595 | if (islocal) | |
596 | code = NameToID(tt, nameinst, &aid->idlist_val[i]); | |
597 | else | |
598 | code = NameToID(tt, aname->namelist_val[i], &aid->idlist_val[i]); | |
599 | ||
600 | if (code != PRSUCCESS) | |
601 | aid->idlist_val[i] = ANONYMOUSID; | |
602 | osi_audit(PTS_NmToIdEvent, code, AUD_STR, | |
603 | aname->namelist_val[i], AUD_ID, aid->idlist_val[i], | |
604 | AUD_END); | |
605 | ViceLog(125, ("PTS_NameToID: code %d aname %s aid %d\n", code, | |
606 | aname->namelist_val[i], aid->idlist_val[i])); | |
607 | if (count++ > 50) { | |
608 | #ifndef AFS_PTHREAD_ENV | |
609 | IOMGR_Poll(); | |
610 | #endif | |
611 | count = 0; | |
612 | } | |
613 | } | |
614 | aid->idlist_len = aname->namelist_len; | |
615 | ||
616 | code = ubik_EndTrans(tt); | |
617 | if (code) | |
618 | return code; | |
619 | return PRSUCCESS; | |
620 | } | |
621 | ||
622 | /* | |
623 | * SPR_IDToName | |
624 | * Given an array of ids, find the name for each of them. | |
625 | * The array of ids and names is unlimited. | |
626 | */ | |
627 | afs_int32 | |
628 | SPR_IDToName(struct rx_call *call, idlist *aid, namelist *aname) | |
629 | { | |
630 | afs_int32 code; | |
631 | afs_int32 cid = ANONYMOUSID; | |
632 | ||
633 | code = idToName(call, aid, aname, &cid); | |
634 | osi_auditU(call, PTS_IdToNmEvent, code, AUD_END); | |
635 | ViceLog(125, ("PTS_IDToName: code %d\n", code)); | |
636 | return code; | |
637 | } | |
638 | ||
639 | static afs_int32 | |
640 | idToName(struct rx_call *call, idlist *aid, namelist *aname, afs_int32 *cid) | |
641 | { | |
642 | afs_int32 code; | |
643 | struct ubik_trans *tt; | |
644 | afs_int32 i; | |
645 | int size; | |
646 | int count = 0; | |
647 | ||
648 | /* leave this first for rpc stub */ | |
649 | size = aid->idlist_len; | |
650 | if (size == 0) | |
651 | return 0; | |
652 | if (size < 0 || size > INT_MAX / PR_MAXNAMELEN) | |
653 | return PRTOOMANY; | |
654 | aname->namelist_val = calloc(size, PR_MAXNAMELEN); | |
655 | aname->namelist_len = 0; | |
656 | if (aname->namelist_val == 0) | |
657 | return PRNOMEM; | |
658 | if (aid->idlist_len == 0) | |
659 | return 0; | |
660 | if (size == 0) | |
661 | return PRTOOMANY; /* rxgen will probably handle this */ | |
662 | ||
663 | code = ReadPreamble(&tt); | |
664 | if (code) | |
665 | return code; | |
666 | ||
667 | code = WhoIsThis(call, tt, cid); | |
668 | if (code) | |
669 | ABORT_WITH(tt, PRPERM); | |
670 | if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID) | |
671 | ABORT_WITH(tt, PRPERM); | |
672 | ||
673 | for (i = 0; i < aid->idlist_len; i++) { | |
674 | code = IDToName(tt, aid->idlist_val[i], aname->namelist_val[i]); | |
675 | if (code != PRSUCCESS) | |
676 | sprintf(aname->namelist_val[i], "%d", aid->idlist_val[i]); | |
677 | osi_audit(PTS_IdToNmEvent, code, AUD_ID, aid->idlist_val[i], | |
678 | AUD_STR, aname->namelist_val[i], AUD_END); | |
679 | ViceLog(125, ("PTS_idToName: code %d aid %d aname %s\n", code, | |
680 | aid->idlist_val[i], aname->namelist_val[i])); | |
681 | if (count++ > 50) { | |
682 | #ifndef AFS_PTHREAD_ENV | |
683 | IOMGR_Poll(); | |
684 | #endif | |
685 | count = 0; | |
686 | } | |
687 | } | |
688 | aname->namelist_len = aid->idlist_len; | |
689 | ||
690 | code = ubik_EndTrans(tt); | |
691 | if (code) | |
692 | return code; | |
693 | return PRSUCCESS; | |
694 | } | |
695 | ||
696 | afs_int32 | |
697 | SPR_Delete(struct rx_call *call, afs_int32 aid) | |
698 | { | |
699 | afs_int32 code; | |
700 | afs_int32 cid = ANONYMOUSID; | |
701 | ||
702 | code = Delete(call, aid, &cid); | |
703 | osi_auditU(call, PTS_DelEvent, code, AUD_ID, aid, AUD_END); | |
704 | ViceLog(5, ("PTS_Delete: code %d cid %d aid %d\n", code, cid, aid)); | |
705 | return code; | |
706 | } | |
707 | ||
708 | static afs_int32 | |
709 | Delete(struct rx_call *call, afs_int32 aid, afs_int32 *cid) | |
710 | { | |
711 | afs_int32 code; | |
712 | struct ubik_trans *tt; | |
713 | struct prentry tentry; | |
714 | afs_int32 loc, nptr; | |
715 | int count; | |
716 | ||
717 | if (aid == SYSADMINID || aid == ANYUSERID || aid == AUTHUSERID | |
718 | || aid == ANONYMOUSID) | |
719 | return PRPERM; | |
720 | ||
721 | code = WritePreamble(&tt); | |
722 | if (code) | |
723 | return code; | |
724 | ||
725 | code = WhoIsThis(call, tt, cid); | |
726 | if (code) | |
727 | ABORT_WITH(tt, PRPERM); | |
728 | ||
729 | /* Read in entry to be deleted */ | |
730 | loc = FindByID(tt, aid); | |
731 | if (loc == 0) | |
732 | ABORT_WITH(tt, PRNOENT); | |
733 | code = pr_ReadEntry(tt, 0, loc, &tentry); | |
734 | if (code) | |
735 | ABORT_WITH(tt, PRDBFAIL); | |
736 | ||
737 | /* Do some access checking */ | |
738 | if (tentry.owner != *cid && !IsAMemberOf(tt, *cid, SYSADMINID) | |
739 | && !IsAMemberOf(tt, *cid, tentry.owner) && !pr_noAuth) | |
740 | ABORT_WITH(tt, PRPERM); | |
741 | ||
742 | if (restricted && !IsAMemberOf(tt, *cid, SYSADMINID)) { | |
743 | ABORT_WITH(tt, PRPERM); | |
744 | } | |
745 | ||
746 | /* Delete each continuation block as a separate transaction so that no one | |
747 | * transaction become to large to complete. */ | |
748 | nptr = tentry.next; | |
749 | while (nptr != 0) { | |
750 | struct contentry centry; | |
751 | int i; | |
752 | ||
753 | code = pr_ReadCoEntry(tt, 0, nptr, ¢ry); | |
754 | if (code != 0) | |
755 | ABORT_WITH(tt, PRDBFAIL); | |
756 | for (i = 0; i < COSIZE; i++) { | |
757 | if (centry.entries[i] == PRBADID) | |
758 | continue; | |
759 | if (centry.entries[i] == 0) | |
760 | break; | |
761 | #if defined(SUPERGROUPS) | |
762 | if (aid < 0 && centry.entries[i] < 0) /* Supergroup */ | |
763 | code = RemoveFromSGEntry(tt, aid, centry.entries[i]); | |
764 | else | |
765 | #endif | |
766 | code = RemoveFromEntry(tt, aid, centry.entries[i]); | |
767 | if (code) | |
768 | ABORT_WITH(tt, code); | |
769 | tentry.count--; /* maintain count */ | |
770 | #ifndef AFS_PTHREAD_ENV | |
771 | if ((i & 3) == 0) | |
772 | IOMGR_Poll(); | |
773 | #endif | |
774 | } | |
775 | tentry.next = centry.next; /* thread out this block */ | |
776 | code = FreeBlock(tt, nptr); /* free continuation block */ | |
777 | if (code) | |
778 | ABORT_WITH(tt, code); | |
779 | code = pr_WriteEntry(tt, 0, loc, &tentry); /* update main entry */ | |
780 | if (code) | |
781 | ABORT_WITH(tt, code); | |
782 | ||
783 | /* end this trans and start a new one */ | |
784 | code = ubik_EndTrans(tt); | |
785 | if (code) | |
786 | return code; | |
787 | #ifndef AFS_PTHREAD_ENV | |
788 | IOMGR_Poll(); /* just to keep the connection alive */ | |
789 | #endif | |
790 | code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt); | |
791 | if (code) | |
792 | return code; | |
793 | code = ubik_SetLock(tt, 1, 1, LOCKWRITE); | |
794 | if (code) | |
795 | ABORT_WITH(tt, code); | |
796 | ||
797 | /* re-read entry to get consistent uptodate info */ | |
798 | loc = FindByID(tt, aid); | |
799 | if (loc == 0) | |
800 | ABORT_WITH(tt, PRNOENT); | |
801 | code = pr_ReadEntry(tt, 0, loc, &tentry); | |
802 | if (code) | |
803 | ABORT_WITH(tt, PRDBFAIL); | |
804 | ||
805 | nptr = tentry.next; | |
806 | } | |
807 | ||
808 | #if defined(SUPERGROUPS) | |
809 | /* Delete each continuation block as a separate transaction | |
810 | * so that no one transaction become too large to complete. */ | |
811 | { | |
812 | struct prentryg *tentryg = (struct prentryg *)&tentry; | |
813 | nptr = tentryg->nextsg; | |
814 | while (nptr != 0) { | |
815 | struct contentry centry; | |
816 | int i; | |
817 | ||
818 | code = pr_ReadCoEntry(tt, 0, nptr, ¢ry); | |
819 | if (code != 0) | |
820 | ABORT_WITH(tt, PRDBFAIL); | |
821 | for (i = 0; i < COSIZE; i++) { | |
822 | if (centry.entries[i] == PRBADID) | |
823 | continue; | |
824 | if (centry.entries[i] == 0) | |
825 | break; | |
826 | code = RemoveFromEntry(tt, aid, centry.entries[i]); | |
827 | if (code) | |
828 | ABORT_WITH(tt, code); | |
829 | tentryg->countsg--; /* maintain count */ | |
830 | #ifndef AFS_PTHREAD_ENV | |
831 | if ((i & 3) == 0) | |
832 | IOMGR_Poll(); | |
833 | #endif | |
834 | } | |
835 | tentryg->nextsg = centry.next; /* thread out this block */ | |
836 | code = FreeBlock(tt, nptr); /* free continuation block */ | |
837 | if (code) | |
838 | ABORT_WITH(tt, code); | |
839 | code = pr_WriteEntry(tt, 0, loc, &tentry); /* update main entry */ | |
840 | if (code) | |
841 | ABORT_WITH(tt, code); | |
842 | ||
843 | /* end this trans and start a new one */ | |
844 | code = ubik_EndTrans(tt); | |
845 | if (code) | |
846 | return code; | |
847 | #ifndef AFS_PTHREAD_ENV | |
848 | IOMGR_Poll(); /* just to keep the connection alive */ | |
849 | #endif | |
850 | ||
851 | code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt); | |
852 | if (code) | |
853 | return code; | |
854 | code = ubik_SetLock(tt, 1, 1, LOCKWRITE); | |
855 | if (code) | |
856 | ABORT_WITH(tt, code); | |
857 | ||
858 | /* re-read entry to get consistent uptodate info */ | |
859 | loc = FindByID(tt, aid); | |
860 | if (loc == 0) | |
861 | ABORT_WITH(tt, PRNOENT); | |
862 | code = pr_ReadEntry(tt, 0, loc, &tentry); | |
863 | if (code) | |
864 | ABORT_WITH(tt, PRDBFAIL); | |
865 | ||
866 | nptr = tentryg->nextsg; | |
867 | } | |
868 | } | |
869 | ||
870 | #endif /* SUPERGROUPS */ | |
871 | ||
872 | /* Then move the owned chain, except possibly ourself to the orphan list. | |
873 | * Because this list can be very long and so exceed the size of a ubik | |
874 | * transaction, we start a new transaction every 50 entries. */ | |
875 | count = 0; | |
876 | nptr = tentry.owned; | |
877 | while (nptr != 0) { | |
878 | struct prentry nentry; | |
879 | ||
880 | code = pr_ReadEntry(tt, 0, nptr, &nentry); | |
881 | if (code) | |
882 | ABORT_WITH(tt, PRDBFAIL); | |
883 | nptr = tentry.owned = nentry.nextOwned; /* thread out */ | |
884 | ||
885 | if (nentry.id != tentry.id) { /* don't add us to orphan chain! */ | |
886 | code = AddToOrphan(tt, nentry.id); | |
887 | if (code) | |
888 | ABORT_WITH(tt, code); | |
889 | count++; | |
890 | #ifndef AFS_PTHREAD_ENV | |
891 | if ((count & 3) == 0) | |
892 | IOMGR_Poll(); | |
893 | #endif | |
894 | } | |
895 | if (count < 50) | |
896 | continue; | |
897 | code = pr_WriteEntry(tt, 0, loc, &tentry); /* update main entry */ | |
898 | if (code) | |
899 | ABORT_WITH(tt, code); | |
900 | ||
901 | /* end this trans and start a new one */ | |
902 | code = ubik_EndTrans(tt); | |
903 | if (code) | |
904 | return code; | |
905 | #ifndef AFS_PTHREAD_ENV | |
906 | IOMGR_Poll(); /* just to keep the connection alive */ | |
907 | #endif | |
908 | code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt); | |
909 | if (code) | |
910 | return code; | |
911 | code = ubik_SetLock(tt, 1, 1, LOCKWRITE); | |
912 | if (code) | |
913 | ABORT_WITH(tt, code); | |
914 | ||
915 | /* re-read entry to get consistent uptodate info */ | |
916 | loc = FindByID(tt, aid); | |
917 | if (loc == 0) | |
918 | ABORT_WITH(tt, PRNOENT); | |
919 | code = pr_ReadEntry(tt, 0, loc, &tentry); | |
920 | if (code) | |
921 | ABORT_WITH(tt, PRDBFAIL); | |
922 | ||
923 | nptr = tentry.owned; | |
924 | } | |
925 | ||
926 | /* now do what's left of the deletion stuff */ | |
927 | code = DeleteEntry(tt, &tentry, loc); | |
928 | if (code != PRSUCCESS) | |
929 | ABORT_WITH(tt, code); | |
930 | ||
931 | code = ubik_EndTrans(tt); | |
932 | if (code) | |
933 | return code; | |
934 | return PRSUCCESS; | |
935 | } | |
936 | ||
937 | afs_int32 | |
938 | SPR_UpdateEntry(struct rx_call *call, afs_int32 aid, char *name, | |
939 | struct PrUpdateEntry *uentry) | |
940 | { | |
941 | afs_int32 code; | |
942 | afs_int32 cid = ANONYMOUSID; | |
943 | ||
944 | code = UpdateEntry(call, aid, name, uentry, &cid); | |
945 | osi_auditU(call, PTS_UpdEntEvent, code, AUD_ID, aid, AUD_STR, name, AUD_END); | |
946 | ViceLog(5, ("PTS_UpdateEntry: code %d cid %d aid %d name %s\n", code, cid, aid, name)); | |
947 | return code; | |
948 | } | |
949 | ||
950 | afs_int32 | |
951 | UpdateEntry(struct rx_call *call, afs_int32 aid, char *name, | |
952 | struct PrUpdateEntry *uentry, afs_int32 *cid) | |
953 | { | |
954 | afs_int32 code; | |
955 | struct ubik_trans *tt; | |
956 | struct prentry tentry; | |
957 | afs_int32 loc; | |
958 | int id = 0; | |
959 | ||
960 | if (aid) { | |
961 | id = aid; | |
962 | if (aid == SYSADMINID || aid == ANYUSERID || aid == AUTHUSERID | |
963 | || aid == ANONYMOUSID) | |
964 | return PRPERM; | |
965 | } | |
966 | ||
967 | code = WritePreamble(&tt); | |
968 | if (code) | |
969 | return code; | |
970 | ||
971 | code = WhoIsThis(call, tt, cid); | |
972 | if (code) | |
973 | ABORT_WITH(tt, PRPERM); | |
974 | code = IsAMemberOf(tt, *cid, SYSADMINID); | |
975 | if (!code && !pr_noAuth) | |
976 | ABORT_WITH(tt, PRPERM); | |
977 | ||
978 | /* Read in entry to be deleted */ | |
979 | if (id) { | |
980 | loc = FindByID(tt, aid); | |
981 | } else { | |
982 | loc = FindByName(tt, name, &tentry); | |
983 | } | |
984 | if (loc == 0) | |
985 | ABORT_WITH(tt, PRNOENT); | |
986 | code = pr_ReadEntry(tt, 0, loc, &tentry); | |
987 | if (code) | |
988 | ABORT_WITH(tt, PRDBFAIL); | |
989 | ||
990 | if (uentry->Mask & PRUPDATE_NAMEHASH) { | |
991 | int tloc; | |
992 | code = RemoveFromNameHash(tt, tentry.name, &tloc); | |
993 | if (code != PRSUCCESS) | |
994 | ABORT_WITH(tt, PRDBFAIL); | |
995 | code = AddToNameHash(tt, tentry.name, loc); | |
996 | if (code) | |
997 | ABORT_WITH(tt, code); | |
998 | } | |
999 | ||
1000 | if (uentry->Mask & PRUPDATE_IDHASH) { | |
1001 | int tloc; | |
1002 | if (!id) | |
1003 | id = tentry.id; | |
1004 | code = RemoveFromIDHash(tt, id, &tloc); | |
1005 | if (code != PRSUCCESS) | |
1006 | ABORT_WITH(tt, PRDBFAIL); | |
1007 | code = AddToIDHash(tt, id, loc); | |
1008 | if (code) | |
1009 | ABORT_WITH(tt, code); | |
1010 | } | |
1011 | ||
1012 | code = ubik_EndTrans(tt); | |
1013 | if (code) | |
1014 | return code; | |
1015 | return PRSUCCESS; | |
1016 | } | |
1017 | ||
1018 | afs_int32 | |
1019 | SPR_RemoveFromGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid) | |
1020 | { | |
1021 | afs_int32 code; | |
1022 | afs_int32 cid = ANONYMOUSID; | |
1023 | ||
1024 | code = removeFromGroup(call, aid, gid, &cid); | |
1025 | osi_auditU(call, PTS_RmFmGrpEvent, code, AUD_ID, gid, AUD_ID, aid, | |
1026 | AUD_END); | |
1027 | ViceLog(5, ("PTS_RemoveFromGroup: code %d cid %d gid %d aid %d\n", code, cid, gid, aid)); | |
1028 | return code; | |
1029 | } | |
1030 | ||
1031 | static afs_int32 | |
1032 | removeFromGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid, | |
1033 | afs_int32 *cid) | |
1034 | { | |
1035 | afs_int32 code; | |
1036 | struct ubik_trans *tt; | |
1037 | afs_int32 tempu; | |
1038 | afs_int32 tempg; | |
1039 | struct prentry uentry; | |
1040 | struct prentry gentry; | |
1041 | ||
1042 | code = WritePreamble(&tt); | |
1043 | if (code) | |
1044 | return code; | |
1045 | ||
1046 | code = WhoIsThis(call, tt, cid); | |
1047 | if (code) | |
1048 | ABORT_WITH(tt, PRPERM); | |
1049 | tempu = FindByID(tt, aid); | |
1050 | if (!tempu) | |
1051 | ABORT_WITH(tt, PRNOENT); | |
1052 | tempg = FindByID(tt, gid); | |
1053 | if (!tempg) | |
1054 | ABORT_WITH(tt, PRNOENT); | |
1055 | memset(&uentry, 0, sizeof(uentry)); | |
1056 | memset(&gentry, 0, sizeof(gentry)); | |
1057 | code = pr_ReadEntry(tt, 0, tempu, &uentry); | |
1058 | if (code != 0) | |
1059 | ABORT_WITH(tt, code); | |
1060 | code = pr_ReadEntry(tt, 0, tempg, &gentry); | |
1061 | if (code != 0) | |
1062 | ABORT_WITH(tt, code); | |
1063 | if (!(gentry.flags & PRGRP)) | |
1064 | ABORT_WITH(tt, PRNOTGROUP); | |
1065 | #if !defined(SUPERGROUPS) | |
1066 | if (uentry.flags & PRGRP) | |
1067 | ABORT_WITH(tt, PRNOTUSER); | |
1068 | #endif | |
1069 | if (!AccessOK(tt, *cid, &gentry, PRP_REMOVE_MEM, 0)) | |
1070 | ABORT_WITH(tt, PRPERM); | |
1071 | code = RemoveFromEntry(tt, aid, gid); | |
1072 | if (code != PRSUCCESS) | |
1073 | ABORT_WITH(tt, code); | |
1074 | #if defined(SUPERGROUPS) | |
1075 | if (!(uentry.flags & PRGRP)) | |
1076 | #endif | |
1077 | code = RemoveFromEntry(tt, gid, aid); | |
1078 | #if defined(SUPERGROUPS) | |
1079 | else | |
1080 | code = RemoveFromSGEntry(tt, gid, aid); | |
1081 | #endif | |
1082 | if (code != PRSUCCESS) | |
1083 | ABORT_WITH(tt, code); | |
1084 | ||
1085 | code = ubik_EndTrans(tt); | |
1086 | if (code) | |
1087 | return code; | |
1088 | return PRSUCCESS; | |
1089 | } | |
1090 | ||
1091 | ||
1092 | afs_int32 | |
1093 | SPR_GetCPS(struct rx_call *call, afs_int32 aid, prlist *alist, afs_int32 *over) | |
1094 | { | |
1095 | afs_int32 code; | |
1096 | afs_int32 cid = ANONYMOUSID; | |
1097 | ||
1098 | code = getCPS(call, aid, alist, over, &cid); | |
1099 | osi_auditU(call, PTS_GetCPSEvent, code, AUD_ID, aid, AUD_END); | |
1100 | ViceLog(125, ("PTS_GetCPS: code %d cid %d aid %d\n", code, cid, aid)); | |
1101 | return code; | |
1102 | } | |
1103 | ||
1104 | static afs_int32 | |
1105 | getCPS(struct rx_call *call, afs_int32 aid, prlist *alist, afs_int32 *over, | |
1106 | afs_int32 *cid) | |
1107 | { | |
1108 | afs_int32 code; | |
1109 | struct ubik_trans *tt; | |
1110 | afs_int32 temp; | |
1111 | struct prentry tentry; | |
1112 | ||
1113 | *over = 0; | |
1114 | alist->prlist_len = 0; | |
1115 | alist->prlist_val = NULL; | |
1116 | ||
1117 | code = ReadPreamble(&tt); | |
1118 | if (code) | |
1119 | return code; | |
1120 | ||
1121 | code = WhoIsThis(call, tt, cid); | |
1122 | if (code) | |
1123 | ABORT_WITH(tt, PRPERM); | |
1124 | if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID) | |
1125 | ABORT_WITH(tt, PRPERM); | |
1126 | ||
1127 | temp = FindByID(tt, aid); | |
1128 | if (!temp) | |
1129 | ABORT_WITH(tt, PRNOENT); | |
1130 | code = pr_ReadEntry(tt, 0, temp, &tentry); | |
1131 | if (code) | |
1132 | ABORT_WITH(tt, code); | |
1133 | ||
1134 | if (!AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY)) | |
1135 | ABORT_WITH(tt, PRPERM); | |
1136 | ||
1137 | code = GetList(tt, &tentry, alist, 1); | |
1138 | if (code != PRSUCCESS) | |
1139 | ABORT_WITH(tt, code); | |
1140 | ||
1141 | code = ubik_EndTrans(tt); | |
1142 | return code; | |
1143 | } | |
1144 | ||
1145 | ||
1146 | int | |
1147 | inCPS(prlist CPS, afs_int32 id) | |
1148 | { | |
1149 | int i; | |
1150 | ||
1151 | for (i = (CPS.prlist_len - 1); i >= 0; i--) { | |
1152 | if (CPS.prlist_val[i] == id) | |
1153 | return (1); | |
1154 | } | |
1155 | return (0); | |
1156 | } | |
1157 | ||
1158 | ||
1159 | afs_int32 | |
1160 | SPR_GetCPS2(struct rx_call *call, afs_int32 aid, afs_int32 ahost, | |
1161 | prlist *alist, afs_int32 *over) | |
1162 | { | |
1163 | afs_int32 code; | |
1164 | afs_int32 cid = ANONYMOUSID; | |
1165 | ||
1166 | code = getCPS2(call, aid, ahost, alist, over, &cid); | |
1167 | osi_auditU(call, PTS_GetCPS2Event, code, AUD_ID, aid, AUD_HOST, htonl(ahost), | |
1168 | AUD_END); | |
1169 | ViceLog(125, ("PTS_GetCPS2: code %d cid %d aid %d ahost %d\n", code, cid, aid, ahost)); | |
1170 | return code; | |
1171 | } | |
1172 | ||
1173 | static afs_int32 | |
1174 | getCPS2(struct rx_call *call, afs_int32 aid, afs_uint32 ahost, prlist *alist, | |
1175 | afs_int32 *over, afs_int32 *cid) | |
1176 | { | |
1177 | afs_int32 code; | |
1178 | struct ubik_trans *tt; | |
1179 | afs_int32 temp; | |
1180 | struct prentry tentry; | |
1181 | struct prentry host_tentry; | |
1182 | afs_int32 hostid; | |
1183 | int host_list = 0; | |
1184 | struct in_addr iaddr; | |
1185 | char hoststr[16]; | |
1186 | ||
1187 | *over = 0; | |
1188 | iaddr.s_addr = ntohl(ahost); | |
1189 | alist->prlist_len = 0; | |
1190 | alist->prlist_val = NULL; | |
1191 | ||
1192 | code = ReadPreamble(&tt); | |
1193 | if (code) | |
1194 | return code; | |
1195 | ||
1196 | if (aid != PRBADID) { | |
1197 | temp = FindByID(tt, aid); | |
1198 | if (!temp) | |
1199 | ABORT_WITH(tt, PRNOENT); | |
1200 | code = pr_ReadEntry(tt, 0, temp, &tentry); | |
1201 | if (code) | |
1202 | ABORT_WITH(tt, code); | |
1203 | ||
1204 | /* afs does authenticate now */ | |
1205 | code = WhoIsThis(call, tt, cid); | |
1206 | if (code | |
1207 | || !AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY)) | |
1208 | ABORT_WITH(tt, PRPERM); | |
1209 | } | |
1210 | code = NameToID(tt, afs_inet_ntoa_r(iaddr.s_addr, hoststr), &hostid); | |
1211 | if (code == PRSUCCESS && hostid != 0) { | |
1212 | temp = FindByID(tt, hostid); | |
1213 | if (temp) { | |
1214 | code = pr_ReadEntry(tt, 0, temp, &host_tentry); | |
1215 | if (code == PRSUCCESS) | |
1216 | host_list = 1; | |
1217 | else | |
1218 | fprintf(stderr, "pr_ReadEntry returned %d\n", code); | |
1219 | } else | |
1220 | fprintf(stderr, "FindByID Failed -- Not found\n"); | |
1221 | } | |
1222 | if (host_list) | |
1223 | code = GetList2(tt, &tentry, &host_tentry, alist, 1); | |
1224 | else | |
1225 | code = GetList(tt, &tentry, alist, 1); | |
1226 | if (!code) | |
1227 | code = addWildCards(tt, alist, ntohl(ahost)); | |
1228 | if (code != PRSUCCESS) | |
1229 | ABORT_WITH(tt, code); | |
1230 | ||
1231 | code = ubik_EndTrans(tt); | |
1232 | return code; | |
1233 | } | |
1234 | ||
1235 | ||
1236 | afs_int32 | |
1237 | SPR_GetHostCPS(struct rx_call *call, afs_int32 ahost, prlist *alist, | |
1238 | afs_int32 *over) | |
1239 | { | |
1240 | afs_int32 code; | |
1241 | afs_int32 cid = ANONYMOUSID; | |
1242 | ||
1243 | code = getHostCPS(call, ahost, alist, over, &cid); | |
1244 | osi_auditU(call, PTS_GetHCPSEvent, code, AUD_HOST, htonl(ahost), AUD_END); | |
1245 | ViceLog(125, ("PTS_GetHostCPS: code %d ahost %u (0x%x)\n", code, ahost, ahost)); | |
1246 | return code; | |
1247 | } | |
1248 | ||
1249 | afs_int32 | |
1250 | getHostCPS(struct rx_call *call, afs_uint32 ahost, prlist *alist, | |
1251 | afs_int32 *over, afs_int32 *cid) | |
1252 | { | |
1253 | afs_int32 code, temp; | |
1254 | struct ubik_trans *tt; | |
1255 | struct prentry host_tentry; | |
1256 | afs_int32 hostid; | |
1257 | struct in_addr iaddr; | |
1258 | char hoststr[16]; | |
1259 | ||
1260 | *over = 0; | |
1261 | iaddr.s_addr = ntohl(ahost); | |
1262 | alist->prlist_len = 0; | |
1263 | alist->prlist_val = NULL; | |
1264 | ||
1265 | code = ReadPreamble(&tt); | |
1266 | if (code) | |
1267 | return code; | |
1268 | ||
1269 | code = WhoIsThis(call, tt, cid); | |
1270 | if (code) | |
1271 | ABORT_WITH(tt, PRPERM); | |
1272 | if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID) | |
1273 | ABORT_WITH(tt, PRPERM); | |
1274 | ||
1275 | code = NameToID(tt, afs_inet_ntoa_r(iaddr.s_addr, hoststr), &hostid); | |
1276 | if (code == PRSUCCESS && hostid != 0) { | |
1277 | temp = FindByID(tt, hostid); | |
1278 | if (temp) { | |
1279 | code = pr_ReadEntry(tt, 0, temp, &host_tentry); | |
1280 | if (code == PRSUCCESS) { | |
1281 | code = GetList(tt, &host_tentry, alist, 0); | |
1282 | if (code) | |
1283 | goto bad; | |
1284 | } else | |
1285 | fprintf(stderr, "pr_ReadEntry returned %d\n", code); | |
1286 | } else | |
1287 | fprintf(stderr, "FindByID Failed -- Not found\n"); | |
1288 | } | |
1289 | code = addWildCards(tt, alist, ntohl(ahost)); | |
1290 | bad: | |
1291 | if (code != PRSUCCESS) | |
1292 | ABORT_WITH(tt, code); | |
1293 | ||
1294 | code = ubik_EndTrans(tt); | |
1295 | return code; | |
1296 | } | |
1297 | ||
1298 | ||
1299 | afs_int32 | |
1300 | SPR_ListMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid) | |
1301 | { | |
1302 | afs_int32 code; | |
1303 | afs_int32 cid = ANONYMOUSID; | |
1304 | ||
1305 | code = listMax(call, uid, gid, &cid); | |
1306 | osi_auditU(call, PTS_LstMaxEvent, code, AUD_END); | |
1307 | ViceLog(125, ("PTS_ListMax: code %d\n", code)); | |
1308 | return code; | |
1309 | } | |
1310 | ||
1311 | afs_int32 | |
1312 | listMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid, afs_int32 *cid) | |
1313 | { | |
1314 | afs_int32 code; | |
1315 | struct ubik_trans *tt; | |
1316 | ||
1317 | code = ReadPreamble(&tt); | |
1318 | if (code) | |
1319 | return code; | |
1320 | ||
1321 | code = WhoIsThis(call, tt, cid); | |
1322 | if (code) | |
1323 | ABORT_WITH(tt, PRPERM); | |
1324 | if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID) | |
1325 | ABORT_WITH(tt, PRPERM); | |
1326 | ||
1327 | code = GetMax(tt, uid, gid); | |
1328 | if (code != PRSUCCESS) | |
1329 | ABORT_WITH(tt, code); | |
1330 | ||
1331 | code = ubik_EndTrans(tt); | |
1332 | if (code) | |
1333 | return code; | |
1334 | return PRSUCCESS; | |
1335 | } | |
1336 | ||
1337 | afs_int32 | |
1338 | SPR_SetMax(struct rx_call *call, afs_int32 aid, afs_int32 gflag) | |
1339 | { | |
1340 | afs_int32 code; | |
1341 | afs_int32 cid = ANONYMOUSID; | |
1342 | ||
1343 | code = setMax(call, aid, gflag, &cid); | |
1344 | osi_auditU(call, PTS_SetMaxEvent, code, AUD_ID, aid, AUD_LONG, gflag, | |
1345 | AUD_END); | |
1346 | ViceLog(125, ("PTS_SetMax: code %d cid %d aid %d gflag %d\n", code, cid, aid, gflag)); | |
1347 | return code; | |
1348 | } | |
1349 | ||
1350 | static afs_int32 | |
1351 | setMax(struct rx_call *call, afs_int32 aid, afs_int32 gflag, afs_int32 *cid) | |
1352 | { | |
1353 | afs_int32 code; | |
1354 | struct ubik_trans *tt; | |
1355 | ||
1356 | code = WritePreamble(&tt); | |
1357 | if (code) | |
1358 | return code; | |
1359 | ||
1360 | code = WhoIsThis(call, tt, cid); | |
1361 | if (code) | |
1362 | ABORT_WITH(tt, PRPERM); | |
1363 | if (!AccessOK(tt, *cid, 0, 0, 0)) | |
1364 | ABORT_WITH(tt, PRPERM); | |
1365 | if (((gflag & PRGRP) && (aid > 0)) || (!(gflag & PRGRP) && (aid < 0))) | |
1366 | ABORT_WITH(tt, PRBADARG); | |
1367 | ||
1368 | code = SetMax(tt, aid, gflag); | |
1369 | if (code != PRSUCCESS) | |
1370 | ABORT_WITH(tt, code); | |
1371 | ||
1372 | code = ubik_EndTrans(tt); | |
1373 | if (code) | |
1374 | return code; | |
1375 | return PRSUCCESS; | |
1376 | } | |
1377 | ||
1378 | afs_int32 | |
1379 | SPR_ListEntry(struct rx_call *call, afs_int32 aid, struct prcheckentry *aentry) | |
1380 | { | |
1381 | afs_int32 code; | |
1382 | afs_int32 cid = ANONYMOUSID; | |
1383 | ||
1384 | code = listEntry(call, aid, aentry, &cid); | |
1385 | osi_auditU(call, PTS_LstEntEvent, code, AUD_ID, aid, AUD_END); | |
1386 | ViceLog(125, ("PTS_ListEntry: code %d cid %d aid %d\n", code, cid, aid)); | |
1387 | return code; | |
1388 | } | |
1389 | ||
1390 | static afs_int32 | |
1391 | listEntry(struct rx_call *call, afs_int32 aid, struct prcheckentry *aentry, | |
1392 | afs_int32 *cid) | |
1393 | { | |
1394 | afs_int32 code; | |
1395 | struct ubik_trans *tt; | |
1396 | afs_int32 temp; | |
1397 | struct prentry tentry; | |
1398 | ||
1399 | code = ReadPreamble(&tt); | |
1400 | if (code) | |
1401 | return code; | |
1402 | ||
1403 | code = WhoIsThis(call, tt, cid); | |
1404 | if (code) | |
1405 | ABORT_WITH(tt, PRPERM); | |
1406 | if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID) | |
1407 | ABORT_WITH(tt, PRPERM); | |
1408 | temp = FindByID(tt, aid); | |
1409 | if (!temp) | |
1410 | ABORT_WITH(tt, PRNOENT); | |
1411 | code = pr_ReadEntry(tt, 0, temp, &tentry); | |
1412 | if (code != 0) | |
1413 | ABORT_WITH(tt, code); | |
1414 | if (!AccessOK(tt, *cid, &tentry, PRP_STATUS_MEM, PRP_STATUS_ANY)) | |
1415 | ABORT_WITH(tt, PRPERM); | |
1416 | ||
1417 | aentry->flags = tentry.flags >> PRIVATE_SHIFT; | |
1418 | if (aentry->flags == 0) { | |
1419 | if (tentry.flags & PRGRP) | |
1420 | aentry->flags = prp_group_default >> PRIVATE_SHIFT; | |
1421 | else | |
1422 | aentry->flags = prp_user_default >> PRIVATE_SHIFT; | |
1423 | } | |
1424 | aentry->owner = tentry.owner; | |
1425 | aentry->id = tentry.id; | |
1426 | strncpy(aentry->name, tentry.name, PR_MAXNAMELEN); | |
1427 | aentry->creator = tentry.creator; | |
1428 | aentry->ngroups = tentry.ngroups; | |
1429 | aentry->nusers = tentry.nusers; | |
1430 | aentry->count = tentry.count; | |
1431 | memset(aentry->reserved, 0, sizeof(aentry->reserved)); | |
1432 | code = ubik_EndTrans(tt); | |
1433 | if (code) | |
1434 | return code; | |
1435 | return PRSUCCESS; | |
1436 | } | |
1437 | ||
1438 | afs_int32 | |
1439 | SPR_ListEntries(struct rx_call *call, afs_int32 flag, afs_int32 startindex, | |
1440 | prentries *bulkentries, afs_int32 *nextstartindex) | |
1441 | { | |
1442 | afs_int32 code; | |
1443 | afs_int32 cid = ANONYMOUSID; | |
1444 | ||
1445 | code = listEntries(call, flag, startindex, bulkentries, nextstartindex, &cid); | |
1446 | osi_auditU(call, PTS_LstEntsEvent, code, AUD_LONG, flag, AUD_END); | |
1447 | ViceLog(125, ("PTS_ListEntries: code %d cid %d flag %d\n", code, cid, flag)); | |
1448 | return code; | |
1449 | } | |
1450 | ||
1451 | static afs_int32 | |
1452 | listEntries(struct rx_call *call, afs_int32 flag, afs_int32 startindex, | |
1453 | prentries *bulkentries, afs_int32 *nextstartindex, afs_int32 *cid) | |
1454 | { | |
1455 | afs_int32 code; | |
1456 | struct ubik_trans *tt; | |
1457 | afs_int32 i, eof, pos, maxentries, f; | |
1458 | struct prentry tentry; | |
1459 | afs_int32 pollcount = 0; | |
1460 | ||
1461 | *nextstartindex = -1; | |
1462 | bulkentries->prentries_val = 0; | |
1463 | bulkentries->prentries_len = 0; | |
1464 | ||
1465 | code = ReadPreamble(&tt); | |
1466 | if (code) | |
1467 | return code; | |
1468 | ||
1469 | /* Make sure we are an authenticated caller and that we are on the | |
1470 | * SYSADMIN list. | |
1471 | */ | |
1472 | code = WhoIsThis(call, tt, cid); | |
1473 | if (code) | |
1474 | ABORT_WITH(tt, PRPERM); | |
1475 | code = IsAMemberOf(tt, *cid, SYSADMINID); | |
1476 | if (!code && !pr_noAuth) | |
1477 | ABORT_WITH(tt, PRPERM); | |
1478 | ||
1479 | eof = ntohl(cheader.eofPtr) - sizeof(cheader); | |
1480 | maxentries = eof / sizeof(struct prentry); | |
1481 | for (i = startindex; i < maxentries; i++) { | |
1482 | pos = i * sizeof(struct prentry) + sizeof(cheader); | |
1483 | code = pr_ReadEntry(tt, 0, pos, &tentry); | |
1484 | if (code) | |
1485 | goto done; | |
1486 | ||
1487 | if (++pollcount > 50) { | |
1488 | #ifndef AFS_PTHREAD_ENV | |
1489 | IOMGR_Poll(); | |
1490 | #endif | |
1491 | pollcount = 0; | |
1492 | } | |
1493 | ||
1494 | f = (tentry.flags & PRTYPE); | |
1495 | if (((flag & PRUSERS) && (f == 0)) || /* User entry */ | |
1496 | ((flag & PRGROUPS) && (f & PRGRP))) { /* Group entry */ | |
1497 | code = put_prentries(&tentry, bulkentries); | |
1498 | if (code == -1) | |
1499 | break; /* Filled return array */ | |
1500 | if (code) | |
1501 | goto done; | |
1502 | } | |
1503 | } | |
1504 | code = 0; | |
1505 | if (i < maxentries) | |
1506 | *nextstartindex = i; | |
1507 | ||
1508 | done: | |
1509 | if (code) { | |
1510 | if (bulkentries->prentries_val) | |
1511 | free(bulkentries->prentries_val); | |
1512 | bulkentries->prentries_val = 0; | |
1513 | bulkentries->prentries_len = 0; | |
1514 | ABORT_WITH(tt, code); | |
1515 | } else { | |
1516 | code = ubik_EndTrans(tt); | |
1517 | } | |
1518 | if (code) | |
1519 | return code; | |
1520 | return PRSUCCESS; | |
1521 | } | |
1522 | ||
1523 | #define PR_MAXENTRIES 500 | |
1524 | static afs_int32 | |
1525 | put_prentries(struct prentry *tentry, prentries *bulkentries) | |
1526 | { | |
1527 | struct prlistentries *entry; | |
1528 | ||
1529 | if (bulkentries->prentries_val == 0) { | |
1530 | bulkentries->prentries_len = 0; | |
1531 | bulkentries->prentries_val = malloc(PR_MAXENTRIES * | |
1532 | sizeof(struct prlistentries)); | |
1533 | if (!bulkentries->prentries_val) { | |
1534 | return (PRNOMEM); | |
1535 | } | |
1536 | } | |
1537 | ||
1538 | if (bulkentries->prentries_len >= PR_MAXENTRIES) { | |
1539 | return (-1); | |
1540 | } | |
1541 | ||
1542 | entry = bulkentries->prentries_val; | |
1543 | entry += bulkentries->prentries_len; | |
1544 | ||
1545 | memset(entry, 0, sizeof(*entry)); | |
1546 | entry->flags = tentry->flags >> PRIVATE_SHIFT; | |
1547 | if (entry->flags == 0) { | |
1548 | entry->flags = | |
1549 | ((tentry-> | |
1550 | flags & PRGRP) ? prp_group_default : prp_user_default) >> | |
1551 | PRIVATE_SHIFT; | |
1552 | } | |
1553 | entry->owner = tentry->owner; | |
1554 | entry->id = tentry->id; | |
1555 | entry->creator = tentry->creator; | |
1556 | entry->ngroups = tentry->ngroups; | |
1557 | entry->nusers = tentry->nusers; | |
1558 | entry->count = tentry->count; | |
1559 | strncpy(entry->name, tentry->name, PR_MAXNAMELEN); | |
1560 | bulkentries->prentries_len++; | |
1561 | return 0; | |
1562 | } | |
1563 | ||
1564 | afs_int32 | |
1565 | SPR_ChangeEntry(struct rx_call *call, afs_int32 aid, char *name, afs_int32 oid, | |
1566 | afs_int32 newid) | |
1567 | { | |
1568 | afs_int32 code; | |
1569 | afs_int32 cid = ANONYMOUSID; | |
1570 | ||
1571 | code = changeEntry(call, aid, name, oid, newid, &cid); | |
1572 | osi_auditU(call, PTS_ChgEntEvent, code, AUD_ID, aid, AUD_STR, name, | |
1573 | AUD_LONG, oid, AUD_LONG, newid, AUD_END); | |
1574 | ViceLog(5, ("PTS_ChangeEntry: code %d cid %d aid %d name %s oid %d newid %d\n", code, cid, aid, name, oid, newid)); | |
1575 | return code; | |
1576 | } | |
1577 | ||
1578 | static afs_int32 | |
1579 | changeEntry(struct rx_call *call, afs_int32 aid, char *name, afs_int32 oid, | |
1580 | afs_int32 newid, afs_int32 *cid) | |
1581 | { | |
1582 | afs_int32 code; | |
1583 | struct ubik_trans *tt; | |
1584 | afs_int32 pos; | |
1585 | ||
1586 | if (!name) | |
1587 | return PRPERM; | |
1588 | stolower(name); | |
1589 | ||
1590 | if (aid == ANYUSERID || aid == AUTHUSERID || aid == ANONYMOUSID | |
1591 | || aid == SYSADMINID) | |
1592 | return PRPERM; | |
1593 | ||
1594 | code = WritePreamble(&tt); | |
1595 | if (code) | |
1596 | return code; | |
1597 | ||
1598 | code = WhoIsThis(call, tt, cid); | |
1599 | if (code) | |
1600 | ABORT_WITH(tt, PRPERM); | |
1601 | pos = FindByID(tt, aid); | |
1602 | if (!pos) | |
1603 | ABORT_WITH(tt, PRNOENT); | |
1604 | /* protection check in changeentry */ | |
1605 | code = ChangeEntry(tt, aid, *cid, name, oid, newid); | |
1606 | if (code != PRSUCCESS) | |
1607 | ABORT_WITH(tt, code); | |
1608 | ||
1609 | code = ubik_EndTrans(tt); | |
1610 | return code; | |
1611 | } | |
1612 | ||
1613 | afs_int32 | |
1614 | SPR_SetFieldsEntry(struct rx_call *call, | |
1615 | afs_int32 id, | |
1616 | afs_int32 mask, /* specify which fields to update */ | |
1617 | afs_int32 flags, afs_int32 ngroups, afs_int32 nusers, | |
1618 | afs_int32 spare1, afs_int32 spare2) | |
1619 | { | |
1620 | afs_int32 code; | |
1621 | afs_int32 cid = ANONYMOUSID; | |
1622 | ||
1623 | code = | |
1624 | setFieldsEntry(call, id, mask, flags, ngroups, nusers, spare1, | |
1625 | spare2, &cid); | |
1626 | osi_auditU(call, PTS_SetFldEntEvent, code, AUD_ID, id, AUD_END); | |
1627 | ViceLog(5, ("PTS_SetFieldsEntry: code %d cid %d id %d\n", code, cid, id)); | |
1628 | return code; | |
1629 | } | |
1630 | ||
1631 | static afs_int32 | |
1632 | setFieldsEntry(struct rx_call *call, | |
1633 | afs_int32 id, | |
1634 | afs_int32 mask, /* specify which fields to update */ | |
1635 | afs_int32 flags, afs_int32 ngroups, afs_int32 nusers, | |
1636 | afs_int32 spare1, afs_int32 spare2, afs_int32 *cid) | |
1637 | { | |
1638 | afs_int32 code; | |
1639 | struct ubik_trans *tt; | |
1640 | afs_int32 pos; | |
1641 | struct prentry tentry; | |
1642 | afs_int32 tflags; | |
1643 | ||
1644 | if (mask == 0) | |
1645 | return 0; /* no-op */ | |
1646 | ||
1647 | if (id == ANYUSERID || id == AUTHUSERID || id == ANONYMOUSID) | |
1648 | return PRPERM; | |
1649 | ||
1650 | code = WritePreamble(&tt); | |
1651 | if (code) | |
1652 | return code; | |
1653 | ||
1654 | code = WhoIsThis(call, tt, cid); | |
1655 | if (code) | |
1656 | ABORT_WITH(tt, PRPERM); | |
1657 | pos = FindByID(tt, id); | |
1658 | if (!pos) | |
1659 | ABORT_WITH(tt, PRNOENT); | |
1660 | code = pr_ReadEntry(tt, 0, pos, &tentry); | |
1661 | if (code) | |
1662 | ABORT_WITH(tt, code); | |
1663 | tflags = tentry.flags; | |
1664 | ||
1665 | if (mask & (PR_SF_NGROUPS | PR_SF_NUSERS)) { | |
1666 | if (!AccessOK(tt, *cid, 0, 0, 0)) | |
1667 | ABORT_WITH(tt, PRPERM); | |
1668 | if ((tflags & PRQUOTA) == 0) { /* default if only setting one */ | |
1669 | tentry.ngroups = tentry.nusers = 20; | |
1670 | } | |
1671 | } else { | |
1672 | if (!AccessOK(tt, *cid, &tentry, 0, 0)) | |
1673 | ABORT_WITH(tt, PRPERM); | |
1674 | } | |
1675 | ||
1676 | if (mask & 0xffff) { /* if setting flag bits */ | |
1677 | afs_int32 flagsMask = mask & 0xffff; | |
1678 | tflags &= ~(flagsMask << PRIVATE_SHIFT); | |
1679 | tflags |= (flags & flagsMask) << PRIVATE_SHIFT; | |
1680 | tflags |= PRACCESS; | |
1681 | } | |
1682 | ||
1683 | if (mask & PR_SF_NGROUPS) { /* setting group limit */ | |
1684 | if (ngroups < 0) | |
1685 | ABORT_WITH(tt, PRBADARG); | |
1686 | tentry.ngroups = ngroups; | |
1687 | tflags |= PRQUOTA; | |
1688 | } | |
1689 | ||
1690 | if (mask & PR_SF_NUSERS) { /* setting foreign user limit */ | |
1691 | if (nusers < 0) | |
1692 | ABORT_WITH(tt, PRBADARG); | |
1693 | tentry.nusers = nusers; | |
1694 | tflags |= PRQUOTA; | |
1695 | } | |
1696 | tentry.flags = tflags; | |
1697 | ||
1698 | code = pr_WriteEntry(tt, 0, pos, &tentry); | |
1699 | if (code) | |
1700 | ABORT_WITH(tt, code); | |
1701 | ||
1702 | code = ubik_EndTrans(tt); | |
1703 | return code; | |
1704 | } | |
1705 | ||
1706 | afs_int32 | |
1707 | SPR_ListElements(struct rx_call *call, afs_int32 aid, prlist *alist, | |
1708 | afs_int32 *over) | |
1709 | { | |
1710 | afs_int32 code; | |
1711 | afs_int32 cid = ANONYMOUSID; | |
1712 | ||
1713 | code = listElements(call, aid, alist, over, &cid); | |
1714 | osi_auditU(call, PTS_LstEleEvent, code, AUD_ID, aid, AUD_END); | |
1715 | ViceLog(125, ("PTS_ListElements: code %d cid %d aid %d\n", code, cid, aid)); | |
1716 | return code; | |
1717 | } | |
1718 | ||
1719 | static afs_int32 | |
1720 | listElements(struct rx_call *call, afs_int32 aid, prlist *alist, | |
1721 | afs_int32 *over, afs_int32 *cid) | |
1722 | { | |
1723 | afs_int32 code; | |
1724 | struct ubik_trans *tt; | |
1725 | afs_int32 temp; | |
1726 | struct prentry tentry; | |
1727 | ||
1728 | *over = 0; | |
1729 | alist->prlist_len = 0; | |
1730 | alist->prlist_val = NULL; | |
1731 | ||
1732 | code = ReadPreamble(&tt); | |
1733 | if (code) | |
1734 | return code; | |
1735 | ||
1736 | code = WhoIsThis(call, tt, cid); | |
1737 | if (code) | |
1738 | ABORT_WITH(tt, PRPERM); | |
1739 | ||
1740 | temp = FindByID(tt, aid); | |
1741 | if (!temp) | |
1742 | ABORT_WITH(tt, PRNOENT); | |
1743 | code = pr_ReadEntry(tt, 0, temp, &tentry); | |
1744 | if (code) | |
1745 | ABORT_WITH(tt, code); | |
1746 | if (!AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY)) | |
1747 | ABORT_WITH(tt, PRPERM); | |
1748 | ||
1749 | code = GetList(tt, &tentry, alist, 0); | |
1750 | if (code != PRSUCCESS) | |
1751 | ABORT_WITH(tt, code); | |
1752 | ||
1753 | code = ubik_EndTrans(tt); | |
1754 | return code; | |
1755 | } | |
1756 | ||
1757 | ||
1758 | afs_int32 | |
1759 | SPR_ListSuperGroups(struct rx_call *call, afs_int32 aid, prlist *alist, | |
1760 | afs_int32 *over) | |
1761 | { | |
1762 | #if defined(SUPERGROUPS) | |
1763 | afs_int32 code; | |
1764 | afs_int32 cid = ANONYMOUSID; | |
1765 | ||
1766 | code = listSuperGroups(call, aid, alist, over, &cid); | |
1767 | osi_auditU(call, PTS_LstSGrps, code, AUD_ID, aid, AUD_END); | |
1768 | ViceLog(125, ("PTS_ListSuperGroups: code %d cid %d aid %d\n", code, cid, aid)); | |
1769 | return code; | |
1770 | #else | |
1771 | return RXGEN_OPCODE; | |
1772 | #endif | |
1773 | } | |
1774 | ||
1775 | #if defined(SUPERGROUPS) | |
1776 | static afs_int32 | |
1777 | listSuperGroups(struct rx_call *call, afs_int32 aid, prlist *alist, | |
1778 | afs_int32 *over, afs_int32 *cid) | |
1779 | { | |
1780 | afs_int32 code; | |
1781 | struct ubik_trans *tt; | |
1782 | afs_int32 temp; | |
1783 | struct prentry tentry; | |
1784 | ||
1785 | alist->prlist_len = 0; | |
1786 | alist->prlist_val = (afs_int32 *) 0; | |
1787 | ||
1788 | code = ReadPreamble(&tt); | |
1789 | if (code) | |
1790 | return code; | |
1791 | ||
1792 | code = WhoIsThis(call, tt, cid); | |
1793 | if (code) | |
1794 | ABORT_WITH(tt, PRPERM); | |
1795 | if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID) | |
1796 | ABORT_WITH(tt, PRPERM); | |
1797 | ||
1798 | code = ubik_SetLock(tt, 1, 1, LOCKREAD); | |
1799 | if (code) | |
1800 | ABORT_WITH(tt, code); | |
1801 | ||
1802 | temp = FindByID(tt, aid); | |
1803 | if (!temp) | |
1804 | ABORT_WITH(tt, PRNOENT); | |
1805 | code = pr_ReadEntry(tt, 0, temp, &tentry); | |
1806 | if (code) | |
1807 | ABORT_WITH(tt, code); | |
1808 | if (!AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY)) | |
1809 | ABORT_WITH(tt, PRPERM); | |
1810 | ||
1811 | code = GetSGList(tt, &tentry, alist); | |
1812 | *over = 0; | |
1813 | if (code == PRTOOMANY) | |
1814 | *over = 1; | |
1815 | else if (code != PRSUCCESS) | |
1816 | ABORT_WITH(tt, code); | |
1817 | ||
1818 | code = ubik_EndTrans(tt); | |
1819 | ||
1820 | return code; | |
1821 | } | |
1822 | ||
1823 | #endif /* SUPERGROUPS */ | |
1824 | ||
1825 | /* | |
1826 | * SPR_ListOwned | |
1827 | * List the entries owned by this id. If the id is zero, | |
1828 | * return the orphans list. This will return up to PR_MAXGROUPS | |
1829 | * at a time with the lastP available to get the rest. The | |
1830 | * maximum value is enforced in GetOwnedChain(). | |
1831 | */ | |
1832 | afs_int32 | |
1833 | SPR_ListOwned(struct rx_call *call, afs_int32 aid, prlist *alist, | |
1834 | afs_int32 *lastP) | |
1835 | { | |
1836 | afs_int32 code; | |
1837 | afs_int32 cid = ANONYMOUSID; | |
1838 | ||
1839 | code = listOwned(call, aid, alist, lastP, &cid); | |
1840 | osi_auditU(call, PTS_LstOwnEvent, code, AUD_ID, aid, AUD_END); | |
1841 | ViceLog(125, ("PTS_ListOwned: code %d cid %d aid %d\n", code, cid, aid)); | |
1842 | return code; | |
1843 | } | |
1844 | ||
1845 | afs_int32 | |
1846 | listOwned(struct rx_call *call, afs_int32 aid, prlist *alist, afs_int32 *lastP, | |
1847 | afs_int32 *cid) | |
1848 | { | |
1849 | afs_int32 code; | |
1850 | struct ubik_trans *tt; | |
1851 | struct prentry tentry; | |
1852 | afs_int32 head = 0; | |
1853 | afs_int32 start; | |
1854 | ||
1855 | alist->prlist_len = 0; | |
1856 | alist->prlist_val = NULL; | |
1857 | ||
1858 | if (!lastP) | |
1859 | return PRBADARG; | |
1860 | start = *lastP; | |
1861 | *lastP = 0; | |
1862 | ||
1863 | code = ReadPreamble(&tt); | |
1864 | if (code) | |
1865 | return code; | |
1866 | ||
1867 | code = WhoIsThis(call, tt, cid); | |
1868 | if (code) | |
1869 | ABORT_WITH(tt, PRPERM); | |
1870 | ||
1871 | if (start) { | |
1872 | code = pr_ReadEntry(tt, 0, start, &tentry); | |
1873 | if (!code && (tentry.owner == aid)) | |
1874 | head = start; /* pick up where we left off */ | |
1875 | } | |
1876 | ||
1877 | if (!head) { | |
1878 | if (aid) { | |
1879 | afs_int32 loc = FindByID(tt, aid); | |
1880 | if (loc == 0) | |
1881 | ABORT_WITH(tt, PRNOENT); | |
1882 | code = pr_ReadEntry(tt, 0, loc, &tentry); | |
1883 | if (code) | |
1884 | ABORT_WITH(tt, code); | |
1885 | ||
1886 | if (!AccessOK(tt, *cid, &tentry, -1, PRP_OWNED_ANY)) | |
1887 | ABORT_WITH(tt, PRPERM); | |
1888 | head = tentry.owned; | |
1889 | } else { | |
1890 | if (!AccessOK(tt, *cid, 0, 0, 0)) | |
1891 | ABORT_WITH(tt, PRPERM); | |
1892 | head = ntohl(cheader.orphan); | |
1893 | } | |
1894 | } | |
1895 | ||
1896 | code = GetOwnedChain(tt, &head, alist); | |
1897 | if (code) { | |
1898 | if (code == PRTOOMANY) | |
1899 | *lastP = head; | |
1900 | else | |
1901 | ABORT_WITH(tt, code); | |
1902 | } | |
1903 | ||
1904 | code = ubik_EndTrans(tt); | |
1905 | return code; | |
1906 | } | |
1907 | ||
1908 | afs_int32 | |
1909 | SPR_IsAMemberOf(struct rx_call *call, afs_int32 uid, afs_int32 gid, | |
1910 | afs_int32 *flag) | |
1911 | { | |
1912 | afs_int32 code; | |
1913 | afs_int32 cid = ANONYMOUSID; | |
1914 | ||
1915 | code = isAMemberOf(call, uid, gid, flag, &cid); | |
1916 | osi_auditU(call, PTS_IsMemOfEvent, code, AUD_LONG, uid, AUD_LONG, gid, | |
1917 | AUD_END); | |
1918 | ViceLog(125, ("PTS_IsAMemberOf: code %d cid %d uid %d gid %d\n", code, cid, uid, gid)); | |
1919 | return code; | |
1920 | } | |
1921 | ||
1922 | static afs_int32 | |
1923 | isAMemberOf(struct rx_call *call, afs_int32 uid, afs_int32 gid, afs_int32 *flag, | |
1924 | afs_int32 *cid) | |
1925 | { | |
1926 | afs_int32 code; | |
1927 | struct ubik_trans *tt; | |
1928 | ||
1929 | code = ReadPreamble(&tt); | |
1930 | if (code) | |
1931 | return code; | |
1932 | ||
1933 | { | |
1934 | afs_int32 uloc = FindByID(tt, uid); | |
1935 | afs_int32 gloc = FindByID(tt, gid); | |
1936 | struct prentry uentry, gentry; | |
1937 | ||
1938 | if (!uloc || !gloc) | |
1939 | ABORT_WITH(tt, PRNOENT); | |
1940 | code = WhoIsThis(call, tt, cid); | |
1941 | if (code) | |
1942 | ABORT_WITH(tt, PRPERM); | |
1943 | code = pr_ReadEntry(tt, 0, uloc, &uentry); | |
1944 | if (code) | |
1945 | ABORT_WITH(tt, code); | |
1946 | code = pr_ReadEntry(tt, 0, gloc, &gentry); | |
1947 | if (code) | |
1948 | ABORT_WITH(tt, code); | |
1949 | #if !defined(SUPERGROUPS) | |
1950 | if ((uentry.flags & PRGRP) || !(gentry.flags & PRGRP)) | |
1951 | ABORT_WITH(tt, PRBADARG); | |
1952 | #else | |
1953 | if (!(gentry.flags & PRGRP)) | |
1954 | ABORT_WITH(tt, PRBADARG); | |
1955 | #endif | |
1956 | if (!AccessOK(tt, *cid, &uentry, 0, PRP_MEMBER_ANY) | |
1957 | && !AccessOK(tt, *cid, &gentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY)) | |
1958 | ABORT_WITH(tt, PRPERM); | |
1959 | } | |
1960 | ||
1961 | *flag = IsAMemberOf(tt, uid, gid); | |
1962 | code = ubik_EndTrans(tt); | |
1963 | return code; | |
1964 | } | |
1965 | ||
1966 | static afs_int32 | |
1967 | addWildCards(struct ubik_trans *tt, prlist *alist, afs_uint32 host) | |
1968 | { | |
1969 | afs_int32 temp; | |
1970 | struct prentry tentry; | |
1971 | prlist wlist; | |
1972 | unsigned wild = htonl(0xffffff00); | |
1973 | struct in_addr iaddr; | |
1974 | afs_int32 hostid; | |
1975 | int size = 0, i, code; | |
1976 | int added = 0; | |
1977 | char hoststr[16]; | |
1978 | ||
1979 | while ((host = (host & wild))) { | |
1980 | wild = htonl(ntohl(wild) << 8); | |
1981 | iaddr.s_addr = host; | |
1982 | code = NameToID(tt, afs_inet_ntoa_r(iaddr.s_addr, hoststr), &hostid); | |
1983 | if (code == PRSUCCESS && hostid != 0) { | |
1984 | temp = FindByID(tt, hostid); | |
1985 | if (temp) { | |
1986 | code = pr_ReadEntry(tt, 0, temp, &tentry); | |
1987 | if (code != PRSUCCESS) | |
1988 | continue; | |
1989 | } else | |
1990 | continue; | |
1991 | } else | |
1992 | continue; | |
1993 | wlist.prlist_len = 0; | |
1994 | wlist.prlist_val = NULL; | |
1995 | ||
1996 | code = GetList(tt, &tentry, &wlist, 0); | |
1997 | if (code) | |
1998 | return code; | |
1999 | added += wlist.prlist_len; | |
2000 | for (i = 0; i < wlist.prlist_len; i++) { | |
2001 | if (!inCPS(*alist, wlist.prlist_val[i])) | |
2002 | if ((code = AddToPRList(alist, &size, wlist.prlist_val[i]))) { | |
2003 | free(wlist.prlist_val); | |
2004 | return (code); | |
2005 | } | |
2006 | } | |
2007 | if (wlist.prlist_val) | |
2008 | free(wlist.prlist_val); | |
2009 | } | |
2010 | if (added) | |
2011 | qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp); | |
2012 | return 0; | |
2013 | } | |
2014 | ||
2015 | static afs_int32 | |
2016 | WhoIsThisWithName(struct rx_call *acall, struct ubik_trans *at, afs_int32 *aid, | |
2017 | char *aname) | |
2018 | { | |
2019 | afs_int32 islocal = 1; | |
2020 | /* aid is set to the identity of the caller, if known, else ANONYMOUSID */ | |
2021 | /* returns -1 and sets aid to ANONYMOUSID on any failure */ | |
2022 | struct rx_connection *tconn; | |
2023 | afs_int32 code; | |
2024 | char tcell[MAXKTCREALMLEN]; | |
2025 | char name[MAXKTCNAMELEN]; | |
2026 | char inst[MAXKTCNAMELEN]; | |
2027 | int ilen; | |
2028 | char vname[256]; | |
2029 | ||
2030 | *aid = ANONYMOUSID; | |
2031 | tconn = rx_ConnectionOf(acall); | |
2032 | code = rx_SecurityClassOf(tconn); | |
2033 | if (code == RX_SECIDX_NULL) | |
2034 | return 0; | |
2035 | else if (code == RX_SECIDX_VAB) { | |
2036 | goto done; /* no longer supported */ | |
2037 | } else if (code == RX_SECIDX_KAD) { | |
2038 | if ((code = rxkad_GetServerInfo(rx_ConnectionOf(acall), NULL, NULL, | |
2039 | name, inst, tcell, NULL))) | |
2040 | goto done; | |
2041 | ||
2042 | if (tcell[0]) { | |
2043 | code = afsconf_IsLocalRealmMatch(prdir, &islocal, name, inst, tcell); | |
2044 | if (code) | |
2045 | goto done; | |
2046 | } | |
2047 | strncpy(vname, name, sizeof(vname)); | |
2048 | if ((ilen = strlen(inst))) { | |
2049 | if (strlen(vname) + 1 + ilen >= sizeof(vname)) | |
2050 | goto done; | |
2051 | strcat(vname, "."); | |
2052 | strcat(vname, inst); | |
2053 | } | |
2054 | if (!islocal) { | |
2055 | if (strlen(vname) + strlen(tcell) + 1 >= sizeof(vname)) | |
2056 | goto done; | |
2057 | strcat(vname, "@"); | |
2058 | strcat(vname, tcell); | |
2059 | lcstring(vname, vname, sizeof(vname)); | |
2060 | NameToID(at, vname, aid); | |
2061 | if (aname) | |
2062 | strcpy(aname, vname); | |
2063 | return 2; | |
2064 | } | |
2065 | ||
2066 | if (strcmp(AUTH_SUPERUSER, vname) == 0) | |
2067 | *aid = SYSADMINID; /* special case for the fileserver */ | |
2068 | else { | |
2069 | lcstring(vname, vname, sizeof(vname)); | |
2070 | code = NameToID(at, vname, aid); | |
2071 | } | |
2072 | } | |
2073 | done: | |
2074 | if (code && !pr_noAuth) | |
2075 | return -1; | |
2076 | return 0; | |
2077 | } |