Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / ptserver / ptprocs.c
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, &centry);
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, &centry);
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 }