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>
60 #include <afs/afsutil.h>
65 #include <rx/rx_identity.h>
67 #include <afs/cellconfig.h>
71 #include "ptprototypes.h"
72 #include "afs/audit.h"
74 extern int restricted;
75 extern int restrict_anonymous;
76 extern struct ubik_dbase *dbase;
78 extern int prp_group_default;
79 extern int prp_user_default;
80 extern struct afsconf_dir *prdir;
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, afs_int32 *cid);
94 static afs_int32 lookup_name_from_id(struct ubik_trans *at, afs_int32 aid,
95 char aname[PR_MAXNAMELEN]);
96 static afs_int32 lookup_id_from_name(struct ubik_trans *at,
97 char aname[PR_MAXNAMELEN],
99 static afs_int32 Delete(struct rx_call *call, afs_int32 aid, afs_int32 *cid);
100 static afs_int32 UpdateEntry(struct rx_call *call, afs_int32 aid, char *name,
101 struct PrUpdateEntry *uentry, afs_int32 *cid);
102 static afs_int32 removeFromGroup(struct rx_call *call, afs_int32 aid,
103 afs_int32 gid, afs_int32 *cid);
104 static afs_int32 getCPS(struct rx_call *call, afs_int32 aid, prlist *alist,
105 afs_int32 *over, afs_int32 *cid);
106 static afs_int32 getCPS2(struct rx_call *call, afs_int32 aid, afs_uint32 ahost,
107 prlist *alist, afs_int32 *over, afs_int32 *cid);
108 static afs_int32 getHostCPS(struct rx_call *call, afs_uint32 ahost,
109 prlist *alist, afs_int32 *over, afs_int32 *cid);
110 static afs_int32 listMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid, afs_int32 *cid);
111 static afs_int32 setMax(struct rx_call *call, afs_int32 aid, afs_int32 gflag,
113 static afs_int32 listEntry(struct rx_call *call, afs_int32 aid,
114 struct prcheckentry *aentry, afs_int32 *cid);
115 static afs_int32 listEntries(struct rx_call *call, afs_int32 flag,
116 afs_int32 startindex, prentries *bulkentries,
117 afs_int32 *nextstartindex, afs_int32 *cid);
118 static void put_prentries(struct prentry *tentry, prentries *bulkentries);
119 static afs_int32 changeEntry(struct rx_call *call, afs_int32 aid, char *name,
120 afs_int32 oid, afs_int32 newid, afs_int32 *cid);
121 static afs_int32 setFieldsEntry(struct rx_call *call, afs_int32 id,
122 afs_int32 mask, afs_int32 flags,
123 afs_int32 ngroups, afs_int32 nusers,
124 afs_int32 spare1, afs_int32 spare2,
126 static afs_int32 listElements(struct rx_call *call, afs_int32 aid,
127 prlist *alist, afs_int32 *over, afs_int32 *cid);
128 #if defined(SUPERGROUPS)
129 static afs_int32 listSuperGroups(struct rx_call *call, afs_int32 aid,
130 prlist *alist, afs_int32 *over,
133 static afs_int32 listOwned(struct rx_call *call, afs_int32 aid, prlist *alist,
134 afs_int32 *lastP, afs_int32 *cid);
135 static afs_int32 isAMemberOf(struct rx_call *call, afs_int32 uid, afs_int32 gid,
136 afs_int32 *flag, afs_int32 *cid);
137 static afs_int32 addWildCards(struct ubik_trans *tt, prlist *alist,
139 static afs_int32 WhoIsThisWithName(struct rx_call *acall,
140 struct ubik_trans *at, afs_int32 *aid,
143 /* when we abort, the ubik cachedVersion will be reset, so we'll read in the
144 * header on the next call.
145 * Abort the transaction and return the code.
147 #define ABORT_WITH(tt,code) return(ubik_AbortTrans(tt),code)
150 CreateOK(struct ubik_trans *ut, afs_int32 cid, afs_int32 oid, afs_int32 flag,
153 if (restricted && !admin)
156 if (flag & PRFOREIGN) {
157 /* Foreign users are recognized by the '@' sign and
158 * not by the PRFOREIGN flag.
161 } else if (flag & PRGRP) {
162 /* Allow anonymous group creation only if owner specified
163 * and running noAuth.
165 if (cid == ANONYMOUSID) {
166 if ((oid == 0) || !pr_noAuth)
169 } else { /* creating a user */
170 if (oid == ANONYMOUSID)
172 if (!admin && !pr_noAuth)
179 WhoIsThis(struct rx_call *acall, struct ubik_trans *at, afs_int32 *aid)
181 int code = WhoIsThisWithName(acall, at, aid, NULL);
182 if (code == 2 && *aid == ANONYMOUSID)
188 WritePreamble(struct ubik_trans **tt)
196 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, tt);
200 code = ubik_SetLock(*tt, 1, 1, LOCKWRITE);
204 code = read_DbHeader(*tt);
208 ubik_AbortTrans(*tt);
214 ReadPreamble(struct ubik_trans **tt)
222 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, tt);
226 code = ubik_SetLock(*tt, 1, 1, LOCKREAD);
230 code = read_DbHeader(*tt);
234 ubik_AbortTrans(*tt);
240 SPR_INewEntry(struct rx_call *call, char aname[], afs_int32 aid, afs_int32 oid)
243 afs_int32 cid = ANONYMOUSID;
245 code = iNewEntry(call, aname, aid, oid, &cid);
246 osi_auditU(call, PTS_INewEntEvent, code, AUD_ID, aid, AUD_STR, aname,
247 AUD_ID, oid, AUD_END);
248 ViceLog(5, ("PTS_INewEntry: code %d cid %d aid %d aname %s oid %d\n", code, cid, aid, aname, oid));
253 iNewEntry(struct rx_call *call, char aname[], afs_int32 aid, afs_int32 oid,
256 /* used primarily for conversion - not intended to be used as usual means
257 * of entering people into the database. */
258 struct ubik_trans *tt;
265 code = WritePreamble(&tt);
269 code = WhoIsThis(call, tt, cid);
271 ABORT_WITH(tt, PRPERM);
272 admin = IsAMemberOf(tt, *cid, SYSADMINID);
274 /* first verify the id is good */
276 ABORT_WITH(tt, PRPERM);
279 /* only sysadmin can reuse a group id */
280 if (!admin && !pr_noAuth && (aid != ntohl(cheader.maxGroup) - 1))
281 ABORT_WITH(tt, PRPERM);
283 if (FindByID(tt, aid))
284 ABORT_WITH(tt, PRIDEXIST);
286 /* check a few other things */
287 if (!CreateOK(tt, *cid, oid, gflag, admin))
288 ABORT_WITH(tt, PRPERM);
290 code = CreateEntry(tt, aname, &aid, 1, gflag, oid, *cid);
291 if (code != PRSUCCESS)
292 ABORT_WITH(tt, code);
294 /* finally, commit transaction */
295 code = ubik_EndTrans(tt);
303 SPR_NewEntry(struct rx_call *call, char aname[], afs_int32 flag, afs_int32 oid,
307 afs_int32 cid = ANONYMOUSID;
309 code = newEntry(call, aname, flag, oid, aid, &cid);
310 osi_auditU(call, PTS_NewEntEvent, code, AUD_ID, *aid, AUD_STR, aname,
311 AUD_ID, oid, AUD_END);
312 ViceLog(5, ("PTS_NewEntry: code %d cid %d aid %d aname %s oid %d\n", code, cid, *aid, aname, oid));
317 newEntry(struct rx_call *call, char aname[], afs_int32 flag, afs_int32 oid,
318 afs_int32 *aid, afs_int32 *cid)
321 struct ubik_trans *tt;
324 char cname[PR_MAXNAMELEN];
327 code = WritePreamble(&tt);
331 /* this is for cross-cell self registration. It is not added in the
332 * SPR_INewEntry because we want self-registration to only do
333 * automatic id assignment.
335 code = WhoIsThisWithName(call, tt, cid, cname);
336 if (code && code != 2)
337 ABORT_WITH(tt, PRPERM);
338 admin = IsAMemberOf(tt, *cid, SYSADMINID);
339 if (code == 2 /* foreign cell request */) {
342 if (!restricted && (strcmp(aname, cname) == 0)) {
343 /* can't autoregister while providing an owner id */
345 ABORT_WITH(tt, PRPERM);
351 if (!CreateOK(tt, *cid, oid, flag, admin))
352 ABORT_WITH(tt, PRPERM);
354 code = CreateEntry(tt, aname, aid, 0, flag, oid, *cid);
356 * If this was an autoregistration then be sure to audit log
357 * the proper id as the creator.
359 if (foreign && code == 0 && *aid > 0)
361 if (code != PRSUCCESS)
362 ABORT_WITH(tt, code);
364 code = ubik_EndTrans(tt);
373 SPR_WhereIsIt(struct rx_call *call, afs_int32 aid, afs_int32 *apos)
376 afs_int32 cid = ANONYMOUSID;
378 code = whereIsIt(call, aid, apos, &cid);
379 osi_auditU(call, PTS_WheIsItEvent, code, AUD_ID, aid, AUD_LONG, *apos,
381 ViceLog(125, ("PTS_WhereIsIt: code %d cid %d aid %d apos %d\n", code, cid, aid, *apos));
386 whereIsIt(struct rx_call *call, afs_int32 aid, afs_int32 *apos, afs_int32 *cid)
389 struct ubik_trans *tt;
392 code = ReadPreamble(&tt);
396 code = WhoIsThis(call, tt, cid);
398 ABORT_WITH(tt, PRPERM);
399 if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID)
400 ABORT_WITH(tt, PRPERM);
402 temp = FindByID(tt, aid);
404 ABORT_WITH(tt, PRNOENT);
406 code = ubik_EndTrans(tt);
414 SPR_DumpEntry(struct rx_call *call, afs_int32 apos,
415 struct prdebugentry *aentry)
418 afs_int32 cid = ANONYMOUSID;
420 code = dumpEntry(call, apos, aentry, &cid);
421 osi_auditU(call, PTS_DmpEntEvent, code, AUD_LONG, apos, AUD_END);
422 ViceLog(125, ("PTS_DumpEntry: code %d cid %d apos %d\n", code, cid, apos));
427 dumpEntry(struct rx_call *call, afs_int32 apos, struct prdebugentry *aentry,
431 struct ubik_trans *tt;
433 code = ReadPreamble(&tt);
437 code = WhoIsThis(call, tt, cid);
439 ABORT_WITH(tt, PRPERM);
440 code = pr_ReadEntry(tt, 0, apos, (struct prentry *)aentry);
442 ABORT_WITH(tt, code);
444 if (!AccessOK(tt, *cid, 0, PRP_STATUS_MEM, 0))
445 ABORT_WITH(tt, PRPERM);
447 code = ubik_EndTrans(tt);
454 SPR_AddToGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid)
457 afs_int32 cid = ANONYMOUSID;
459 code = addToGroup(call, aid, gid, &cid);
460 osi_auditU(call, PTS_AdToGrpEvent, code, AUD_ID, gid, AUD_ID, aid,
462 ViceLog(5, ("PTS_AddToGroup: code %d cid %d gid %d aid %d\n", code, cid, gid, aid));
467 addToGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid, afs_int32 *cid)
470 struct ubik_trans *tt;
473 struct prentry tentry;
474 struct prentry uentry;
476 if (gid == ANYUSERID || gid == AUTHUSERID)
478 if (aid == ANONYMOUSID)
481 code = WritePreamble(&tt);
485 code = WhoIsThis(call, tt, cid);
487 ABORT_WITH(tt, PRPERM);
488 tempu = FindByID(tt, aid);
490 ABORT_WITH(tt, PRNOENT);
491 memset(&uentry, 0, sizeof(uentry));
492 code = pr_ReadEntry(tt, 0, tempu, &uentry);
494 ABORT_WITH(tt, code);
496 #if !defined(SUPERGROUPS)
497 /* we don't allow groups as members of groups at present */
498 if (uentry.flags & PRGRP)
499 ABORT_WITH(tt, PRNOTUSER);
502 tempg = FindByID(tt, gid);
504 ABORT_WITH(tt, PRNOENT);
505 code = pr_ReadEntry(tt, 0, tempg, &tentry);
507 ABORT_WITH(tt, code);
508 /* make sure that this is a group */
509 if (!(tentry.flags & PRGRP))
510 ABORT_WITH(tt, PRNOTGROUP);
511 if (!AccessOK(tt, *cid, &tentry, PRP_ADD_MEM, PRP_ADD_ANY))
512 ABORT_WITH(tt, PRPERM);
514 code = AddToEntry(tt, &tentry, tempg, aid);
515 if (code != PRSUCCESS)
516 ABORT_WITH(tt, code);
518 #if defined(SUPERGROUPS)
519 if (uentry.flags & PRGRP)
520 code = AddToSGEntry(tt, &uentry, tempu, gid); /* mod group to be in sg */
523 /* now, modify the user's entry as well */
524 code = AddToEntry(tt, &uentry, tempu, gid);
525 if (code != PRSUCCESS)
526 ABORT_WITH(tt, code);
527 code = ubik_EndTrans(tt);
534 SPR_NameToID(struct rx_call *call, namelist *aname, idlist *aid)
538 code = nameToID(call, aname, aid);
539 osi_auditU(call, PTS_NmToIdEvent, code, AUD_END);
540 ViceLog(125, ("PTS_NameToID: code %d\n", code));
545 nameToID(struct rx_call *call, namelist *aname, idlist *aid)
548 struct ubik_trans *tt;
553 /* Initialize return struct */
555 aid->idlist_val = NULL;
557 size = aname->namelist_len;
563 aid->idlist_val = malloc(size * sizeof(afs_int32));
564 if (!aid->idlist_val)
567 code = ReadPreamble(&tt);
571 for (i = 0; i < aname->namelist_len; i++) {
573 char *nameinst, *cell;
574 afs_int32 islocal = 1;
576 strncpy(vname, aname->namelist_val[i], sizeof(vname));
577 vname[sizeof(vname)-1] ='\0';
580 cell = strchr(vname, '@');
587 code = afsconf_IsLocalRealmMatch(prdir, &islocal, nameinst, NULL, cell);
589 ("PTS_NameToID: afsconf_IsLocalRealmMatch(); code=%d, nameinst=%s, cell=%s\n",
590 code, nameinst, cell));
593 code = lookup_id_from_name(tt, nameinst, &aid->idlist_val[i]);
595 code = lookup_id_from_name(tt, aname->namelist_val[i],
596 &aid->idlist_val[i]);
598 if (code != PRSUCCESS)
599 aid->idlist_val[i] = ANONYMOUSID;
600 osi_audit(PTS_NmToIdEvent, code, AUD_STR,
601 aname->namelist_val[i], AUD_ID, aid->idlist_val[i],
603 ViceLog(125, ("PTS_NameToID: code %d aname %s aid %d\n", code,
604 aname->namelist_val[i], aid->idlist_val[i]));
606 #ifndef AFS_PTHREAD_ENV
612 aid->idlist_len = aname->namelist_len;
614 code = ubik_EndTrans(tt);
622 * Given an array of ids, find the name for each of them.
623 * The array of ids and names is unlimited.
626 SPR_IDToName(struct rx_call *call, idlist *aid, namelist *aname)
629 afs_int32 cid = ANONYMOUSID;
631 code = idToName(call, aid, aname, &cid);
632 osi_auditU(call, PTS_IdToNmEvent, code, AUD_END);
633 ViceLog(125, ("PTS_IDToName: code %d\n", code));
638 idToName(struct rx_call *call, idlist *aid, namelist *aname, afs_int32 *cid)
641 struct ubik_trans *tt;
646 /* leave this first for rpc stub */
647 size = aid->idlist_len;
650 if (size < 0 || size > INT_MAX / PR_MAXNAMELEN)
652 aname->namelist_val = calloc(size, PR_MAXNAMELEN);
653 aname->namelist_len = 0;
654 if (aname->namelist_val == 0)
656 if (aid->idlist_len == 0)
659 return PRTOOMANY; /* rxgen will probably handle this */
661 code = ReadPreamble(&tt);
665 code = WhoIsThis(call, tt, cid);
667 ABORT_WITH(tt, PRPERM);
668 if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID)
669 ABORT_WITH(tt, PRPERM);
671 for (i = 0; i < aid->idlist_len; i++) {
672 code = lookup_name_from_id(tt, aid->idlist_val[i],
673 aname->namelist_val[i]);
674 if (code != PRSUCCESS)
675 sprintf(aname->namelist_val[i], "%d", aid->idlist_val[i]);
676 osi_audit(PTS_IdToNmEvent, code, AUD_ID, aid->idlist_val[i],
677 AUD_STR, aname->namelist_val[i], AUD_END);
678 ViceLog(125, ("PTS_idToName: code %d aid %d aname %s\n", code,
679 aid->idlist_val[i], aname->namelist_val[i]));
681 #ifndef AFS_PTHREAD_ENV
687 aname->namelist_len = aid->idlist_len;
689 code = ubik_EndTrans(tt);
696 lookup_name_from_id(struct ubik_trans *at, afs_int32 aid,
697 char aname[PR_MAXNAMELEN])
700 struct prentry tentry;
703 temp = FindByID(at, aid);
706 code = pr_Read(at, 0, temp, (char *)&tentry, sizeof(tentry));
709 strncpy(aname, tentry.name, PR_MAXNAMELEN);
714 lookup_id_from_name(struct ubik_trans *at, char aname[PR_MAXNAMELEN],
718 struct prentry tentry;
720 temp = FindByName(at, aname, &tentry);
728 SPR_Delete(struct rx_call *call, afs_int32 aid)
731 afs_int32 cid = ANONYMOUSID;
733 code = Delete(call, aid, &cid);
734 osi_auditU(call, PTS_DelEvent, code, AUD_ID, aid, AUD_END);
735 ViceLog(5, ("PTS_Delete: code %d cid %d aid %d\n", code, cid, aid));
740 Delete(struct rx_call *call, afs_int32 aid, afs_int32 *cid)
743 struct ubik_trans *tt;
744 struct prentry tentry;
748 if (aid == SYSADMINID || aid == ANYUSERID || aid == AUTHUSERID
749 || aid == ANONYMOUSID)
752 code = WritePreamble(&tt);
756 code = WhoIsThis(call, tt, cid);
758 ABORT_WITH(tt, PRPERM);
760 /* Read in entry to be deleted */
761 loc = FindByID(tt, aid);
763 ABORT_WITH(tt, PRNOENT);
764 code = pr_ReadEntry(tt, 0, loc, &tentry);
766 ABORT_WITH(tt, PRDBFAIL);
768 /* Do some access checking */
769 if (tentry.owner != *cid && !IsAMemberOf(tt, *cid, SYSADMINID)
770 && !IsAMemberOf(tt, *cid, tentry.owner) && !pr_noAuth)
771 ABORT_WITH(tt, PRPERM);
773 if (restricted && !IsAMemberOf(tt, *cid, SYSADMINID)) {
774 ABORT_WITH(tt, PRPERM);
777 /* Delete each continuation block as a separate transaction so that no one
778 * transaction become to large to complete. */
781 struct contentry centry;
784 code = pr_ReadCoEntry(tt, 0, nptr, ¢ry);
786 ABORT_WITH(tt, PRDBFAIL);
787 for (i = 0; i < COSIZE; i++) {
788 if (centry.entries[i] == PRBADID)
790 if (centry.entries[i] == 0)
792 #if defined(SUPERGROUPS)
793 if (aid < 0 && centry.entries[i] < 0) /* Supergroup */
794 code = RemoveFromSGEntry(tt, aid, centry.entries[i]);
797 code = RemoveFromEntry(tt, aid, centry.entries[i]);
799 ABORT_WITH(tt, code);
800 tentry.count--; /* maintain count */
801 #ifndef AFS_PTHREAD_ENV
806 tentry.next = centry.next; /* thread out this block */
807 code = FreeBlock(tt, nptr); /* free continuation block */
809 ABORT_WITH(tt, code);
810 code = pr_WriteEntry(tt, 0, loc, &tentry); /* update main entry */
812 ABORT_WITH(tt, code);
814 /* end this trans and start a new one */
815 code = ubik_EndTrans(tt);
818 #ifndef AFS_PTHREAD_ENV
819 IOMGR_Poll(); /* just to keep the connection alive */
821 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
824 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
826 ABORT_WITH(tt, code);
828 /* re-read entry to get consistent uptodate info */
829 loc = FindByID(tt, aid);
831 ABORT_WITH(tt, PRNOENT);
832 code = pr_ReadEntry(tt, 0, loc, &tentry);
834 ABORT_WITH(tt, PRDBFAIL);
839 #if defined(SUPERGROUPS)
840 /* Delete each continuation block as a separate transaction
841 * so that no one transaction become too large to complete. */
843 struct prentryg *tentryg = (struct prentryg *)&tentry;
844 nptr = tentryg->nextsg;
846 struct contentry centry;
849 code = pr_ReadCoEntry(tt, 0, nptr, ¢ry);
851 ABORT_WITH(tt, PRDBFAIL);
852 for (i = 0; i < COSIZE; i++) {
853 if (centry.entries[i] == PRBADID)
855 if (centry.entries[i] == 0)
857 code = RemoveFromEntry(tt, aid, centry.entries[i]);
859 ABORT_WITH(tt, code);
860 tentryg->countsg--; /* maintain count */
861 #ifndef AFS_PTHREAD_ENV
866 tentryg->nextsg = centry.next; /* thread out this block */
867 code = FreeBlock(tt, nptr); /* free continuation block */
869 ABORT_WITH(tt, code);
870 code = pr_WriteEntry(tt, 0, loc, &tentry); /* update main entry */
872 ABORT_WITH(tt, code);
874 /* end this trans and start a new one */
875 code = ubik_EndTrans(tt);
878 #ifndef AFS_PTHREAD_ENV
879 IOMGR_Poll(); /* just to keep the connection alive */
882 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
885 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
887 ABORT_WITH(tt, code);
889 /* re-read entry to get consistent uptodate info */
890 loc = FindByID(tt, aid);
892 ABORT_WITH(tt, PRNOENT);
893 code = pr_ReadEntry(tt, 0, loc, &tentry);
895 ABORT_WITH(tt, PRDBFAIL);
897 nptr = tentryg->nextsg;
901 #endif /* SUPERGROUPS */
903 /* Then move the owned chain, except possibly ourself to the orphan list.
904 * Because this list can be very long and so exceed the size of a ubik
905 * transaction, we start a new transaction every 50 entries. */
909 struct prentry nentry;
911 code = pr_ReadEntry(tt, 0, nptr, &nentry);
913 ABORT_WITH(tt, PRDBFAIL);
914 nptr = tentry.owned = nentry.nextOwned; /* thread out */
916 if (nentry.id != tentry.id) { /* don't add us to orphan chain! */
917 code = AddToOrphan(tt, nentry.id);
919 ABORT_WITH(tt, code);
921 #ifndef AFS_PTHREAD_ENV
922 if ((count & 3) == 0)
928 code = pr_WriteEntry(tt, 0, loc, &tentry); /* update main entry */
930 ABORT_WITH(tt, code);
932 /* end this trans and start a new one */
933 code = ubik_EndTrans(tt);
936 #ifndef AFS_PTHREAD_ENV
937 IOMGR_Poll(); /* just to keep the connection alive */
939 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
942 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
944 ABORT_WITH(tt, code);
946 /* re-read entry to get consistent uptodate info */
947 loc = FindByID(tt, aid);
949 ABORT_WITH(tt, PRNOENT);
950 code = pr_ReadEntry(tt, 0, loc, &tentry);
952 ABORT_WITH(tt, PRDBFAIL);
957 /* now do what's left of the deletion stuff */
958 code = DeleteEntry(tt, &tentry, loc);
959 if (code != PRSUCCESS)
960 ABORT_WITH(tt, code);
962 code = ubik_EndTrans(tt);
969 SPR_UpdateEntry(struct rx_call *call, afs_int32 aid, char *name,
970 struct PrUpdateEntry *uentry)
973 afs_int32 cid = ANONYMOUSID;
975 code = UpdateEntry(call, aid, name, uentry, &cid);
976 osi_auditU(call, PTS_UpdEntEvent, code, AUD_ID, aid, AUD_STR, name, AUD_END);
977 ViceLog(5, ("PTS_UpdateEntry: code %d cid %d aid %d name %s\n", code, cid, aid, name));
982 UpdateEntry(struct rx_call *call, afs_int32 aid, char *name,
983 struct PrUpdateEntry *uentry, afs_int32 *cid)
986 struct ubik_trans *tt;
987 struct prentry tentry;
993 if (aid == SYSADMINID || aid == ANYUSERID || aid == AUTHUSERID
994 || aid == ANONYMOUSID)
998 code = WritePreamble(&tt);
1002 code = WhoIsThis(call, tt, cid);
1004 ABORT_WITH(tt, PRPERM);
1005 code = IsAMemberOf(tt, *cid, SYSADMINID);
1006 if (!code && !pr_noAuth)
1007 ABORT_WITH(tt, PRPERM);
1009 /* Read in entry to be deleted */
1011 loc = FindByID(tt, aid);
1013 loc = FindByName(tt, name, &tentry);
1016 ABORT_WITH(tt, PRNOENT);
1017 code = pr_ReadEntry(tt, 0, loc, &tentry);
1019 ABORT_WITH(tt, PRDBFAIL);
1021 if (uentry->Mask & PRUPDATE_NAMEHASH) {
1023 code = RemoveFromNameHash(tt, tentry.name, &tloc);
1024 if (code != PRSUCCESS)
1025 ABORT_WITH(tt, PRDBFAIL);
1026 code = AddToNameHash(tt, tentry.name, loc);
1028 ABORT_WITH(tt, code);
1031 if (uentry->Mask & PRUPDATE_IDHASH) {
1035 code = RemoveFromIDHash(tt, id, &tloc);
1036 if (code != PRSUCCESS)
1037 ABORT_WITH(tt, PRDBFAIL);
1038 code = AddToIDHash(tt, id, loc);
1040 ABORT_WITH(tt, code);
1043 code = ubik_EndTrans(tt);
1050 SPR_RemoveFromGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid)
1053 afs_int32 cid = ANONYMOUSID;
1055 code = removeFromGroup(call, aid, gid, &cid);
1056 osi_auditU(call, PTS_RmFmGrpEvent, code, AUD_ID, gid, AUD_ID, aid,
1058 ViceLog(5, ("PTS_RemoveFromGroup: code %d cid %d gid %d aid %d\n", code, cid, gid, aid));
1063 removeFromGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid,
1067 struct ubik_trans *tt;
1070 struct prentry uentry;
1071 struct prentry gentry;
1073 code = WritePreamble(&tt);
1077 code = WhoIsThis(call, tt, cid);
1079 ABORT_WITH(tt, PRPERM);
1080 tempu = FindByID(tt, aid);
1082 ABORT_WITH(tt, PRNOENT);
1083 tempg = FindByID(tt, gid);
1085 ABORT_WITH(tt, PRNOENT);
1086 memset(&uentry, 0, sizeof(uentry));
1087 memset(&gentry, 0, sizeof(gentry));
1088 code = pr_ReadEntry(tt, 0, tempu, &uentry);
1090 ABORT_WITH(tt, code);
1091 code = pr_ReadEntry(tt, 0, tempg, &gentry);
1093 ABORT_WITH(tt, code);
1094 if (!(gentry.flags & PRGRP))
1095 ABORT_WITH(tt, PRNOTGROUP);
1096 #if !defined(SUPERGROUPS)
1097 if (uentry.flags & PRGRP)
1098 ABORT_WITH(tt, PRNOTUSER);
1100 if (!AccessOK(tt, *cid, &gentry, PRP_REMOVE_MEM, 0))
1101 ABORT_WITH(tt, PRPERM);
1102 code = RemoveFromEntry(tt, aid, gid);
1103 if (code != PRSUCCESS)
1104 ABORT_WITH(tt, code);
1105 #if defined(SUPERGROUPS)
1106 if (!(uentry.flags & PRGRP))
1108 code = RemoveFromEntry(tt, gid, aid);
1109 #if defined(SUPERGROUPS)
1111 code = RemoveFromSGEntry(tt, gid, aid);
1113 if (code != PRSUCCESS)
1114 ABORT_WITH(tt, code);
1116 code = ubik_EndTrans(tt);
1124 SPR_GetCPS(struct rx_call *call, afs_int32 aid, prlist *alist, afs_int32 *over)
1127 afs_int32 cid = ANONYMOUSID;
1129 code = getCPS(call, aid, alist, over, &cid);
1130 osi_auditU(call, PTS_GetCPSEvent, code, AUD_ID, aid, AUD_END);
1131 ViceLog(125, ("PTS_GetCPS: code %d cid %d aid %d\n", code, cid, aid));
1136 getCPS(struct rx_call *call, afs_int32 aid, prlist *alist, afs_int32 *over,
1140 struct ubik_trans *tt;
1142 struct prentry tentry;
1145 alist->prlist_len = 0;
1146 alist->prlist_val = NULL;
1148 code = ReadPreamble(&tt);
1152 code = WhoIsThis(call, tt, cid);
1154 ABORT_WITH(tt, PRPERM);
1155 if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID)
1156 ABORT_WITH(tt, PRPERM);
1158 temp = FindByID(tt, aid);
1160 ABORT_WITH(tt, PRNOENT);
1161 code = pr_ReadEntry(tt, 0, temp, &tentry);
1163 ABORT_WITH(tt, code);
1165 if (!AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1166 ABORT_WITH(tt, PRPERM);
1168 code = GetList(tt, &tentry, alist, 1);
1169 if (code != PRSUCCESS)
1170 ABORT_WITH(tt, code);
1172 code = ubik_EndTrans(tt);
1178 inCPS(prlist CPS, afs_int32 id)
1182 for (i = (CPS.prlist_len - 1); i >= 0; i--) {
1183 if (CPS.prlist_val[i] == id)
1191 SPR_GetCPS2(struct rx_call *call, afs_int32 aid, afs_int32 ahost,
1192 prlist *alist, afs_int32 *over)
1195 afs_int32 cid = ANONYMOUSID;
1197 code = getCPS2(call, aid, ahost, alist, over, &cid);
1198 osi_auditU(call, PTS_GetCPS2Event, code, AUD_ID, aid, AUD_HOST, htonl(ahost),
1200 ViceLog(125, ("PTS_GetCPS2: code %d cid %d aid %d ahost %d\n", code, cid, aid, ahost));
1205 getCPS2(struct rx_call *call, afs_int32 aid, afs_uint32 ahost, prlist *alist,
1206 afs_int32 *over, afs_int32 *cid)
1209 struct ubik_trans *tt;
1211 struct prentry tentry;
1212 struct prentry host_tentry;
1215 struct in_addr iaddr;
1219 iaddr.s_addr = ntohl(ahost);
1220 alist->prlist_len = 0;
1221 alist->prlist_val = NULL;
1223 code = ReadPreamble(&tt);
1227 if (aid != PRBADID) {
1228 temp = FindByID(tt, aid);
1230 ABORT_WITH(tt, PRNOENT);
1231 code = pr_ReadEntry(tt, 0, temp, &tentry);
1233 ABORT_WITH(tt, code);
1235 /* afs does authenticate now */
1236 code = WhoIsThis(call, tt, cid);
1238 || !AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1239 ABORT_WITH(tt, PRPERM);
1241 code = lookup_id_from_name(tt, afs_inet_ntoa_r(iaddr.s_addr, hoststr),
1243 if (code == PRSUCCESS && hostid != 0) {
1244 temp = FindByID(tt, hostid);
1246 code = pr_ReadEntry(tt, 0, temp, &host_tentry);
1247 if (code == PRSUCCESS)
1250 fprintf(stderr, "pr_ReadEntry returned %d\n", code);
1252 fprintf(stderr, "FindByID Failed -- Not found\n");
1255 code = GetList2(tt, &tentry, &host_tentry, alist, 1);
1257 code = GetList(tt, &tentry, alist, 1);
1259 code = addWildCards(tt, alist, ntohl(ahost));
1260 if (code != PRSUCCESS)
1261 ABORT_WITH(tt, code);
1263 code = ubik_EndTrans(tt);
1269 SPR_GetHostCPS(struct rx_call *call, afs_int32 ahost, prlist *alist,
1273 afs_int32 cid = ANONYMOUSID;
1275 code = getHostCPS(call, ahost, alist, over, &cid);
1276 osi_auditU(call, PTS_GetHCPSEvent, code, AUD_HOST, htonl(ahost), AUD_END);
1277 ViceLog(125, ("PTS_GetHostCPS: code %d ahost %u (0x%x)\n", code, ahost, ahost));
1282 getHostCPS(struct rx_call *call, afs_uint32 ahost, prlist *alist,
1283 afs_int32 *over, afs_int32 *cid)
1285 afs_int32 code, temp;
1286 struct ubik_trans *tt;
1287 struct prentry host_tentry;
1289 struct in_addr iaddr;
1293 iaddr.s_addr = ntohl(ahost);
1294 alist->prlist_len = 0;
1295 alist->prlist_val = NULL;
1297 code = ReadPreamble(&tt);
1301 code = WhoIsThis(call, tt, cid);
1303 ABORT_WITH(tt, PRPERM);
1304 if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID)
1305 ABORT_WITH(tt, PRPERM);
1307 code = lookup_id_from_name(tt, afs_inet_ntoa_r(iaddr.s_addr, hoststr),
1309 if (code == PRSUCCESS && hostid != 0) {
1310 temp = FindByID(tt, hostid);
1312 code = pr_ReadEntry(tt, 0, temp, &host_tentry);
1313 if (code == PRSUCCESS) {
1314 code = GetList(tt, &host_tentry, alist, 0);
1318 fprintf(stderr, "pr_ReadEntry returned %d\n", code);
1320 fprintf(stderr, "FindByID Failed -- Not found\n");
1322 code = addWildCards(tt, alist, ntohl(ahost));
1324 if (code != PRSUCCESS)
1325 ABORT_WITH(tt, code);
1327 code = ubik_EndTrans(tt);
1333 SPR_ListMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid)
1336 afs_int32 cid = ANONYMOUSID;
1338 code = listMax(call, uid, gid, &cid);
1339 osi_auditU(call, PTS_LstMaxEvent, code, AUD_END);
1340 ViceLog(125, ("PTS_ListMax: code %d\n", code));
1345 listMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid, afs_int32 *cid)
1348 struct ubik_trans *tt;
1350 code = ReadPreamble(&tt);
1354 code = WhoIsThis(call, tt, cid);
1356 ABORT_WITH(tt, PRPERM);
1357 if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID)
1358 ABORT_WITH(tt, PRPERM);
1360 code = GetMax(tt, uid, gid);
1361 if (code != PRSUCCESS)
1362 ABORT_WITH(tt, code);
1364 code = ubik_EndTrans(tt);
1371 SPR_SetMax(struct rx_call *call, afs_int32 aid, afs_int32 gflag)
1374 afs_int32 cid = ANONYMOUSID;
1376 code = setMax(call, aid, gflag, &cid);
1377 osi_auditU(call, PTS_SetMaxEvent, code, AUD_ID, aid, AUD_LONG, gflag,
1379 ViceLog(125, ("PTS_SetMax: code %d cid %d aid %d gflag %d\n", code, cid, aid, gflag));
1384 setMax(struct rx_call *call, afs_int32 aid, afs_int32 gflag, afs_int32 *cid)
1387 struct ubik_trans *tt;
1389 code = WritePreamble(&tt);
1393 code = WhoIsThis(call, tt, cid);
1395 ABORT_WITH(tt, PRPERM);
1396 if (!AccessOK(tt, *cid, 0, 0, 0))
1397 ABORT_WITH(tt, PRPERM);
1398 if (((gflag & PRGRP) && (aid > 0)) || (!(gflag & PRGRP) && (aid < 0)))
1399 ABORT_WITH(tt, PRBADARG);
1401 code = SetMax(tt, aid, gflag);
1402 if (code != PRSUCCESS)
1403 ABORT_WITH(tt, code);
1405 code = ubik_EndTrans(tt);
1412 SPR_ListEntry(struct rx_call *call, afs_int32 aid, struct prcheckentry *aentry)
1415 afs_int32 cid = ANONYMOUSID;
1417 code = listEntry(call, aid, aentry, &cid);
1418 osi_auditU(call, PTS_LstEntEvent, code, AUD_ID, aid, AUD_END);
1419 ViceLog(125, ("PTS_ListEntry: code %d cid %d aid %d\n", code, cid, aid));
1424 listEntry(struct rx_call *call, afs_int32 aid, struct prcheckentry *aentry,
1428 struct ubik_trans *tt;
1430 struct prentry tentry;
1432 code = ReadPreamble(&tt);
1436 code = WhoIsThis(call, tt, cid);
1438 ABORT_WITH(tt, PRPERM);
1439 if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID)
1440 ABORT_WITH(tt, PRPERM);
1441 temp = FindByID(tt, aid);
1443 ABORT_WITH(tt, PRNOENT);
1444 code = pr_ReadEntry(tt, 0, temp, &tentry);
1446 ABORT_WITH(tt, code);
1447 if (!AccessOK(tt, *cid, &tentry, PRP_STATUS_MEM, PRP_STATUS_ANY))
1448 ABORT_WITH(tt, PRPERM);
1450 aentry->flags = tentry.flags >> PRIVATE_SHIFT;
1451 if (aentry->flags == 0) {
1452 if (tentry.flags & PRGRP)
1453 aentry->flags = prp_group_default >> PRIVATE_SHIFT;
1455 aentry->flags = prp_user_default >> PRIVATE_SHIFT;
1457 aentry->owner = tentry.owner;
1458 aentry->id = tentry.id;
1459 strncpy(aentry->name, tentry.name, PR_MAXNAMELEN);
1460 aentry->creator = tentry.creator;
1461 aentry->ngroups = tentry.ngroups;
1462 aentry->nusers = tentry.nusers;
1463 aentry->count = tentry.count;
1464 memset(aentry->reserved, 0, sizeof(aentry->reserved));
1465 code = ubik_EndTrans(tt);
1472 SPR_ListEntries(struct rx_call *call, afs_int32 flag, afs_int32 startindex,
1473 prentries *bulkentries, afs_int32 *nextstartindex)
1476 afs_int32 cid = ANONYMOUSID;
1478 code = listEntries(call, flag, startindex, bulkentries, nextstartindex, &cid);
1479 osi_auditU(call, PTS_LstEntsEvent, code, AUD_LONG, flag, AUD_END);
1480 ViceLog(125, ("PTS_ListEntries: code %d cid %d flag %d\n", code, cid, flag));
1484 #define PR_MAXENTRIES 500
1486 listEntries(struct rx_call *call, afs_int32 flag, afs_int32 startindex,
1487 prentries *bulkentries, afs_int32 *nextstartindex, afs_int32 *cid)
1490 struct ubik_trans *tt;
1491 afs_int32 i, eof, pos, maxentries, f;
1492 struct prentry tentry;
1493 afs_int32 pollcount = 0;
1495 *nextstartindex = -1;
1496 bulkentries->prentries_val = 0;
1497 bulkentries->prentries_len = 0;
1499 code = ReadPreamble(&tt);
1503 /* Make sure we are an authenticated caller and that we are on the
1506 code = WhoIsThis(call, tt, cid);
1508 ABORT_WITH(tt, PRPERM);
1509 code = IsAMemberOf(tt, *cid, SYSADMINID);
1510 if (!code && !pr_noAuth)
1511 ABORT_WITH(tt, PRPERM);
1513 eof = ntohl(cheader.eofPtr) - sizeof(cheader);
1514 maxentries = eof / sizeof(struct prentry);
1516 bulkentries->prentries_val = calloc(PR_MAXENTRIES,
1517 sizeof(bulkentries->prentries_val[0]));
1518 if (!bulkentries->prentries_val)
1519 ABORT_WITH(tt, PRNOMEM);
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 put_prentries(&tentry, bulkentries);
1538 if (bulkentries->prentries_len >= PR_MAXENTRIES)
1544 *nextstartindex = i;
1548 if (bulkentries->prentries_val)
1549 free(bulkentries->prentries_val);
1550 bulkentries->prentries_val = 0;
1551 bulkentries->prentries_len = 0;
1552 ABORT_WITH(tt, code);
1554 code = ubik_EndTrans(tt);
1562 put_prentries(struct prentry *tentry, prentries *bulkentries)
1564 struct prlistentries *entry;
1566 entry = bulkentries->prentries_val;
1567 entry += bulkentries->prentries_len;
1569 entry->flags = tentry->flags >> PRIVATE_SHIFT;
1570 if (entry->flags == 0) {
1573 flags & PRGRP) ? prp_group_default : prp_user_default) >>
1576 entry->owner = tentry->owner;
1577 entry->id = tentry->id;
1578 entry->creator = tentry->creator;
1579 entry->ngroups = tentry->ngroups;
1580 entry->nusers = tentry->nusers;
1581 entry->count = tentry->count;
1582 strncpy(entry->name, tentry->name, PR_MAXNAMELEN);
1583 bulkentries->prentries_len++;
1587 SPR_ChangeEntry(struct rx_call *call, afs_int32 aid, char *name, afs_int32 oid,
1591 afs_int32 cid = ANONYMOUSID;
1593 code = changeEntry(call, aid, name, oid, newid, &cid);
1594 osi_auditU(call, PTS_ChgEntEvent, code, AUD_ID, aid, AUD_STR, name,
1595 AUD_LONG, oid, AUD_LONG, newid, AUD_END);
1596 ViceLog(5, ("PTS_ChangeEntry: code %d cid %d aid %d name %s oid %d newid %d\n", code, cid, aid, name, oid, newid));
1601 changeEntry(struct rx_call *call, afs_int32 aid, char *name, afs_int32 oid,
1602 afs_int32 newid, afs_int32 *cid)
1605 struct ubik_trans *tt;
1612 if (aid == ANYUSERID || aid == AUTHUSERID || aid == ANONYMOUSID
1613 || aid == SYSADMINID)
1616 code = WritePreamble(&tt);
1620 code = WhoIsThis(call, tt, cid);
1622 ABORT_WITH(tt, PRPERM);
1623 pos = FindByID(tt, aid);
1625 ABORT_WITH(tt, PRNOENT);
1626 /* protection check in changeentry */
1627 code = ChangeEntry(tt, aid, *cid, name, oid, newid);
1628 if (code != PRSUCCESS)
1629 ABORT_WITH(tt, code);
1631 code = ubik_EndTrans(tt);
1636 SPR_SetFieldsEntry(struct rx_call *call,
1638 afs_int32 mask, /* specify which fields to update */
1639 afs_int32 flags, afs_int32 ngroups, afs_int32 nusers,
1640 afs_int32 spare1, afs_int32 spare2)
1643 afs_int32 cid = ANONYMOUSID;
1646 setFieldsEntry(call, id, mask, flags, ngroups, nusers, spare1,
1648 osi_auditU(call, PTS_SetFldEntEvent, code, AUD_ID, id, AUD_END);
1649 ViceLog(5, ("PTS_SetFieldsEntry: code %d cid %d id %d\n", code, cid, id));
1654 setFieldsEntry(struct rx_call *call,
1656 afs_int32 mask, /* specify which fields to update */
1657 afs_int32 flags, afs_int32 ngroups, afs_int32 nusers,
1658 afs_int32 spare1, afs_int32 spare2, afs_int32 *cid)
1661 struct ubik_trans *tt;
1663 struct prentry tentry;
1667 return 0; /* no-op */
1669 if (id == ANYUSERID || id == AUTHUSERID || id == ANONYMOUSID)
1672 code = WritePreamble(&tt);
1676 code = WhoIsThis(call, tt, cid);
1678 ABORT_WITH(tt, PRPERM);
1679 pos = FindByID(tt, id);
1681 ABORT_WITH(tt, PRNOENT);
1682 code = pr_ReadEntry(tt, 0, pos, &tentry);
1684 ABORT_WITH(tt, code);
1685 tflags = tentry.flags;
1687 if (mask & (PR_SF_NGROUPS | PR_SF_NUSERS)) {
1688 if (!AccessOK(tt, *cid, 0, 0, 0))
1689 ABORT_WITH(tt, PRPERM);
1690 if ((tflags & PRQUOTA) == 0) { /* default if only setting one */
1691 tentry.ngroups = tentry.nusers = 20;
1694 if (!AccessOK(tt, *cid, &tentry, 0, 0))
1695 ABORT_WITH(tt, PRPERM);
1698 if (mask & 0xffff) { /* if setting flag bits */
1699 afs_int32 flagsMask = mask & 0xffff;
1700 tflags &= ~(flagsMask << PRIVATE_SHIFT);
1701 tflags |= (flags & flagsMask) << PRIVATE_SHIFT;
1705 if (mask & PR_SF_NGROUPS) { /* setting group limit */
1707 ABORT_WITH(tt, PRBADARG);
1708 tentry.ngroups = ngroups;
1712 if (mask & PR_SF_NUSERS) { /* setting foreign user limit */
1714 ABORT_WITH(tt, PRBADARG);
1715 tentry.nusers = nusers;
1718 tentry.flags = tflags;
1720 code = pr_WriteEntry(tt, 0, pos, &tentry);
1722 ABORT_WITH(tt, code);
1724 code = ubik_EndTrans(tt);
1729 SPR_ListElements(struct rx_call *call, afs_int32 aid, prlist *alist,
1733 afs_int32 cid = ANONYMOUSID;
1735 code = listElements(call, aid, alist, over, &cid);
1736 osi_auditU(call, PTS_LstEleEvent, code, AUD_ID, aid, AUD_END);
1737 ViceLog(125, ("PTS_ListElements: code %d cid %d aid %d\n", code, cid, aid));
1742 listElements(struct rx_call *call, afs_int32 aid, prlist *alist,
1743 afs_int32 *over, afs_int32 *cid)
1746 struct ubik_trans *tt;
1748 struct prentry tentry;
1751 alist->prlist_len = 0;
1752 alist->prlist_val = NULL;
1754 code = ReadPreamble(&tt);
1758 code = WhoIsThis(call, tt, cid);
1760 ABORT_WITH(tt, PRPERM);
1762 temp = FindByID(tt, aid);
1764 ABORT_WITH(tt, PRNOENT);
1765 code = pr_ReadEntry(tt, 0, temp, &tentry);
1767 ABORT_WITH(tt, code);
1768 if (!AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1769 ABORT_WITH(tt, PRPERM);
1771 code = GetList(tt, &tentry, alist, 0);
1772 if (code != PRSUCCESS)
1773 ABORT_WITH(tt, code);
1775 code = ubik_EndTrans(tt);
1781 SPR_ListSuperGroups(struct rx_call *call, afs_int32 aid, prlist *alist,
1784 #if defined(SUPERGROUPS)
1786 afs_int32 cid = ANONYMOUSID;
1788 code = listSuperGroups(call, aid, alist, over, &cid);
1789 osi_auditU(call, PTS_LstSGrps, code, AUD_ID, aid, AUD_END);
1790 ViceLog(125, ("PTS_ListSuperGroups: code %d cid %d aid %d\n", code, cid, aid));
1793 return RXGEN_OPCODE;
1797 #if defined(SUPERGROUPS)
1799 listSuperGroups(struct rx_call *call, afs_int32 aid, prlist *alist,
1800 afs_int32 *over, afs_int32 *cid)
1803 struct ubik_trans *tt;
1805 struct prentry tentry;
1807 alist->prlist_len = 0;
1808 alist->prlist_val = (afs_int32 *) 0;
1810 code = ReadPreamble(&tt);
1814 code = WhoIsThis(call, tt, cid);
1816 ABORT_WITH(tt, PRPERM);
1817 if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID)
1818 ABORT_WITH(tt, PRPERM);
1820 temp = FindByID(tt, aid);
1822 ABORT_WITH(tt, PRNOENT);
1823 code = pr_ReadEntry(tt, 0, temp, &tentry);
1825 ABORT_WITH(tt, code);
1826 if (!AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1827 ABORT_WITH(tt, PRPERM);
1829 code = GetSGList(tt, &tentry, alist);
1831 if (code == PRTOOMANY)
1833 else if (code != PRSUCCESS)
1834 ABORT_WITH(tt, code);
1836 code = ubik_EndTrans(tt);
1841 #endif /* SUPERGROUPS */
1845 * List the entries owned by this id. If the id is zero,
1846 * return the orphans list. This will return up to PR_MAXGROUPS
1847 * at a time with the lastP available to get the rest. The
1848 * maximum value is enforced in GetOwnedChain().
1851 SPR_ListOwned(struct rx_call *call, afs_int32 aid, prlist *alist,
1855 afs_int32 cid = ANONYMOUSID;
1857 code = listOwned(call, aid, alist, lastP, &cid);
1858 osi_auditU(call, PTS_LstOwnEvent, code, AUD_ID, aid, AUD_END);
1859 ViceLog(125, ("PTS_ListOwned: code %d cid %d aid %d\n", code, cid, aid));
1864 listOwned(struct rx_call *call, afs_int32 aid, prlist *alist, afs_int32 *lastP,
1868 struct ubik_trans *tt;
1869 struct prentry tentry;
1873 alist->prlist_len = 0;
1874 alist->prlist_val = NULL;
1881 code = ReadPreamble(&tt);
1885 code = WhoIsThis(call, tt, cid);
1887 ABORT_WITH(tt, PRPERM);
1890 code = pr_ReadEntry(tt, 0, start, &tentry);
1891 if (!code && (tentry.owner == aid))
1892 head = start; /* pick up where we left off */
1897 afs_int32 loc = FindByID(tt, aid);
1899 ABORT_WITH(tt, PRNOENT);
1900 code = pr_ReadEntry(tt, 0, loc, &tentry);
1902 ABORT_WITH(tt, code);
1904 if (!AccessOK(tt, *cid, &tentry, -1, PRP_OWNED_ANY))
1905 ABORT_WITH(tt, PRPERM);
1906 head = tentry.owned;
1908 if (!AccessOK(tt, *cid, 0, 0, 0))
1909 ABORT_WITH(tt, PRPERM);
1910 head = ntohl(cheader.orphan);
1914 code = GetOwnedChain(tt, &head, alist);
1916 if (code == PRTOOMANY)
1919 ABORT_WITH(tt, code);
1922 code = ubik_EndTrans(tt);
1927 SPR_IsAMemberOf(struct rx_call *call, afs_int32 uid, afs_int32 gid,
1931 afs_int32 cid = ANONYMOUSID;
1933 code = isAMemberOf(call, uid, gid, flag, &cid);
1934 osi_auditU(call, PTS_IsMemOfEvent, code, AUD_LONG, uid, AUD_LONG, gid,
1936 ViceLog(125, ("PTS_IsAMemberOf: code %d cid %d uid %d gid %d\n", code, cid, uid, gid));
1941 isAMemberOf(struct rx_call *call, afs_int32 uid, afs_int32 gid, afs_int32 *flag,
1945 struct ubik_trans *tt;
1947 code = ReadPreamble(&tt);
1952 afs_int32 uloc = FindByID(tt, uid);
1953 afs_int32 gloc = FindByID(tt, gid);
1954 struct prentry uentry, gentry;
1957 ABORT_WITH(tt, PRNOENT);
1958 code = WhoIsThis(call, tt, cid);
1960 ABORT_WITH(tt, PRPERM);
1961 code = pr_ReadEntry(tt, 0, uloc, &uentry);
1963 ABORT_WITH(tt, code);
1964 code = pr_ReadEntry(tt, 0, gloc, &gentry);
1966 ABORT_WITH(tt, code);
1967 #if !defined(SUPERGROUPS)
1968 if ((uentry.flags & PRGRP) || !(gentry.flags & PRGRP))
1969 ABORT_WITH(tt, PRBADARG);
1971 if (!(gentry.flags & PRGRP))
1972 ABORT_WITH(tt, PRBADARG);
1974 if (!AccessOK(tt, *cid, &uentry, 0, PRP_MEMBER_ANY)
1975 && !AccessOK(tt, *cid, &gentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1976 ABORT_WITH(tt, PRPERM);
1979 *flag = IsAMemberOf(tt, uid, gid);
1980 code = ubik_EndTrans(tt);
1985 addWildCards(struct ubik_trans *tt, prlist *alist, afs_uint32 host)
1988 struct prentry tentry;
1990 unsigned wild = htonl(0xffffff00);
1991 struct in_addr iaddr;
1993 int size = 0, i, code;
1997 while ((host = (host & wild))) {
1998 wild = htonl(ntohl(wild) << 8);
1999 iaddr.s_addr = host;
2000 code = lookup_id_from_name(tt, afs_inet_ntoa_r(iaddr.s_addr, hoststr),
2002 if (code == PRSUCCESS && hostid != 0) {
2003 temp = FindByID(tt, hostid);
2005 code = pr_ReadEntry(tt, 0, temp, &tentry);
2006 if (code != PRSUCCESS)
2012 wlist.prlist_len = 0;
2013 wlist.prlist_val = NULL;
2015 code = GetList(tt, &tentry, &wlist, 0);
2018 added += wlist.prlist_len;
2019 for (i = 0; i < wlist.prlist_len; i++) {
2020 if (!inCPS(*alist, wlist.prlist_val[i]))
2021 if ((code = AddToPRList(alist, &size, wlist.prlist_val[i]))) {
2022 free(wlist.prlist_val);
2026 if (wlist.prlist_val)
2027 free(wlist.prlist_val);
2030 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
2035 WhoIsThisWithName(struct rx_call *acall, struct ubik_trans *at, afs_int32 *aid,
2038 afs_int32 islocal = 1;
2039 /* aid is set to the identity of the caller, if known, else ANONYMOUSID */
2040 /* returns -1 and sets aid to ANONYMOUSID on any failure */
2041 struct rx_connection *tconn;
2043 char tcell[MAXKTCREALMLEN];
2044 char name[MAXKTCNAMELEN];
2045 char inst[MAXKTCNAMELEN];
2050 tconn = rx_ConnectionOf(acall);
2051 code = rx_SecurityClassOf(tconn);
2052 if (code == RX_SECIDX_NULL)
2054 else if (code == RX_SECIDX_VAB) {
2055 goto done; /* no longer supported */
2056 } else if (code == RX_SECIDX_KAD) {
2057 if ((code = rxkad_GetServerInfo(rx_ConnectionOf(acall), NULL, NULL,
2058 name, inst, tcell, NULL)))
2062 code = afsconf_IsLocalRealmMatch(prdir, &islocal, name, inst, tcell);
2066 strncpy(vname, name, sizeof(vname));
2067 if ((ilen = strlen(inst))) {
2068 if (strlen(vname) + 1 + ilen >= sizeof(vname))
2071 strcat(vname, inst);
2074 if (strlen(vname) + strlen(tcell) + 1 >= sizeof(vname))
2077 strcat(vname, tcell);
2078 lcstring(vname, vname, sizeof(vname));
2079 lookup_id_from_name(at, vname, aid);
2081 strcpy(aname, vname);
2085 if (strcmp(AUTH_SUPERUSER, vname) == 0)
2086 *aid = SYSADMINID; /* special case for the fileserver */
2088 lcstring(vname, vname, sizeof(vname));
2089 code = lookup_id_from_name(at, vname, aid);
2093 /* If we reached here, we don't understand the security class of the
2094 * given call. But if the calling user is RX_ID_SUPERUSER, we can check
2095 * that without even needing to understand the security class. Remember
2096 * to only check for RX_ID_SUPERUSER specifically; we do not use
2097 * SYSADMINID for other admins. */
2099 struct rx_identity *id = NULL;
2100 is_super = afsconf_SuperIdentity(prdir, acall, &id);
2101 if (is_super && id->kind == RX_ID_SUPERUSER) {
2108 rx_identity_free(&id);
2112 if (code && !pr_noAuth)