2 * Copyright 2000, International Business Machines Corporation and others.
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
11 * (3) function addToGroup
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.
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.
27 * (5) function RemoveFromGroup
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.
35 * (6) Add new functions PR_ListSuperGroups and
38 * (7) function isAMemberOf
40 * 1. Allow groups to be members of groups.
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).
50 #include <afsconfig.h>
51 #include <afs/param.h>
59 #include <afs/afsutil.h>
68 #include "ptprototypes.h"
69 #include "afs/audit.h"
71 #ifdef AFS_ATHENA_STDENV
75 extern int restricted;
76 extern struct ubik_dbase *dbase;
78 extern char *pr_realmName;
79 extern int prp_group_default;
80 extern int prp_user_default;
82 static afs_int32 iNewEntry(struct rx_call *call, char aname[], afs_int32 aid,
83 afs_int32 oid, afs_int32 *cid);
84 static afs_int32 newEntry(struct rx_call *call, char aname[], afs_int32 flag,
85 afs_int32 oid, afs_int32 *aid, afs_int32 *cid);
86 static afs_int32 whereIsIt(struct rx_call *call, afs_int32 aid, afs_int32 *apos,
88 static afs_int32 dumpEntry(struct rx_call *call, afs_int32 apos,
89 struct prdebugentry *aentry, afs_int32 *cid);
90 static afs_int32 addToGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid,
92 static afs_int32 nameToID(struct rx_call *call, namelist *aname, idlist *aid);
93 static afs_int32 idToName(struct rx_call *call, idlist *aid, namelist *aname);
94 static afs_int32 Delete(struct rx_call *call, afs_int32 aid, afs_int32 *cid);
95 static afs_int32 UpdateEntry(struct rx_call *call, afs_int32 aid, char *name,
96 struct PrUpdateEntry *uentry, afs_int32 *cid);
97 static afs_int32 removeFromGroup(struct rx_call *call, afs_int32 aid,
98 afs_int32 gid, afs_int32 *cid);
99 static afs_int32 getCPS(struct rx_call *call, afs_int32 aid, prlist *alist,
100 afs_int32 *over, afs_int32 *cid);
101 static afs_int32 getCPS2(struct rx_call *call, afs_int32 aid, afs_uint32 ahost,
102 prlist *alist, afs_int32 *over, afs_int32 *cid);
103 static afs_int32 getHostCPS(struct rx_call *call, afs_uint32 ahost,
104 prlist *alist, afs_int32 *over);
105 static afs_int32 listMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid);
106 static afs_int32 setMax(struct rx_call *call, afs_int32 aid, afs_int32 gflag,
108 static afs_int32 listEntry(struct rx_call *call, afs_int32 aid,
109 struct prcheckentry *aentry, afs_int32 *cid);
110 static afs_int32 listEntries(struct rx_call *call, afs_int32 flag,
111 afs_int32 startindex, prentries *bulkentries,
112 afs_int32 *nextstartindex, afs_int32 *cid);
113 static afs_int32 put_prentries(struct prentry *tentry, prentries *bulkentries);
114 static afs_int32 changeEntry(struct rx_call *call, afs_int32 aid, char *name,
115 afs_int32 oid, afs_int32 newid, afs_int32 *cid);
116 static afs_int32 setFieldsEntry(struct rx_call *call, afs_int32 id,
117 afs_int32 mask, afs_int32 flags,
118 afs_int32 ngroups, afs_int32 nusers,
119 afs_int32 spare1, afs_int32 spare2,
121 static afs_int32 listElements(struct rx_call *call, afs_int32 aid,
122 prlist *alist, afs_int32 *over, afs_int32 *cid);
123 #if defined(SUPERGROUPS)
124 static afs_int32 listSuperGroups(struct rx_call *call, afs_int32 aid,
125 prlist *alist, afs_int32 *over,
128 static afs_int32 listOwned(struct rx_call *call, afs_int32 aid, prlist *alist,
129 afs_int32 *lastP, afs_int32 *cid);
130 static afs_int32 isAMemberOf(struct rx_call *call, afs_int32 uid, afs_int32 gid,
131 afs_int32 *flag, afs_int32 *cid);
132 static afs_int32 addWildCards(struct ubik_trans *tt, prlist *alist,
134 static afs_int32 WhoIsThisWithName(struct rx_call *acall,
135 struct ubik_trans *at, afs_int32 *aid,
138 /* when we abort, the ubik cachedVersion will be reset, so we'll read in the
139 * header on the next call.
140 * Abort the transaction and return the code.
142 #define ABORT_WITH(tt,code) return(ubik_AbortTrans(tt),code)
145 CreateOK(struct ubik_trans *ut, afs_int32 cid, afs_int32 oid, afs_int32 flag,
148 if (restricted && !admin)
151 if (flag & PRFOREIGN) {
152 /* Foreign users are recognized by the '@' sign and
153 * not by the PRFOREIGN flag.
156 } else if (flag & PRGRP) {
157 /* Allow anonymous group creation only if owner specified
158 * and running noAuth.
160 if (cid == ANONYMOUSID) {
161 if ((oid == 0) || !pr_noAuth)
164 } else { /* creating a user */
165 if (!admin && !pr_noAuth)
172 WhoIsThis(struct rx_call *acall, struct ubik_trans *at, afs_int32 *aid)
174 int code = WhoIsThisWithName(acall, at, aid, NULL);
175 if (code == 2 && *aid == ANONYMOUSID)
181 SPR_INewEntry(struct rx_call *call, char aname[], afs_int32 aid, afs_int32 oid)
184 afs_int32 cid = ANONYMOUSID;
186 code = iNewEntry(call, aname, aid, oid, &cid);
187 osi_auditU(call, PTS_INewEntEvent, code, AUD_ID, aid, AUD_STR, aname,
188 AUD_ID, oid, AUD_END);
189 ViceLog(5, ("PTS_INewEntry: code %d cid %d aid %d aname %s oid %d\n", code, cid, aid, aname, oid));
194 iNewEntry(struct rx_call *call, char aname[], afs_int32 aid, afs_int32 oid,
197 /* used primarily for conversion - not intended to be used as usual means
198 * of entering people into the database. */
199 struct ubik_trans *tt;
206 if (code != PRSUCCESS)
208 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
211 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
213 ABORT_WITH(tt, code);
214 code = read_DbHeader(tt);
216 ABORT_WITH(tt, code);
218 code = WhoIsThis(call, tt, cid);
220 ABORT_WITH(tt, PRPERM);
221 admin = IsAMemberOf(tt, *cid, SYSADMINID);
223 /* first verify the id is good */
225 ABORT_WITH(tt, PRPERM);
228 /* only sysadmin can reuse a group id */
229 if (!admin && !pr_noAuth && (aid != ntohl(cheader.maxGroup) - 1))
230 ABORT_WITH(tt, PRPERM);
232 if (FindByID(tt, aid))
233 ABORT_WITH(tt, PRIDEXIST);
235 /* check a few other things */
236 if (!CreateOK(tt, *cid, oid, gflag, admin))
237 ABORT_WITH(tt, PRPERM);
239 code = CreateEntry(tt, aname, &aid, 1, gflag, oid, *cid);
240 if (code != PRSUCCESS)
241 ABORT_WITH(tt, code);
243 /* finally, commit transaction */
244 code = ubik_EndTrans(tt);
252 SPR_NewEntry(struct rx_call *call, char aname[], afs_int32 flag, afs_int32 oid,
256 afs_int32 cid = ANONYMOUSID;
258 code = newEntry(call, aname, flag, oid, aid, &cid);
259 osi_auditU(call, PTS_NewEntEvent, code, AUD_ID, *aid, AUD_STR, aname,
260 AUD_ID, oid, AUD_END);
261 ViceLog(5, ("PTS_NewEntry: code %d cid %d aid %d aname %s oid %d\n", code, cid, *aid, aname, oid));
266 newEntry(struct rx_call *call, char aname[], afs_int32 flag, afs_int32 oid,
267 afs_int32 *aid, afs_int32 *cid)
270 struct ubik_trans *tt;
272 char cname[PR_MAXNAMELEN];
277 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
280 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
282 ABORT_WITH(tt, code);
283 code = read_DbHeader(tt);
285 ABORT_WITH(tt, code);
287 /* this is for cross-cell self registration. It is not added in the
288 * SPR_INewEntry because we want self-registration to only do
289 * automatic id assignment.
291 code = WhoIsThisWithName(call, tt, cid, cname);
292 if (code != 2) { /* 2 specifies that this is a foreign cell request */
294 ABORT_WITH(tt, PRPERM);
295 admin = IsAMemberOf(tt, *cid, SYSADMINID);
297 admin = ((!restricted && !strcmp(aname, cname))) || IsAMemberOf(tt, *cid, SYSADMINID);
298 oid = *cid = SYSADMINID;
300 if (!CreateOK(tt, *cid, oid, flag, admin))
301 ABORT_WITH(tt, PRPERM);
303 code = CreateEntry(tt, aname, aid, 0, flag, oid, *cid);
304 if (code != PRSUCCESS)
305 ABORT_WITH(tt, code);
307 code = ubik_EndTrans(tt);
316 SPR_WhereIsIt(struct rx_call *call, afs_int32 aid, afs_int32 *apos)
319 afs_int32 cid = ANONYMOUSID;
321 code = whereIsIt(call, aid, apos, &cid);
322 osi_auditU(call, PTS_WheIsItEvent, code, AUD_ID, aid, AUD_LONG, *apos,
324 ViceLog(125, ("PTS_WhereIsIt: code %d cid %d aid %d apos %d\n", code, cid, aid, *apos));
329 whereIsIt(struct rx_call *call, afs_int32 aid, afs_int32 *apos, afs_int32 *cid)
332 struct ubik_trans *tt;
336 if (code != PRSUCCESS)
338 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
341 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
343 ABORT_WITH(tt, code);
344 code = read_DbHeader(tt);
346 ABORT_WITH(tt, code);
348 code = WhoIsThis(call, tt, cid);
350 ABORT_WITH(tt, PRPERM);
352 temp = FindByID(tt, aid);
354 ABORT_WITH(tt, PRNOENT);
356 code = ubik_EndTrans(tt);
364 SPR_DumpEntry(struct rx_call *call, afs_int32 apos,
365 struct prdebugentry *aentry)
368 afs_int32 cid = ANONYMOUSID;
370 code = dumpEntry(call, apos, aentry, &cid);
371 osi_auditU(call, PTS_DmpEntEvent, code, AUD_LONG, apos, AUD_END);
372 ViceLog(125, ("PTS_DumpEntry: code %d cid %d apos %d\n", code, cid, apos));
377 dumpEntry(struct rx_call *call, afs_int32 apos, struct prdebugentry *aentry,
381 struct ubik_trans *tt;
384 if (code != PRSUCCESS)
386 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
389 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
391 ABORT_WITH(tt, code);
392 code = read_DbHeader(tt);
394 ABORT_WITH(tt, code);
396 code = WhoIsThis(call, tt, cid);
398 ABORT_WITH(tt, PRPERM);
399 code = pr_ReadEntry(tt, 0, apos, (struct prentry *)aentry);
401 ABORT_WITH(tt, code);
403 if (!AccessOK(tt, *cid, 0, PRP_STATUS_MEM, 0))
404 ABORT_WITH(tt, PRPERM);
406 /* Since prdebugentry is in the form of a prentry not a coentry, we will
407 * return the coentry slots in network order where the string is. */
409 if (aentry->flags & PRCONT) { /* wrong type, get coentry instead */
410 code = pr_ReadCoEntry(tt, 0, apos, aentry);
412 ABORT_WITH(tt, code);
415 code = ubik_EndTrans(tt);
422 SPR_AddToGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid)
425 afs_int32 cid = ANONYMOUSID;
427 code = addToGroup(call, aid, gid, &cid);
428 osi_auditU(call, PTS_AdToGrpEvent, code, AUD_ID, gid, AUD_ID, aid,
430 ViceLog(5, ("PTS_AddToGroup: code %d cid %d gid %d aid %d\n", code, cid, gid, aid));
435 addToGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid, afs_int32 *cid)
438 struct ubik_trans *tt;
441 struct prentry tentry;
442 struct prentry uentry;
445 if (code != PRSUCCESS)
447 if (gid == ANYUSERID || gid == AUTHUSERID)
449 if (aid == ANONYMOUSID)
451 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
454 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
456 ABORT_WITH(tt, code);
457 code = read_DbHeader(tt);
459 ABORT_WITH(tt, code);
461 code = WhoIsThis(call, tt, cid);
463 ABORT_WITH(tt, PRPERM);
464 tempu = FindByID(tt, aid);
466 ABORT_WITH(tt, PRNOENT);
467 memset(&uentry, 0, sizeof(uentry));
468 code = pr_ReadEntry(tt, 0, tempu, &uentry);
470 ABORT_WITH(tt, code);
472 #if !defined(SUPERGROUPS)
473 /* we don't allow groups as members of groups at present */
474 if (uentry.flags & PRGRP)
475 ABORT_WITH(tt, PRNOTUSER);
478 tempg = FindByID(tt, gid);
480 ABORT_WITH(tt, PRNOENT);
481 code = pr_ReadEntry(tt, 0, tempg, &tentry);
483 ABORT_WITH(tt, code);
484 /* make sure that this is a group */
485 if (!(tentry.flags & PRGRP))
486 ABORT_WITH(tt, PRNOTGROUP);
487 if (!AccessOK(tt, *cid, &tentry, PRP_ADD_MEM, PRP_ADD_ANY))
488 ABORT_WITH(tt, PRPERM);
490 code = AddToEntry(tt, &tentry, tempg, aid);
491 if (code != PRSUCCESS)
492 ABORT_WITH(tt, code);
494 #if defined(SUPERGROUPS)
495 if (uentry.flags & PRGRP)
496 code = AddToSGEntry(tt, &uentry, tempu, gid); /* mod group to be in sg */
499 /* now, modify the user's entry as well */
500 code = AddToEntry(tt, &uentry, tempu, gid);
501 if (code != PRSUCCESS)
502 ABORT_WITH(tt, code);
503 code = ubik_EndTrans(tt);
510 SPR_NameToID(struct rx_call *call, namelist *aname, idlist *aid)
514 code = nameToID(call, aname, aid);
515 osi_auditU(call, PTS_NmToIdEvent, code, AUD_END);
516 ViceLog(125, ("PTS_NameToID: code %d\n", code));
521 nameToID(struct rx_call *call, namelist *aname, idlist *aid)
524 struct ubik_trans *tt;
529 /* Initialize return struct */
531 aid->idlist_val = NULL;
533 size = aname->namelist_len;
539 aid->idlist_val = (afs_int32 *) malloc(size * sizeof(afs_int32));
540 if (!aid->idlist_val)
544 if (code != PRSUCCESS)
546 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
549 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
551 ABORT_WITH(tt, code);
552 code = read_DbHeader(tt);
554 ABORT_WITH(tt, code);
556 for (i = 0; i < aname->namelist_len; i++) {
558 char *nameinst, *cell;
560 strncpy(vname, aname->namelist_val[i], sizeof(vname));
561 vname[sizeof(vname)-1] ='\0';
564 cell = strchr(vname, '@');
570 if (cell && afs_is_foreign_ticket_name(nameinst,NULL,cell,pr_realmName))
571 code = NameToID(tt, aname->namelist_val[i], &aid->idlist_val[i]);
573 code = NameToID(tt, nameinst, &aid->idlist_val[i]);
575 if (code != PRSUCCESS)
576 aid->idlist_val[i] = ANONYMOUSID;
577 osi_audit(PTS_NmToIdEvent, code, AUD_STR,
578 aname->namelist_val[i], AUD_ID, aid->idlist_val[i],
580 ViceLog(125, ("PTS_NameToID: code %d aname %s aid %d\n", code,
581 aname->namelist_val[i], aid->idlist_val[i]));
583 #ifndef AFS_PTHREAD_ENV
589 aid->idlist_len = aname->namelist_len;
591 code = ubik_EndTrans(tt);
599 * Given an array of ids, find the name for each of them.
600 * The array of ids and names is unlimited.
603 SPR_IDToName(struct rx_call *call, idlist *aid, namelist *aname)
607 code = idToName(call, aid, aname);
608 osi_auditU(call, PTS_IdToNmEvent, code, AUD_END);
609 ViceLog(125, ("PTS_IDToName: code %d\n", code));
614 idToName(struct rx_call *call, idlist *aid, namelist *aname)
617 struct ubik_trans *tt;
622 /* leave this first for rpc stub */
623 size = aid->idlist_len;
628 aname->namelist_val = (prname *) malloc(size * PR_MAXNAMELEN);
629 aname->namelist_len = 0;
630 if (aname->namelist_val == 0)
632 if (aid->idlist_len == 0)
635 return PRTOOMANY; /* rxgen will probably handle this */
638 if (code != PRSUCCESS)
640 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
643 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
645 ABORT_WITH(tt, code);
646 code = read_DbHeader(tt);
648 ABORT_WITH(tt, code);
650 for (i = 0; i < aid->idlist_len; i++) {
651 code = IDToName(tt, aid->idlist_val[i], aname->namelist_val[i]);
652 if (code != PRSUCCESS)
653 sprintf(aname->namelist_val[i], "%d", aid->idlist_val[i]);
654 osi_audit(PTS_IdToNmEvent, code, AUD_ID, aid->idlist_val[i],
655 AUD_STR, aname->namelist_val[i], AUD_END);
656 ViceLog(125, ("PTS_idToName: code %d aid %d aname %s\n", code,
657 aid->idlist_val[i], aname->namelist_val[i]));
659 #ifndef AFS_PTHREAD_ENV
665 aname->namelist_len = aid->idlist_len;
667 code = ubik_EndTrans(tt);
674 SPR_Delete(struct rx_call *call, afs_int32 aid)
677 afs_int32 cid = ANONYMOUSID;
679 code = Delete(call, aid, &cid);
680 osi_auditU(call, PTS_DelEvent, code, AUD_ID, aid, AUD_END);
681 ViceLog(5, ("PTS_Delete: code %d cid %d aid %d\n", code, cid, aid));
686 Delete(struct rx_call *call, afs_int32 aid, afs_int32 *cid)
689 struct ubik_trans *tt;
690 struct prentry tentry;
697 if (code != PRSUCCESS)
699 if (aid == SYSADMINID || aid == ANYUSERID || aid == AUTHUSERID
700 || aid == ANONYMOUSID)
702 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
705 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
707 ABORT_WITH(tt, code);
708 code = read_DbHeader(tt);
710 ABORT_WITH(tt, code);
712 code = WhoIsThis(call, tt, cid);
714 ABORT_WITH(tt, PRPERM);
716 /* Read in entry to be deleted */
717 loc = FindByID(tt, aid);
719 ABORT_WITH(tt, PRNOENT);
720 code = pr_ReadEntry(tt, 0, loc, &tentry);
722 ABORT_WITH(tt, PRDBFAIL);
724 /* Do some access checking */
725 if (tentry.owner != *cid && !IsAMemberOf(tt, *cid, SYSADMINID)
726 && !IsAMemberOf(tt, *cid, tentry.owner) && !pr_noAuth)
727 ABORT_WITH(tt, PRPERM);
729 /* Delete each continuation block as a separate transaction so that no one
730 * transaction become to large to complete. */
733 struct contentry centry;
736 code = pr_ReadCoEntry(tt, 0, nptr, ¢ry);
738 ABORT_WITH(tt, PRDBFAIL);
739 for (i = 0; i < COSIZE; i++) {
740 if (centry.entries[i] == PRBADID)
742 if (centry.entries[i] == 0)
744 #if defined(SUPERGROUPS)
745 if (aid < 0 && centry.entries[i] < 0) /* Supergroup */
746 code = RemoveFromSGEntry(tt, aid, centry.entries[i]);
749 code = RemoveFromEntry(tt, aid, centry.entries[i]);
751 ABORT_WITH(tt, code);
752 tentry.count--; /* maintain count */
753 #ifndef AFS_PTHREAD_ENV
758 tentry.next = centry.next; /* thread out this block */
759 code = FreeBlock(tt, nptr); /* free continuation block */
761 ABORT_WITH(tt, code);
762 code = pr_WriteEntry(tt, 0, loc, &tentry); /* update main entry */
764 ABORT_WITH(tt, code);
766 /* end this trans and start a new one */
767 code = ubik_EndTrans(tt);
770 #ifndef AFS_PTHREAD_ENV
771 IOMGR_Poll(); /* just to keep the connection alive */
773 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
776 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
778 ABORT_WITH(tt, code);
780 /* re-read entry to get consistent uptodate info */
781 loc = FindByID(tt, aid);
783 ABORT_WITH(tt, PRNOENT);
784 code = pr_ReadEntry(tt, 0, loc, &tentry);
786 ABORT_WITH(tt, PRDBFAIL);
791 #if defined(SUPERGROUPS)
792 /* Delete each continuation block as a separate transaction
793 * so that no one transaction become too large to complete. */
795 struct prentryg *tentryg = (struct prentryg *)&tentry;
796 nptr = tentryg->nextsg;
798 struct contentry centry;
801 code = pr_ReadCoEntry(tt, 0, nptr, ¢ry);
803 ABORT_WITH(tt, PRDBFAIL);
804 for (i = 0; i < COSIZE; i++) {
805 if (centry.entries[i] == PRBADID)
807 if (centry.entries[i] == 0)
809 code = RemoveFromEntry(tt, aid, centry.entries[i]);
811 ABORT_WITH(tt, code);
812 tentryg->countsg--; /* maintain count */
813 #ifndef AFS_PTHREAD_ENV
818 tentryg->nextsg = centry.next; /* thread out this block */
819 code = FreeBlock(tt, nptr); /* free continuation block */
821 ABORT_WITH(tt, code);
822 code = pr_WriteEntry(tt, 0, loc, &tentry); /* update main entry */
824 ABORT_WITH(tt, code);
826 /* end this trans and start a new one */
827 code = ubik_EndTrans(tt);
830 #ifndef AFS_PTHREAD_ENV
831 IOMGR_Poll(); /* just to keep the connection alive */
834 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
837 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
839 ABORT_WITH(tt, code);
841 /* re-read entry to get consistent uptodate info */
842 loc = FindByID(tt, aid);
844 ABORT_WITH(tt, PRNOENT);
845 code = pr_ReadEntry(tt, 0, loc, &tentry);
847 ABORT_WITH(tt, PRDBFAIL);
849 nptr = tentryg->nextsg;
853 #endif /* SUPERGROUPS */
855 /* Then move the owned chain, except possibly ourself to the orphan list.
856 * Because this list can be very long and so exceed the size of a ubik
857 * transaction, we start a new transaction every 50 entries. */
861 struct prentry nentry;
863 code = pr_ReadEntry(tt, 0, nptr, &nentry);
865 ABORT_WITH(tt, PRDBFAIL);
866 nptr = tentry.owned = nentry.nextOwned; /* thread out */
868 if (nentry.id != tentry.id) { /* don't add us to orphan chain! */
869 code = AddToOrphan(tt, nentry.id);
871 ABORT_WITH(tt, code);
873 #ifndef AFS_PTHREAD_ENV
874 if ((count & 3) == 0)
880 code = pr_WriteEntry(tt, 0, loc, &tentry); /* update main entry */
882 ABORT_WITH(tt, code);
884 /* end this trans and start a new one */
885 code = ubik_EndTrans(tt);
888 #ifndef AFS_PTHREAD_ENV
889 IOMGR_Poll(); /* just to keep the connection alive */
891 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
894 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
896 ABORT_WITH(tt, code);
898 /* re-read entry to get consistent uptodate info */
899 loc = FindByID(tt, aid);
901 ABORT_WITH(tt, PRNOENT);
902 code = pr_ReadEntry(tt, 0, loc, &tentry);
904 ABORT_WITH(tt, PRDBFAIL);
909 /* now do what's left of the deletion stuff */
910 code = DeleteEntry(tt, &tentry, loc);
911 if (code != PRSUCCESS)
912 ABORT_WITH(tt, code);
914 code = ubik_EndTrans(tt);
921 SPR_UpdateEntry(struct rx_call *call, afs_int32 aid, char *name,
922 struct PrUpdateEntry *uentry)
925 afs_int32 cid = ANONYMOUSID;
927 code = UpdateEntry(call, aid, name, uentry, &cid);
928 osi_auditU(call, PTS_UpdEntEvent, code, AUD_ID, aid, AUD_STR, name, AUD_END);
929 ViceLog(5, ("PTS_UpdateEntry: code %d cid %d aid %d name %s\n", code, cid, aid, name));
934 UpdateEntry(struct rx_call *call, afs_int32 aid, char *name,
935 struct PrUpdateEntry *uentry, afs_int32 *cid)
938 struct ubik_trans *tt;
939 struct prentry tentry;
946 if (code != PRSUCCESS)
950 if (aid == SYSADMINID || aid == ANYUSERID || aid == AUTHUSERID
951 || aid == ANONYMOUSID)
954 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
957 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
959 ABORT_WITH(tt, code);
960 code = read_DbHeader(tt);
962 ABORT_WITH(tt, code);
964 code = WhoIsThis(call, tt, cid);
966 ABORT_WITH(tt, PRPERM);
967 code = IsAMemberOf(tt, *cid, SYSADMINID);
968 if (!code && !pr_noAuth)
969 ABORT_WITH(tt, PRPERM);
971 /* Read in entry to be deleted */
973 loc = FindByID(tt, aid);
975 loc = FindByName(tt, name, &tentry);
978 ABORT_WITH(tt, PRNOENT);
979 code = pr_ReadEntry(tt, 0, loc, &tentry);
981 ABORT_WITH(tt, PRDBFAIL);
983 if (uentry->Mask & PRUPDATE_NAMEHASH) {
985 code = RemoveFromNameHash(tt, tentry.name, &tloc);
986 if (code != PRSUCCESS)
987 ABORT_WITH(tt, PRDBFAIL);
988 code = AddToNameHash(tt, tentry.name, loc);
990 ABORT_WITH(tt, code);
993 if (uentry->Mask & PRUPDATE_IDHASH) {
997 code = RemoveFromIDHash(tt, id, &tloc);
998 if (code != PRSUCCESS)
999 ABORT_WITH(tt, PRDBFAIL);
1000 code = AddToIDHash(tt, id, loc);
1002 ABORT_WITH(tt, code);
1005 code = ubik_EndTrans(tt);
1012 SPR_RemoveFromGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid)
1015 afs_int32 cid = ANONYMOUSID;
1017 code = removeFromGroup(call, aid, gid, &cid);
1018 osi_auditU(call, PTS_RmFmGrpEvent, code, AUD_ID, gid, AUD_ID, aid,
1020 ViceLog(5, ("PTS_RemoveFromGroup: code %d cid %d gid %d aid %d\n", code, cid, gid, aid));
1025 removeFromGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid,
1029 struct ubik_trans *tt;
1032 struct prentry uentry;
1033 struct prentry gentry;
1036 if (code != PRSUCCESS)
1038 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1041 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1043 ABORT_WITH(tt, code);
1044 code = read_DbHeader(tt);
1046 ABORT_WITH(tt, code);
1048 code = WhoIsThis(call, tt, cid);
1050 ABORT_WITH(tt, PRPERM);
1051 tempu = FindByID(tt, aid);
1053 ABORT_WITH(tt, PRNOENT);
1054 tempg = FindByID(tt, gid);
1056 ABORT_WITH(tt, PRNOENT);
1057 memset(&uentry, 0, sizeof(uentry));
1058 memset(&gentry, 0, sizeof(gentry));
1059 code = pr_ReadEntry(tt, 0, tempu, &uentry);
1061 ABORT_WITH(tt, code);
1062 code = pr_ReadEntry(tt, 0, tempg, &gentry);
1064 ABORT_WITH(tt, code);
1065 if (!(gentry.flags & PRGRP))
1066 ABORT_WITH(tt, PRNOTGROUP);
1067 #if !defined(SUPERGROUPS)
1068 if (uentry.flags & PRGRP)
1069 ABORT_WITH(tt, PRNOTUSER);
1071 if (!AccessOK(tt, *cid, &gentry, PRP_REMOVE_MEM, 0))
1072 ABORT_WITH(tt, PRPERM);
1073 code = RemoveFromEntry(tt, aid, gid);
1074 if (code != PRSUCCESS)
1075 ABORT_WITH(tt, code);
1076 #if defined(SUPERGROUPS)
1077 if (!(uentry.flags & PRGRP))
1079 code = RemoveFromEntry(tt, gid, aid);
1080 #if defined(SUPERGROUPS)
1082 code = RemoveFromSGEntry(tt, gid, aid);
1084 if (code != PRSUCCESS)
1085 ABORT_WITH(tt, code);
1087 code = ubik_EndTrans(tt);
1095 SPR_GetCPS(struct rx_call *call, afs_int32 aid, prlist *alist, afs_int32 *over)
1098 afs_int32 cid = ANONYMOUSID;
1100 code = getCPS(call, aid, alist, over, &cid);
1101 osi_auditU(call, PTS_GetCPSEvent, code, AUD_ID, aid, AUD_END);
1102 ViceLog(125, ("PTS_GetCPS: code %d cid %d aid %d\n", code, cid, aid));
1107 getCPS(struct rx_call *call, afs_int32 aid, prlist *alist, afs_int32 *over,
1111 struct ubik_trans *tt;
1113 struct prentry tentry;
1116 alist->prlist_len = 0;
1117 alist->prlist_val = NULL;
1119 if (code != PRSUCCESS)
1121 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1124 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1126 ABORT_WITH(tt, code);
1127 code = read_DbHeader(tt);
1129 ABORT_WITH(tt, code);
1131 temp = FindByID(tt, aid);
1133 ABORT_WITH(tt, PRNOENT);
1134 code = pr_ReadEntry(tt, 0, temp, &tentry);
1136 ABORT_WITH(tt, code);
1138 /* afs does authenticate now */
1139 code = WhoIsThis(call, tt, cid);
1140 if (code || !AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1141 ABORT_WITH(tt, PRPERM);
1143 code = GetList(tt, &tentry, alist, 1);
1144 if (code != PRSUCCESS)
1145 ABORT_WITH(tt, code);
1147 code = ubik_EndTrans(tt);
1153 inCPS(prlist CPS, afs_int32 id)
1157 for (i = (CPS.prlist_len - 1); i >= 0; i--) {
1158 if (CPS.prlist_val[i] == id)
1166 SPR_GetCPS2(struct rx_call *call, afs_int32 aid, afs_int32 ahost,
1167 prlist *alist, afs_int32 *over)
1170 afs_int32 cid = ANONYMOUSID;
1172 code = getCPS2(call, aid, ahost, alist, over, &cid);
1173 osi_auditU(call, PTS_GetCPS2Event, code, AUD_ID, aid, AUD_HOST, htonl(ahost),
1175 ViceLog(125, ("PTS_GetCPS2: code %d cid %d aid %d ahost %d\n", code, cid, aid, ahost));
1180 getCPS2(struct rx_call *call, afs_int32 aid, afs_uint32 ahost, prlist *alist,
1181 afs_int32 *over, afs_int32 *cid)
1184 struct ubik_trans *tt;
1186 struct prentry tentry;
1187 struct prentry host_tentry;
1190 struct in_addr iaddr;
1193 iaddr.s_addr = ntohl(ahost);
1194 alist->prlist_len = 0;
1195 alist->prlist_val = NULL;
1197 if (code != PRSUCCESS)
1199 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1202 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1204 ABORT_WITH(tt, code);
1205 code = read_DbHeader(tt);
1207 ABORT_WITH(tt, code);
1209 if (aid != PRBADID) {
1210 temp = FindByID(tt, aid);
1212 ABORT_WITH(tt, PRNOENT);
1213 code = pr_ReadEntry(tt, 0, temp, &tentry);
1215 ABORT_WITH(tt, code);
1217 /* afs does authenticate now */
1218 code = WhoIsThis(call, tt, cid);
1220 || !AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1221 ABORT_WITH(tt, PRPERM);
1223 code = NameToID(tt, inet_ntoa(iaddr), &hostid);
1224 if (code == PRSUCCESS && hostid != 0) {
1225 temp = FindByID(tt, hostid);
1227 code = pr_ReadEntry(tt, 0, temp, &host_tentry);
1228 if (code == PRSUCCESS)
1231 fprintf(stderr, "pr_ReadEntry returned %d\n", code);
1233 fprintf(stderr, "FindByID Failed -- Not found\n");
1236 code = GetList2(tt, &tentry, &host_tentry, alist, 1);
1238 code = GetList(tt, &tentry, alist, 1);
1240 code = addWildCards(tt, alist, ntohl(ahost));
1241 if (code != PRSUCCESS)
1242 ABORT_WITH(tt, code);
1244 code = ubik_EndTrans(tt);
1250 SPR_GetHostCPS(struct rx_call *call, afs_int32 ahost, prlist *alist,
1255 code = getHostCPS(call, ahost, alist, over);
1256 osi_auditU(call, PTS_GetHCPSEvent, code, AUD_HOST, htonl(ahost), AUD_END);
1257 ViceLog(125, ("PTS_GetHostCPS: code %d ahost %d\n", code, ahost));
1262 getHostCPS(struct rx_call *call, afs_uint32 ahost, prlist *alist,
1265 afs_int32 code, temp;
1266 struct ubik_trans *tt;
1267 struct prentry host_tentry;
1269 struct in_addr iaddr;
1272 iaddr.s_addr = ntohl(ahost);
1273 alist->prlist_len = 0;
1274 alist->prlist_val = NULL;
1276 if (code != PRSUCCESS)
1278 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1281 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1283 ABORT_WITH(tt, code);
1284 code = read_DbHeader(tt);
1286 ABORT_WITH(tt, code);
1288 code = NameToID(tt, inet_ntoa(iaddr), &hostid);
1289 if (code == PRSUCCESS && hostid != 0) {
1290 temp = FindByID(tt, hostid);
1292 code = pr_ReadEntry(tt, 0, temp, &host_tentry);
1293 if (code == PRSUCCESS) {
1294 code = GetList(tt, &host_tentry, alist, 0);
1298 fprintf(stderr, "pr_ReadEntry returned %d\n", code);
1300 fprintf(stderr, "FindByID Failed -- Not found\n");
1302 code = addWildCards(tt, alist, ntohl(ahost));
1304 if (code != PRSUCCESS)
1305 ABORT_WITH(tt, code);
1307 code = ubik_EndTrans(tt);
1313 SPR_ListMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid)
1317 code = listMax(call, uid, gid);
1318 osi_auditU(call, PTS_LstMaxEvent, code, AUD_END);
1319 ViceLog(125, ("PTS_ListMax: code %d\n", code));
1324 listMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid)
1327 struct ubik_trans *tt;
1330 if (code != PRSUCCESS)
1332 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1335 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1337 ABORT_WITH(tt, code);
1338 code = read_DbHeader(tt);
1340 ABORT_WITH(tt, code);
1342 code = GetMax(tt, uid, gid);
1343 if (code != PRSUCCESS)
1344 ABORT_WITH(tt, code);
1346 code = ubik_EndTrans(tt);
1353 SPR_SetMax(struct rx_call *call, afs_int32 aid, afs_int32 gflag)
1356 afs_int32 cid = ANONYMOUSID;
1358 code = setMax(call, aid, gflag, &cid);
1359 osi_auditU(call, PTS_SetMaxEvent, code, AUD_ID, aid, AUD_LONG, gflag,
1361 ViceLog(125, ("PTS_SetMax: code %d cid %d aid %d gflag %d\n", code, cid, aid, gflag));
1366 setMax(struct rx_call *call, afs_int32 aid, afs_int32 gflag, afs_int32 *cid)
1369 struct ubik_trans *tt;
1372 if (code != PRSUCCESS)
1374 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1377 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1379 ABORT_WITH(tt, code);
1380 code = read_DbHeader(tt);
1382 ABORT_WITH(tt, code);
1384 code = WhoIsThis(call, tt, cid);
1386 ABORT_WITH(tt, PRPERM);
1387 if (!AccessOK(tt, *cid, 0, 0, 0))
1388 ABORT_WITH(tt, PRPERM);
1389 if (((gflag & PRGRP) && (aid > 0)) || (!(gflag & PRGRP) && (aid < 0)))
1390 ABORT_WITH(tt, PRBADARG);
1392 code = SetMax(tt, aid, gflag);
1393 if (code != PRSUCCESS)
1394 ABORT_WITH(tt, code);
1396 code = ubik_EndTrans(tt);
1403 SPR_ListEntry(struct rx_call *call, afs_int32 aid, struct prcheckentry *aentry)
1406 afs_int32 cid = ANONYMOUSID;
1408 code = listEntry(call, aid, aentry, &cid);
1409 osi_auditU(call, PTS_LstEntEvent, code, AUD_ID, aid, AUD_END);
1410 ViceLog(125, ("PTS_ListEntry: code %d cid %d aid %d\n", code, cid, aid));
1415 listEntry(struct rx_call *call, afs_int32 aid, struct prcheckentry *aentry,
1419 struct ubik_trans *tt;
1421 struct prentry tentry;
1424 if (code != PRSUCCESS)
1426 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1429 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1431 ABORT_WITH(tt, code);
1432 code = read_DbHeader(tt);
1434 ABORT_WITH(tt, code);
1436 code = WhoIsThis(call, tt, cid);
1438 ABORT_WITH(tt, PRPERM);
1439 temp = FindByID(tt, aid);
1441 ABORT_WITH(tt, PRNOENT);
1442 code = pr_ReadEntry(tt, 0, temp, &tentry);
1444 ABORT_WITH(tt, code);
1445 if (!AccessOK(tt, *cid, &tentry, PRP_STATUS_MEM, PRP_STATUS_ANY))
1446 ABORT_WITH(tt, PRPERM);
1448 aentry->flags = tentry.flags >> PRIVATE_SHIFT;
1449 if (aentry->flags == 0) {
1450 if (tentry.flags & PRGRP)
1451 aentry->flags = prp_group_default >> PRIVATE_SHIFT;
1453 aentry->flags = prp_user_default >> PRIVATE_SHIFT;
1455 aentry->owner = tentry.owner;
1456 aentry->id = tentry.id;
1457 strncpy(aentry->name, tentry.name, PR_MAXNAMELEN);
1458 aentry->creator = tentry.creator;
1459 aentry->ngroups = tentry.ngroups;
1460 aentry->nusers = tentry.nusers;
1461 aentry->count = tentry.count;
1462 memset(aentry->reserved, 0, sizeof(aentry->reserved));
1463 code = ubik_EndTrans(tt);
1470 SPR_ListEntries(struct rx_call *call, afs_int32 flag, afs_int32 startindex,
1471 prentries *bulkentries, afs_int32 *nextstartindex)
1474 afs_int32 cid = ANONYMOUSID;
1476 code = listEntries(call, flag, startindex, bulkentries, nextstartindex, &cid);
1477 osi_auditU(call, PTS_LstEntsEvent, code, AUD_LONG, flag, AUD_END);
1478 ViceLog(125, ("PTS_ListEntries: code %d cid %d flag %d\n", code, cid, flag));
1483 listEntries(struct rx_call *call, afs_int32 flag, afs_int32 startindex,
1484 prentries *bulkentries, afs_int32 *nextstartindex, afs_int32 *cid)
1487 struct ubik_trans *tt;
1488 afs_int32 i, eof, pos, maxentries, f;
1489 struct prentry tentry;
1490 afs_int32 pollcount = 0;
1492 *nextstartindex = -1;
1493 bulkentries->prentries_val = 0;
1494 bulkentries->prentries_len = 0;
1497 if (code != PRSUCCESS)
1499 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1502 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1504 ABORT_WITH(tt, code);
1505 code = read_DbHeader(tt);
1507 ABORT_WITH(tt, code);
1509 /* Make sure we are an authenticated caller and that we are on the
1512 code = WhoIsThis(call, tt, cid);
1514 ABORT_WITH(tt, PRPERM);
1515 code = IsAMemberOf(tt, *cid, SYSADMINID);
1516 if (!code && !pr_noAuth)
1517 ABORT_WITH(tt, PRPERM);
1519 eof = ntohl(cheader.eofPtr) - sizeof(cheader);
1520 maxentries = eof / sizeof(struct prentry);
1521 for (i = startindex; i < maxentries; i++) {
1522 pos = i * sizeof(struct prentry) + sizeof(cheader);
1523 code = pr_ReadEntry(tt, 0, pos, &tentry);
1527 if (++pollcount > 50) {
1528 #ifndef AFS_PTHREAD_ENV
1534 f = (tentry.flags & PRTYPE);
1535 if (((flag & PRUSERS) && (f == 0)) || /* User entry */
1536 ((flag & PRGROUPS) && (f & PRGRP))) { /* Group entry */
1537 code = put_prentries(&tentry, bulkentries);
1539 break; /* Filled return array */
1546 *nextstartindex = i;
1550 if (bulkentries->prentries_val)
1551 free(bulkentries->prentries_val);
1552 bulkentries->prentries_val = 0;
1553 bulkentries->prentries_len = 0;
1554 ABORT_WITH(tt, code);
1556 code = ubik_EndTrans(tt);
1563 #define PR_MAXENTRIES 500
1565 put_prentries(struct prentry *tentry, prentries *bulkentries)
1567 struct prlistentries *entry;
1569 if (bulkentries->prentries_val == 0) {
1570 bulkentries->prentries_len = 0;
1571 bulkentries->prentries_val =
1572 (struct prlistentries *)malloc(PR_MAXENTRIES *
1573 sizeof(struct prentry));
1574 if (!bulkentries->prentries_val) {
1579 if (bulkentries->prentries_len >= PR_MAXENTRIES) {
1583 entry = (struct prlistentries *)bulkentries->prentries_val;
1584 entry += bulkentries->prentries_len;
1586 entry->flags = tentry->flags >> PRIVATE_SHIFT;
1587 if (entry->flags == 0) {
1590 flags & PRGRP) ? prp_group_default : prp_user_default) >>
1593 entry->owner = tentry->owner;
1594 entry->id = tentry->id;
1595 entry->creator = tentry->creator;
1596 entry->ngroups = tentry->ngroups;
1597 entry->nusers = tentry->nusers;
1598 entry->count = tentry->count;
1599 strncpy(entry->name, tentry->name, PR_MAXNAMELEN);
1600 memset(entry->reserved, 0, sizeof(entry->reserved));
1601 bulkentries->prentries_len++;
1606 SPR_ChangeEntry(struct rx_call *call, afs_int32 aid, char *name, afs_int32 oid,
1610 afs_int32 cid = ANONYMOUSID;
1612 code = changeEntry(call, aid, name, oid, newid, &cid);
1613 osi_auditU(call, PTS_ChgEntEvent, code, AUD_ID, aid, AUD_STR, name,
1614 AUD_LONG, oid, AUD_LONG, newid, AUD_END);
1615 ViceLog(5, ("PTS_ChangeEntry: code %d cid %d aid %d name %s oid %d newid %d\n", code, cid, aid, name, oid, newid));
1620 changeEntry(struct rx_call *call, afs_int32 aid, char *name, afs_int32 oid,
1621 afs_int32 newid, afs_int32 *cid)
1624 struct ubik_trans *tt;
1634 if (aid == ANYUSERID || aid == AUTHUSERID || aid == ANONYMOUSID
1635 || aid == SYSADMINID)
1637 if (code != PRSUCCESS)
1639 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1642 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1644 ABORT_WITH(tt, code);
1645 code = read_DbHeader(tt);
1647 ABORT_WITH(tt, code);
1649 code = WhoIsThis(call, tt, cid);
1651 ABORT_WITH(tt, PRPERM);
1652 pos = FindByID(tt, aid);
1654 ABORT_WITH(tt, PRNOENT);
1655 /* protection check in changeentry */
1656 code = ChangeEntry(tt, aid, *cid, name, oid, newid);
1657 if (code != PRSUCCESS)
1658 ABORT_WITH(tt, code);
1660 code = ubik_EndTrans(tt);
1665 SPR_SetFieldsEntry(struct rx_call *call,
1667 afs_int32 mask, /* specify which fields to update */
1668 afs_int32 flags, afs_int32 ngroups, afs_int32 nusers,
1669 afs_int32 spare1, afs_int32 spare2)
1672 afs_int32 cid = ANONYMOUSID;
1675 setFieldsEntry(call, id, mask, flags, ngroups, nusers, spare1,
1677 osi_auditU(call, PTS_SetFldEntEvent, code, AUD_ID, id, AUD_END);
1678 ViceLog(5, ("PTS_SetFieldsEntry: code %d cid %d id %d\n", code, cid, id));
1683 setFieldsEntry(struct rx_call *call,
1685 afs_int32 mask, /* specify which fields to update */
1686 afs_int32 flags, afs_int32 ngroups, afs_int32 nusers,
1687 afs_int32 spare1, afs_int32 spare2, afs_int32 *cid)
1690 struct ubik_trans *tt;
1692 struct prentry tentry;
1696 return 0; /* no-op */
1700 if (id == ANYUSERID || id == AUTHUSERID || id == ANONYMOUSID)
1702 if (code != PRSUCCESS)
1704 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1707 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1709 ABORT_WITH(tt, code);
1710 code = read_DbHeader(tt);
1712 ABORT_WITH(tt, code);
1714 code = WhoIsThis(call, tt, cid);
1716 ABORT_WITH(tt, PRPERM);
1717 pos = FindByID(tt, id);
1719 ABORT_WITH(tt, PRNOENT);
1720 code = pr_ReadEntry(tt, 0, pos, &tentry);
1722 ABORT_WITH(tt, code);
1723 tflags = tentry.flags;
1725 if (mask & (PR_SF_NGROUPS | PR_SF_NUSERS)) {
1726 if (!AccessOK(tt, *cid, 0, 0, 0))
1727 ABORT_WITH(tt, PRPERM);
1728 if ((tflags & PRQUOTA) == 0) { /* default if only setting one */
1729 tentry.ngroups = tentry.nusers = 20;
1732 if (!AccessOK(tt, *cid, &tentry, 0, 0))
1733 ABORT_WITH(tt, PRPERM);
1736 if (mask & 0xffff) { /* if setting flag bits */
1737 afs_int32 flagsMask = mask & 0xffff;
1738 tflags &= ~(flagsMask << PRIVATE_SHIFT);
1739 tflags |= (flags & flagsMask) << PRIVATE_SHIFT;
1743 if (mask & PR_SF_NGROUPS) { /* setting group limit */
1745 ABORT_WITH(tt, PRBADARG);
1746 tentry.ngroups = ngroups;
1750 if (mask & PR_SF_NUSERS) { /* setting foreign user limit */
1752 ABORT_WITH(tt, PRBADARG);
1753 tentry.nusers = nusers;
1756 tentry.flags = tflags;
1758 code = pr_WriteEntry(tt, 0, pos, &tentry);
1760 ABORT_WITH(tt, code);
1762 code = ubik_EndTrans(tt);
1767 SPR_ListElements(struct rx_call *call, afs_int32 aid, prlist *alist,
1771 afs_int32 cid = ANONYMOUSID;
1773 code = listElements(call, aid, alist, over, &cid);
1774 osi_auditU(call, PTS_LstEleEvent, code, AUD_ID, aid, AUD_END);
1775 ViceLog(125, ("PTS_ListElements: code %d cid %d aid %d\n", code, cid, aid));
1780 listElements(struct rx_call *call, afs_int32 aid, prlist *alist,
1781 afs_int32 *over, afs_int32 *cid)
1784 struct ubik_trans *tt;
1786 struct prentry tentry;
1789 alist->prlist_len = 0;
1790 alist->prlist_val = NULL;
1793 if (code != PRSUCCESS)
1795 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1798 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1800 ABORT_WITH(tt, code);
1801 code = read_DbHeader(tt);
1803 ABORT_WITH(tt, code);
1805 code = WhoIsThis(call, tt, cid);
1807 ABORT_WITH(tt, PRPERM);
1809 temp = FindByID(tt, aid);
1811 ABORT_WITH(tt, PRNOENT);
1812 code = pr_ReadEntry(tt, 0, temp, &tentry);
1814 ABORT_WITH(tt, code);
1815 if (!AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1816 ABORT_WITH(tt, PRPERM);
1818 code = GetList(tt, &tentry, alist, 0);
1819 if (code != PRSUCCESS)
1820 ABORT_WITH(tt, code);
1822 code = ubik_EndTrans(tt);
1828 SPR_ListSuperGroups(struct rx_call *call, afs_int32 aid, prlist *alist,
1831 #if defined(SUPERGROUPS)
1833 afs_int32 cid = ANONYMOUSID;
1835 code = listSuperGroups(call, aid, alist, over, &cid);
1836 osi_auditU(call, PTS_LstSGrps, code, AUD_ID, aid, AUD_END);
1837 ViceLog(125, ("PTS_ListSuperGroups: code %d cid %d aid %d\n", code, cid, aid));
1840 return RXGEN_OPCODE;
1844 #if defined(SUPERGROUPS)
1846 listSuperGroups(struct rx_call *call, afs_int32 aid, prlist *alist,
1847 afs_int32 *over, afs_int32 *cid)
1850 struct ubik_trans *tt;
1852 struct prentry tentry;
1854 alist->prlist_len = 0;
1855 alist->prlist_val = (afs_int32 *) 0;
1858 if (code != PRSUCCESS)
1860 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1863 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1865 ABORT_WITH(tt, code);
1866 code = WhoIsThis(call, tt, cid);
1868 ABORT_WITH(tt, PRPERM);
1870 temp = FindByID(tt, aid);
1872 ABORT_WITH(tt, PRNOENT);
1873 code = pr_ReadEntry(tt, 0, temp, &tentry);
1875 ABORT_WITH(tt, code);
1876 if (!AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1877 ABORT_WITH(tt, PRPERM);
1879 code = GetSGList(tt, &tentry, alist);
1881 if (code == PRTOOMANY)
1883 else if (code != PRSUCCESS)
1884 ABORT_WITH(tt, code);
1886 code = ubik_EndTrans(tt);
1892 #endif /* SUPERGROUPS */
1896 * List the entries owned by this id. If the id is zero,
1897 * return the orphans list. This will return up to PR_MAXGROUPS
1898 * at a time with the lastP available to get the rest. The
1899 * maximum value is enforced in GetOwnedChain().
1902 SPR_ListOwned(struct rx_call *call, afs_int32 aid, prlist *alist,
1906 afs_int32 cid = ANONYMOUSID;
1908 code = listOwned(call, aid, alist, lastP, &cid);
1909 osi_auditU(call, PTS_LstOwnEvent, code, AUD_ID, aid, AUD_END);
1910 ViceLog(125, ("PTS_ListOwned: code %d cid %d aid %d\n", code, cid, aid));
1915 listOwned(struct rx_call *call, afs_int32 aid, prlist *alist, afs_int32 *lastP,
1919 struct ubik_trans *tt;
1920 struct prentry tentry;
1924 alist->prlist_len = 0;
1925 alist->prlist_val = NULL;
1933 if (code != PRSUCCESS)
1935 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1938 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1940 ABORT_WITH(tt, code);
1941 code = read_DbHeader(tt);
1943 ABORT_WITH(tt, code);
1945 code = WhoIsThis(call, tt, cid);
1947 ABORT_WITH(tt, PRPERM);
1950 code = pr_ReadEntry(tt, 0, start, &tentry);
1951 if (!code && (tentry.owner == aid))
1952 head = start; /* pick up where we left off */
1957 afs_int32 loc = FindByID(tt, aid);
1959 ABORT_WITH(tt, PRNOENT);
1960 code = pr_ReadEntry(tt, 0, loc, &tentry);
1962 ABORT_WITH(tt, code);
1964 if (!AccessOK(tt, *cid, &tentry, -1, PRP_OWNED_ANY))
1965 ABORT_WITH(tt, PRPERM);
1966 head = tentry.owned;
1968 if (!AccessOK(tt, *cid, 0, 0, 0))
1969 ABORT_WITH(tt, PRPERM);
1970 head = ntohl(cheader.orphan);
1974 code = GetOwnedChain(tt, &head, alist);
1976 if (code == PRTOOMANY)
1979 ABORT_WITH(tt, code);
1982 code = ubik_EndTrans(tt);
1987 SPR_IsAMemberOf(struct rx_call *call, afs_int32 uid, afs_int32 gid,
1991 afs_int32 cid = ANONYMOUSID;
1993 code = isAMemberOf(call, uid, gid, flag, &cid);
1994 osi_auditU(call, PTS_IsMemOfEvent, code, AUD_LONG, uid, AUD_LONG, gid,
1996 ViceLog(125, ("PTS_IsAMemberOf: code %d cid %d uid %d gid %d\n", code, cid, uid, gid));
2001 isAMemberOf(struct rx_call *call, afs_int32 uid, afs_int32 gid, afs_int32 *flag,
2005 struct ubik_trans *tt;
2008 if (code != PRSUCCESS)
2010 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
2013 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
2015 ABORT_WITH(tt, code);
2016 code = read_DbHeader(tt);
2018 ABORT_WITH(tt, code);
2021 afs_int32 uloc = FindByID(tt, uid);
2022 afs_int32 gloc = FindByID(tt, gid);
2023 struct prentry uentry, gentry;
2026 ABORT_WITH(tt, PRNOENT);
2027 code = WhoIsThis(call, tt, cid);
2029 ABORT_WITH(tt, PRPERM);
2030 code = pr_ReadEntry(tt, 0, uloc, &uentry);
2032 ABORT_WITH(tt, code);
2033 code = pr_ReadEntry(tt, 0, gloc, &gentry);
2035 ABORT_WITH(tt, code);
2036 #if !defined(SUPERGROUPS)
2037 if ((uentry.flags & PRGRP) || !(gentry.flags & PRGRP))
2038 ABORT_WITH(tt, PRBADARG);
2040 if (!(gentry.flags & PRGRP))
2041 ABORT_WITH(tt, PRBADARG);
2043 if (!AccessOK(tt, *cid, &uentry, 0, PRP_MEMBER_ANY)
2044 && !AccessOK(tt, *cid, &gentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
2045 ABORT_WITH(tt, PRPERM);
2048 *flag = IsAMemberOf(tt, uid, gid);
2049 code = ubik_EndTrans(tt);
2054 addWildCards(struct ubik_trans *tt, prlist *alist, afs_uint32 host)
2057 struct prentry tentry;
2059 unsigned wild = htonl(0xffffff00);
2060 struct in_addr iaddr;
2062 int size = 0, i, code;
2065 while ((host = (host & wild))) {
2066 wild = htonl(ntohl(wild) << 8);
2067 iaddr.s_addr = host;
2068 code = NameToID(tt, inet_ntoa(iaddr), &hostid);
2069 if (code == PRSUCCESS && hostid != 0) {
2070 temp = FindByID(tt, hostid);
2072 code = pr_ReadEntry(tt, 0, temp, &tentry);
2073 if (code != PRSUCCESS)
2079 wlist.prlist_len = 0;
2080 wlist.prlist_val = NULL;
2082 code = GetList(tt, &tentry, &wlist, 0);
2085 added += wlist.prlist_len;
2086 for (i = 0; i < wlist.prlist_len; i++) {
2087 if (!inCPS(*alist, wlist.prlist_val[i]))
2088 if ((code = AddToPRList(alist, &size, wlist.prlist_val[i]))) {
2089 free(wlist.prlist_val);
2093 if (wlist.prlist_val)
2094 free(wlist.prlist_val);
2097 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
2102 WhoIsThisWithName(struct rx_call *acall, struct ubik_trans *at, afs_int32 *aid,
2106 /* aid is set to the identity of the caller, if known, else ANONYMOUSID */
2107 /* returns -1 and sets aid to ANONYMOUSID on any failure */
2108 struct rx_connection *tconn;
2110 char tcell[MAXKTCREALMLEN];
2111 char name[MAXKTCNAMELEN];
2112 char inst[MAXKTCNAMELEN];
2117 tconn = rx_ConnectionOf(acall);
2118 code = rx_SecurityClassOf(tconn);
2121 else if (code == 1) { /* vab class */
2122 goto done; /* no longer supported */
2123 } else if (code == 2) { /* kad class */
2124 if ((code = rxkad_GetServerInfo(acall->conn, NULL, NULL,
2125 name, inst, tcell, NULL)))
2129 foreign = afs_is_foreign_ticket_name(name, inst, tcell,
2132 strncpy(vname, name, sizeof(vname));
2133 if ((ilen = strlen(inst))) {
2134 if (strlen(vname) + 1 + ilen >= sizeof(vname))
2137 strcat(vname, inst);
2140 if (strlen(vname) + strlen(tcell) + 1 >= sizeof(vname))
2143 strcat(vname, tcell);
2144 lcstring(vname, vname, sizeof(vname));
2145 code = NameToID(at, vname, aid);
2147 strcpy(aname, vname);
2151 if (strcmp(AUTH_SUPERUSER, vname) == 0)
2152 *aid = SYSADMINID; /* special case for the fileserver */
2154 lcstring(vname, vname, sizeof(vname));
2155 code = NameToID(at, vname, aid);
2159 if (code && !pr_noAuth)