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 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, afs_int32 *cid);
105 static afs_int32 listMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid, afs_int32 *cid);
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 (oid == ANONYMOUSID)
167 if (!admin && !pr_noAuth)
174 WhoIsThis(struct rx_call *acall, struct ubik_trans *at, afs_int32 *aid)
176 int code = WhoIsThisWithName(acall, at, aid, NULL);
177 if (code == 2 && *aid == ANONYMOUSID)
183 WritePreamble(struct ubik_trans **tt)
191 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, tt);
195 code = ubik_SetLock(*tt, 1, 1, LOCKWRITE);
199 code = read_DbHeader(*tt);
203 ubik_AbortTrans(*tt);
209 ReadPreamble(struct ubik_trans **tt)
217 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, tt);
221 code = ubik_SetLock(*tt, 1, 1, LOCKREAD);
225 code = read_DbHeader(*tt);
229 ubik_AbortTrans(*tt);
235 SPR_INewEntry(struct rx_call *call, char aname[], afs_int32 aid, afs_int32 oid)
238 afs_int32 cid = ANONYMOUSID;
240 code = iNewEntry(call, aname, aid, oid, &cid);
241 osi_auditU(call, PTS_INewEntEvent, code, AUD_ID, aid, AUD_STR, aname,
242 AUD_ID, oid, AUD_END);
243 ViceLog(5, ("PTS_INewEntry: code %d cid %d aid %d aname %s oid %d\n", code, cid, aid, aname, oid));
248 iNewEntry(struct rx_call *call, char aname[], afs_int32 aid, afs_int32 oid,
251 /* used primarily for conversion - not intended to be used as usual means
252 * of entering people into the database. */
253 struct ubik_trans *tt;
260 code = WritePreamble(&tt);
264 code = WhoIsThis(call, tt, cid);
266 ABORT_WITH(tt, PRPERM);
267 admin = IsAMemberOf(tt, *cid, SYSADMINID);
269 /* first verify the id is good */
271 ABORT_WITH(tt, PRPERM);
274 /* only sysadmin can reuse a group id */
275 if (!admin && !pr_noAuth && (aid != ntohl(cheader.maxGroup) - 1))
276 ABORT_WITH(tt, PRPERM);
278 if (FindByID(tt, aid))
279 ABORT_WITH(tt, PRIDEXIST);
281 /* check a few other things */
282 if (!CreateOK(tt, *cid, oid, gflag, admin))
283 ABORT_WITH(tt, PRPERM);
285 code = CreateEntry(tt, aname, &aid, 1, gflag, oid, *cid);
286 if (code != PRSUCCESS)
287 ABORT_WITH(tt, code);
289 /* finally, commit transaction */
290 code = ubik_EndTrans(tt);
298 SPR_NewEntry(struct rx_call *call, char aname[], afs_int32 flag, afs_int32 oid,
302 afs_int32 cid = ANONYMOUSID;
304 code = newEntry(call, aname, flag, oid, aid, &cid);
305 osi_auditU(call, PTS_NewEntEvent, code, AUD_ID, *aid, AUD_STR, aname,
306 AUD_ID, oid, AUD_END);
307 ViceLog(5, ("PTS_NewEntry: code %d cid %d aid %d aname %s oid %d\n", code, cid, *aid, aname, oid));
312 newEntry(struct rx_call *call, char aname[], afs_int32 flag, afs_int32 oid,
313 afs_int32 *aid, afs_int32 *cid)
316 struct ubik_trans *tt;
319 char cname[PR_MAXNAMELEN];
322 code = WritePreamble(&tt);
326 /* this is for cross-cell self registration. It is not added in the
327 * SPR_INewEntry because we want self-registration to only do
328 * automatic id assignment.
330 code = WhoIsThisWithName(call, tt, cid, cname);
331 if (code && code != 2)
332 ABORT_WITH(tt, PRPERM);
333 admin = IsAMemberOf(tt, *cid, SYSADMINID);
334 if (code == 2 /* foreign cell request */) {
337 if (!restricted && (strcmp(aname, cname) == 0)) {
338 /* can't autoregister while providing an owner id */
340 ABORT_WITH(tt, PRPERM);
346 if (!CreateOK(tt, *cid, oid, flag, admin))
347 ABORT_WITH(tt, PRPERM);
349 code = CreateEntry(tt, aname, aid, 0, flag, oid, *cid);
351 * If this was an autoregistration then be sure to audit log
352 * the proper id as the creator.
354 if (foreign && code == 0 && *aid > 0)
356 if (code != PRSUCCESS)
357 ABORT_WITH(tt, code);
359 code = ubik_EndTrans(tt);
368 SPR_WhereIsIt(struct rx_call *call, afs_int32 aid, afs_int32 *apos)
371 afs_int32 cid = ANONYMOUSID;
373 code = whereIsIt(call, aid, apos, &cid);
374 osi_auditU(call, PTS_WheIsItEvent, code, AUD_ID, aid, AUD_LONG, *apos,
376 ViceLog(125, ("PTS_WhereIsIt: code %d cid %d aid %d apos %d\n", code, cid, aid, *apos));
381 whereIsIt(struct rx_call *call, afs_int32 aid, afs_int32 *apos, afs_int32 *cid)
384 struct ubik_trans *tt;
387 code = ReadPreamble(&tt);
391 code = WhoIsThis(call, tt, cid);
393 ABORT_WITH(tt, PRPERM);
394 if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID)
395 ABORT_WITH(tt, PRPERM);
397 temp = FindByID(tt, aid);
399 ABORT_WITH(tt, PRNOENT);
401 code = ubik_EndTrans(tt);
409 SPR_DumpEntry(struct rx_call *call, afs_int32 apos,
410 struct prdebugentry *aentry)
413 afs_int32 cid = ANONYMOUSID;
415 code = dumpEntry(call, apos, aentry, &cid);
416 osi_auditU(call, PTS_DmpEntEvent, code, AUD_LONG, apos, AUD_END);
417 ViceLog(125, ("PTS_DumpEntry: code %d cid %d apos %d\n", code, cid, apos));
422 dumpEntry(struct rx_call *call, afs_int32 apos, struct prdebugentry *aentry,
426 struct ubik_trans *tt;
428 code = ReadPreamble(&tt);
432 code = WhoIsThis(call, tt, cid);
434 ABORT_WITH(tt, PRPERM);
435 code = pr_ReadEntry(tt, 0, apos, (struct prentry *)aentry);
437 ABORT_WITH(tt, code);
439 if (!AccessOK(tt, *cid, 0, PRP_STATUS_MEM, 0))
440 ABORT_WITH(tt, PRPERM);
442 /* Since prdebugentry is in the form of a prentry not a coentry, we will
443 * return the coentry slots in network order where the string is. */
445 if (aentry->flags & PRCONT) { /* wrong type, get coentry instead */
446 code = pr_ReadCoEntry(tt, 0, apos, aentry);
448 ABORT_WITH(tt, code);
451 code = ubik_EndTrans(tt);
458 SPR_AddToGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid)
461 afs_int32 cid = ANONYMOUSID;
463 code = addToGroup(call, aid, gid, &cid);
464 osi_auditU(call, PTS_AdToGrpEvent, code, AUD_ID, gid, AUD_ID, aid,
466 ViceLog(5, ("PTS_AddToGroup: code %d cid %d gid %d aid %d\n", code, cid, gid, aid));
471 addToGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid, afs_int32 *cid)
474 struct ubik_trans *tt;
477 struct prentry tentry;
478 struct prentry uentry;
480 if (gid == ANYUSERID || gid == AUTHUSERID)
482 if (aid == ANONYMOUSID)
485 code = WritePreamble(&tt);
489 code = WhoIsThis(call, tt, cid);
491 ABORT_WITH(tt, PRPERM);
492 tempu = FindByID(tt, aid);
494 ABORT_WITH(tt, PRNOENT);
495 memset(&uentry, 0, sizeof(uentry));
496 code = pr_ReadEntry(tt, 0, tempu, &uentry);
498 ABORT_WITH(tt, code);
500 #if !defined(SUPERGROUPS)
501 /* we don't allow groups as members of groups at present */
502 if (uentry.flags & PRGRP)
503 ABORT_WITH(tt, PRNOTUSER);
506 tempg = FindByID(tt, gid);
508 ABORT_WITH(tt, PRNOENT);
509 code = pr_ReadEntry(tt, 0, tempg, &tentry);
511 ABORT_WITH(tt, code);
512 /* make sure that this is a group */
513 if (!(tentry.flags & PRGRP))
514 ABORT_WITH(tt, PRNOTGROUP);
515 if (!AccessOK(tt, *cid, &tentry, PRP_ADD_MEM, PRP_ADD_ANY))
516 ABORT_WITH(tt, PRPERM);
518 code = AddToEntry(tt, &tentry, tempg, aid);
519 if (code != PRSUCCESS)
520 ABORT_WITH(tt, code);
522 #if defined(SUPERGROUPS)
523 if (uentry.flags & PRGRP)
524 code = AddToSGEntry(tt, &uentry, tempu, gid); /* mod group to be in sg */
527 /* now, modify the user's entry as well */
528 code = AddToEntry(tt, &uentry, tempu, gid);
529 if (code != PRSUCCESS)
530 ABORT_WITH(tt, code);
531 code = ubik_EndTrans(tt);
538 SPR_NameToID(struct rx_call *call, namelist *aname, idlist *aid)
542 code = nameToID(call, aname, aid);
543 osi_auditU(call, PTS_NmToIdEvent, code, AUD_END);
544 ViceLog(125, ("PTS_NameToID: code %d\n", code));
549 nameToID(struct rx_call *call, namelist *aname, idlist *aid)
552 struct ubik_trans *tt;
557 /* Initialize return struct */
559 aid->idlist_val = NULL;
561 size = aname->namelist_len;
567 aid->idlist_val = malloc(size * sizeof(afs_int32));
568 if (!aid->idlist_val)
571 code = ReadPreamble(&tt);
575 for (i = 0; i < aname->namelist_len; i++) {
577 char *nameinst, *cell;
578 afs_int32 islocal = 1;
580 strncpy(vname, aname->namelist_val[i], sizeof(vname));
581 vname[sizeof(vname)-1] ='\0';
584 cell = strchr(vname, '@');
591 code = afsconf_IsLocalRealmMatch(prdir, &islocal, nameinst, NULL, cell);
593 ("PTS_NameToID: afsconf_IsLocalRealmMatch(); code=%d, nameinst=%s, cell=%s\n",
594 code, nameinst, cell));
597 code = NameToID(tt, nameinst, &aid->idlist_val[i]);
599 code = NameToID(tt, aname->namelist_val[i], &aid->idlist_val[i]);
601 if (code != PRSUCCESS)
602 aid->idlist_val[i] = ANONYMOUSID;
603 osi_audit(PTS_NmToIdEvent, code, AUD_STR,
604 aname->namelist_val[i], AUD_ID, aid->idlist_val[i],
606 ViceLog(125, ("PTS_NameToID: code %d aname %s aid %d\n", code,
607 aname->namelist_val[i], aid->idlist_val[i]));
609 #ifndef AFS_PTHREAD_ENV
615 aid->idlist_len = aname->namelist_len;
617 code = ubik_EndTrans(tt);
625 * Given an array of ids, find the name for each of them.
626 * The array of ids and names is unlimited.
629 SPR_IDToName(struct rx_call *call, idlist *aid, namelist *aname)
632 afs_int32 cid = ANONYMOUSID;
634 code = idToName(call, aid, aname, &cid);
635 osi_auditU(call, PTS_IdToNmEvent, code, AUD_END);
636 ViceLog(125, ("PTS_IDToName: code %d\n", code));
641 idToName(struct rx_call *call, idlist *aid, namelist *aname, afs_int32 *cid)
644 struct ubik_trans *tt;
649 /* leave this first for rpc stub */
650 size = aid->idlist_len;
653 if (size < 0 || size > INT_MAX / PR_MAXNAMELEN)
655 aname->namelist_val = calloc(size, PR_MAXNAMELEN);
656 aname->namelist_len = 0;
657 if (aname->namelist_val == 0)
659 if (aid->idlist_len == 0)
662 return PRTOOMANY; /* rxgen will probably handle this */
664 code = ReadPreamble(&tt);
668 code = WhoIsThis(call, tt, cid);
670 ABORT_WITH(tt, PRPERM);
671 if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID)
672 ABORT_WITH(tt, PRPERM);
674 for (i = 0; i < aid->idlist_len; i++) {
675 code = IDToName(tt, aid->idlist_val[i], aname->namelist_val[i]);
676 if (code != PRSUCCESS)
677 sprintf(aname->namelist_val[i], "%d", aid->idlist_val[i]);
678 osi_audit(PTS_IdToNmEvent, code, AUD_ID, aid->idlist_val[i],
679 AUD_STR, aname->namelist_val[i], AUD_END);
680 ViceLog(125, ("PTS_idToName: code %d aid %d aname %s\n", code,
681 aid->idlist_val[i], aname->namelist_val[i]));
683 #ifndef AFS_PTHREAD_ENV
689 aname->namelist_len = aid->idlist_len;
691 code = ubik_EndTrans(tt);
698 SPR_Delete(struct rx_call *call, afs_int32 aid)
701 afs_int32 cid = ANONYMOUSID;
703 code = Delete(call, aid, &cid);
704 osi_auditU(call, PTS_DelEvent, code, AUD_ID, aid, AUD_END);
705 ViceLog(5, ("PTS_Delete: code %d cid %d aid %d\n", code, cid, aid));
710 Delete(struct rx_call *call, afs_int32 aid, afs_int32 *cid)
713 struct ubik_trans *tt;
714 struct prentry tentry;
718 if (aid == SYSADMINID || aid == ANYUSERID || aid == AUTHUSERID
719 || aid == ANONYMOUSID)
722 code = WritePreamble(&tt);
726 code = WhoIsThis(call, tt, cid);
728 ABORT_WITH(tt, PRPERM);
730 /* Read in entry to be deleted */
731 loc = FindByID(tt, aid);
733 ABORT_WITH(tt, PRNOENT);
734 code = pr_ReadEntry(tt, 0, loc, &tentry);
736 ABORT_WITH(tt, PRDBFAIL);
738 /* Do some access checking */
739 if (tentry.owner != *cid && !IsAMemberOf(tt, *cid, SYSADMINID)
740 && !IsAMemberOf(tt, *cid, tentry.owner) && !pr_noAuth)
741 ABORT_WITH(tt, PRPERM);
743 if (restricted && !IsAMemberOf(tt, *cid, SYSADMINID)) {
744 ABORT_WITH(tt, PRPERM);
747 /* Delete each continuation block as a separate transaction so that no one
748 * transaction become to large to complete. */
751 struct contentry centry;
754 code = pr_ReadCoEntry(tt, 0, nptr, ¢ry);
756 ABORT_WITH(tt, PRDBFAIL);
757 for (i = 0; i < COSIZE; i++) {
758 if (centry.entries[i] == PRBADID)
760 if (centry.entries[i] == 0)
762 #if defined(SUPERGROUPS)
763 if (aid < 0 && centry.entries[i] < 0) /* Supergroup */
764 code = RemoveFromSGEntry(tt, aid, centry.entries[i]);
767 code = RemoveFromEntry(tt, aid, centry.entries[i]);
769 ABORT_WITH(tt, code);
770 tentry.count--; /* maintain count */
771 #ifndef AFS_PTHREAD_ENV
776 tentry.next = centry.next; /* thread out this block */
777 code = FreeBlock(tt, nptr); /* free continuation block */
779 ABORT_WITH(tt, code);
780 code = pr_WriteEntry(tt, 0, loc, &tentry); /* update main entry */
782 ABORT_WITH(tt, code);
784 /* end this trans and start a new one */
785 code = ubik_EndTrans(tt);
788 #ifndef AFS_PTHREAD_ENV
789 IOMGR_Poll(); /* just to keep the connection alive */
791 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
794 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
796 ABORT_WITH(tt, code);
798 /* re-read entry to get consistent uptodate info */
799 loc = FindByID(tt, aid);
801 ABORT_WITH(tt, PRNOENT);
802 code = pr_ReadEntry(tt, 0, loc, &tentry);
804 ABORT_WITH(tt, PRDBFAIL);
809 #if defined(SUPERGROUPS)
810 /* Delete each continuation block as a separate transaction
811 * so that no one transaction become too large to complete. */
813 struct prentryg *tentryg = (struct prentryg *)&tentry;
814 nptr = tentryg->nextsg;
816 struct contentry centry;
819 code = pr_ReadCoEntry(tt, 0, nptr, ¢ry);
821 ABORT_WITH(tt, PRDBFAIL);
822 for (i = 0; i < COSIZE; i++) {
823 if (centry.entries[i] == PRBADID)
825 if (centry.entries[i] == 0)
827 code = RemoveFromEntry(tt, aid, centry.entries[i]);
829 ABORT_WITH(tt, code);
830 tentryg->countsg--; /* maintain count */
831 #ifndef AFS_PTHREAD_ENV
836 tentryg->nextsg = centry.next; /* thread out this block */
837 code = FreeBlock(tt, nptr); /* free continuation block */
839 ABORT_WITH(tt, code);
840 code = pr_WriteEntry(tt, 0, loc, &tentry); /* update main entry */
842 ABORT_WITH(tt, code);
844 /* end this trans and start a new one */
845 code = ubik_EndTrans(tt);
848 #ifndef AFS_PTHREAD_ENV
849 IOMGR_Poll(); /* just to keep the connection alive */
852 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
855 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
857 ABORT_WITH(tt, code);
859 /* re-read entry to get consistent uptodate info */
860 loc = FindByID(tt, aid);
862 ABORT_WITH(tt, PRNOENT);
863 code = pr_ReadEntry(tt, 0, loc, &tentry);
865 ABORT_WITH(tt, PRDBFAIL);
867 nptr = tentryg->nextsg;
871 #endif /* SUPERGROUPS */
873 /* Then move the owned chain, except possibly ourself to the orphan list.
874 * Because this list can be very long and so exceed the size of a ubik
875 * transaction, we start a new transaction every 50 entries. */
879 struct prentry nentry;
881 code = pr_ReadEntry(tt, 0, nptr, &nentry);
883 ABORT_WITH(tt, PRDBFAIL);
884 nptr = tentry.owned = nentry.nextOwned; /* thread out */
886 if (nentry.id != tentry.id) { /* don't add us to orphan chain! */
887 code = AddToOrphan(tt, nentry.id);
889 ABORT_WITH(tt, code);
891 #ifndef AFS_PTHREAD_ENV
892 if ((count & 3) == 0)
898 code = pr_WriteEntry(tt, 0, loc, &tentry); /* update main entry */
900 ABORT_WITH(tt, code);
902 /* end this trans and start a new one */
903 code = ubik_EndTrans(tt);
906 #ifndef AFS_PTHREAD_ENV
907 IOMGR_Poll(); /* just to keep the connection alive */
909 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
912 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
914 ABORT_WITH(tt, code);
916 /* re-read entry to get consistent uptodate info */
917 loc = FindByID(tt, aid);
919 ABORT_WITH(tt, PRNOENT);
920 code = pr_ReadEntry(tt, 0, loc, &tentry);
922 ABORT_WITH(tt, PRDBFAIL);
927 /* now do what's left of the deletion stuff */
928 code = DeleteEntry(tt, &tentry, loc);
929 if (code != PRSUCCESS)
930 ABORT_WITH(tt, code);
932 code = ubik_EndTrans(tt);
939 SPR_UpdateEntry(struct rx_call *call, afs_int32 aid, char *name,
940 struct PrUpdateEntry *uentry)
943 afs_int32 cid = ANONYMOUSID;
945 code = UpdateEntry(call, aid, name, uentry, &cid);
946 osi_auditU(call, PTS_UpdEntEvent, code, AUD_ID, aid, AUD_STR, name, AUD_END);
947 ViceLog(5, ("PTS_UpdateEntry: code %d cid %d aid %d name %s\n", code, cid, aid, name));
952 UpdateEntry(struct rx_call *call, afs_int32 aid, char *name,
953 struct PrUpdateEntry *uentry, afs_int32 *cid)
956 struct ubik_trans *tt;
957 struct prentry tentry;
963 if (aid == SYSADMINID || aid == ANYUSERID || aid == AUTHUSERID
964 || aid == ANONYMOUSID)
968 code = WritePreamble(&tt);
972 code = WhoIsThis(call, tt, cid);
974 ABORT_WITH(tt, PRPERM);
975 code = IsAMemberOf(tt, *cid, SYSADMINID);
976 if (!code && !pr_noAuth)
977 ABORT_WITH(tt, PRPERM);
979 /* Read in entry to be deleted */
981 loc = FindByID(tt, aid);
983 loc = FindByName(tt, name, &tentry);
986 ABORT_WITH(tt, PRNOENT);
987 code = pr_ReadEntry(tt, 0, loc, &tentry);
989 ABORT_WITH(tt, PRDBFAIL);
991 if (uentry->Mask & PRUPDATE_NAMEHASH) {
993 code = RemoveFromNameHash(tt, tentry.name, &tloc);
994 if (code != PRSUCCESS)
995 ABORT_WITH(tt, PRDBFAIL);
996 code = AddToNameHash(tt, tentry.name, loc);
998 ABORT_WITH(tt, code);
1001 if (uentry->Mask & PRUPDATE_IDHASH) {
1005 code = RemoveFromIDHash(tt, id, &tloc);
1006 if (code != PRSUCCESS)
1007 ABORT_WITH(tt, PRDBFAIL);
1008 code = AddToIDHash(tt, id, loc);
1010 ABORT_WITH(tt, code);
1013 code = ubik_EndTrans(tt);
1020 SPR_RemoveFromGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid)
1023 afs_int32 cid = ANONYMOUSID;
1025 code = removeFromGroup(call, aid, gid, &cid);
1026 osi_auditU(call, PTS_RmFmGrpEvent, code, AUD_ID, gid, AUD_ID, aid,
1028 ViceLog(5, ("PTS_RemoveFromGroup: code %d cid %d gid %d aid %d\n", code, cid, gid, aid));
1033 removeFromGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid,
1037 struct ubik_trans *tt;
1040 struct prentry uentry;
1041 struct prentry gentry;
1043 code = WritePreamble(&tt);
1047 code = WhoIsThis(call, tt, cid);
1049 ABORT_WITH(tt, PRPERM);
1050 tempu = FindByID(tt, aid);
1052 ABORT_WITH(tt, PRNOENT);
1053 tempg = FindByID(tt, gid);
1055 ABORT_WITH(tt, PRNOENT);
1056 memset(&uentry, 0, sizeof(uentry));
1057 memset(&gentry, 0, sizeof(gentry));
1058 code = pr_ReadEntry(tt, 0, tempu, &uentry);
1060 ABORT_WITH(tt, code);
1061 code = pr_ReadEntry(tt, 0, tempg, &gentry);
1063 ABORT_WITH(tt, code);
1064 if (!(gentry.flags & PRGRP))
1065 ABORT_WITH(tt, PRNOTGROUP);
1066 #if !defined(SUPERGROUPS)
1067 if (uentry.flags & PRGRP)
1068 ABORT_WITH(tt, PRNOTUSER);
1070 if (!AccessOK(tt, *cid, &gentry, PRP_REMOVE_MEM, 0))
1071 ABORT_WITH(tt, PRPERM);
1072 code = RemoveFromEntry(tt, aid, gid);
1073 if (code != PRSUCCESS)
1074 ABORT_WITH(tt, code);
1075 #if defined(SUPERGROUPS)
1076 if (!(uentry.flags & PRGRP))
1078 code = RemoveFromEntry(tt, gid, aid);
1079 #if defined(SUPERGROUPS)
1081 code = RemoveFromSGEntry(tt, gid, aid);
1083 if (code != PRSUCCESS)
1084 ABORT_WITH(tt, code);
1086 code = ubik_EndTrans(tt);
1094 SPR_GetCPS(struct rx_call *call, afs_int32 aid, prlist *alist, afs_int32 *over)
1097 afs_int32 cid = ANONYMOUSID;
1099 code = getCPS(call, aid, alist, over, &cid);
1100 osi_auditU(call, PTS_GetCPSEvent, code, AUD_ID, aid, AUD_END);
1101 ViceLog(125, ("PTS_GetCPS: code %d cid %d aid %d\n", code, cid, aid));
1106 getCPS(struct rx_call *call, afs_int32 aid, prlist *alist, afs_int32 *over,
1110 struct ubik_trans *tt;
1112 struct prentry tentry;
1115 alist->prlist_len = 0;
1116 alist->prlist_val = NULL;
1118 code = ReadPreamble(&tt);
1122 code = WhoIsThis(call, tt, cid);
1124 ABORT_WITH(tt, PRPERM);
1125 if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID)
1126 ABORT_WITH(tt, PRPERM);
1128 temp = FindByID(tt, aid);
1130 ABORT_WITH(tt, PRNOENT);
1131 code = pr_ReadEntry(tt, 0, temp, &tentry);
1133 ABORT_WITH(tt, code);
1135 if (!AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1136 ABORT_WITH(tt, PRPERM);
1138 code = GetList(tt, &tentry, alist, 1);
1139 if (code != PRSUCCESS)
1140 ABORT_WITH(tt, code);
1142 code = ubik_EndTrans(tt);
1148 inCPS(prlist CPS, afs_int32 id)
1152 for (i = (CPS.prlist_len - 1); i >= 0; i--) {
1153 if (CPS.prlist_val[i] == id)
1161 SPR_GetCPS2(struct rx_call *call, afs_int32 aid, afs_int32 ahost,
1162 prlist *alist, afs_int32 *over)
1165 afs_int32 cid = ANONYMOUSID;
1167 code = getCPS2(call, aid, ahost, alist, over, &cid);
1168 osi_auditU(call, PTS_GetCPS2Event, code, AUD_ID, aid, AUD_HOST, htonl(ahost),
1170 ViceLog(125, ("PTS_GetCPS2: code %d cid %d aid %d ahost %d\n", code, cid, aid, ahost));
1175 getCPS2(struct rx_call *call, afs_int32 aid, afs_uint32 ahost, prlist *alist,
1176 afs_int32 *over, afs_int32 *cid)
1179 struct ubik_trans *tt;
1181 struct prentry tentry;
1182 struct prentry host_tentry;
1185 struct in_addr iaddr;
1189 iaddr.s_addr = ntohl(ahost);
1190 alist->prlist_len = 0;
1191 alist->prlist_val = NULL;
1193 code = ReadPreamble(&tt);
1197 if (aid != PRBADID) {
1198 temp = FindByID(tt, aid);
1200 ABORT_WITH(tt, PRNOENT);
1201 code = pr_ReadEntry(tt, 0, temp, &tentry);
1203 ABORT_WITH(tt, code);
1205 /* afs does authenticate now */
1206 code = WhoIsThis(call, tt, cid);
1208 || !AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1209 ABORT_WITH(tt, PRPERM);
1211 code = NameToID(tt, afs_inet_ntoa_r(iaddr.s_addr, hoststr), &hostid);
1212 if (code == PRSUCCESS && hostid != 0) {
1213 temp = FindByID(tt, hostid);
1215 code = pr_ReadEntry(tt, 0, temp, &host_tentry);
1216 if (code == PRSUCCESS)
1219 fprintf(stderr, "pr_ReadEntry returned %d\n", code);
1221 fprintf(stderr, "FindByID Failed -- Not found\n");
1224 code = GetList2(tt, &tentry, &host_tentry, alist, 1);
1226 code = GetList(tt, &tentry, alist, 1);
1228 code = addWildCards(tt, alist, ntohl(ahost));
1229 if (code != PRSUCCESS)
1230 ABORT_WITH(tt, code);
1232 code = ubik_EndTrans(tt);
1238 SPR_GetHostCPS(struct rx_call *call, afs_int32 ahost, prlist *alist,
1242 afs_int32 cid = ANONYMOUSID;
1244 code = getHostCPS(call, ahost, alist, over, &cid);
1245 osi_auditU(call, PTS_GetHCPSEvent, code, AUD_HOST, htonl(ahost), AUD_END);
1246 ViceLog(125, ("PTS_GetHostCPS: code %d ahost %u (0x%x)\n", code, ahost, ahost));
1251 getHostCPS(struct rx_call *call, afs_uint32 ahost, prlist *alist,
1252 afs_int32 *over, afs_int32 *cid)
1254 afs_int32 code, temp;
1255 struct ubik_trans *tt;
1256 struct prentry host_tentry;
1258 struct in_addr iaddr;
1262 iaddr.s_addr = ntohl(ahost);
1263 alist->prlist_len = 0;
1264 alist->prlist_val = NULL;
1266 code = ReadPreamble(&tt);
1270 code = WhoIsThis(call, tt, cid);
1272 ABORT_WITH(tt, PRPERM);
1273 if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID)
1274 ABORT_WITH(tt, PRPERM);
1276 code = NameToID(tt, afs_inet_ntoa_r(iaddr.s_addr, hoststr), &hostid);
1277 if (code == PRSUCCESS && hostid != 0) {
1278 temp = FindByID(tt, hostid);
1280 code = pr_ReadEntry(tt, 0, temp, &host_tentry);
1281 if (code == PRSUCCESS) {
1282 code = GetList(tt, &host_tentry, alist, 0);
1286 fprintf(stderr, "pr_ReadEntry returned %d\n", code);
1288 fprintf(stderr, "FindByID Failed -- Not found\n");
1290 code = addWildCards(tt, alist, ntohl(ahost));
1292 if (code != PRSUCCESS)
1293 ABORT_WITH(tt, code);
1295 code = ubik_EndTrans(tt);
1301 SPR_ListMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid)
1304 afs_int32 cid = ANONYMOUSID;
1306 code = listMax(call, uid, gid, &cid);
1307 osi_auditU(call, PTS_LstMaxEvent, code, AUD_END);
1308 ViceLog(125, ("PTS_ListMax: code %d\n", code));
1313 listMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid, afs_int32 *cid)
1316 struct ubik_trans *tt;
1318 code = ReadPreamble(&tt);
1322 code = WhoIsThis(call, tt, cid);
1324 ABORT_WITH(tt, PRPERM);
1325 if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID)
1326 ABORT_WITH(tt, PRPERM);
1328 code = GetMax(tt, uid, gid);
1329 if (code != PRSUCCESS)
1330 ABORT_WITH(tt, code);
1332 code = ubik_EndTrans(tt);
1339 SPR_SetMax(struct rx_call *call, afs_int32 aid, afs_int32 gflag)
1342 afs_int32 cid = ANONYMOUSID;
1344 code = setMax(call, aid, gflag, &cid);
1345 osi_auditU(call, PTS_SetMaxEvent, code, AUD_ID, aid, AUD_LONG, gflag,
1347 ViceLog(125, ("PTS_SetMax: code %d cid %d aid %d gflag %d\n", code, cid, aid, gflag));
1352 setMax(struct rx_call *call, afs_int32 aid, afs_int32 gflag, afs_int32 *cid)
1355 struct ubik_trans *tt;
1357 code = WritePreamble(&tt);
1361 code = WhoIsThis(call, tt, cid);
1363 ABORT_WITH(tt, PRPERM);
1364 if (!AccessOK(tt, *cid, 0, 0, 0))
1365 ABORT_WITH(tt, PRPERM);
1366 if (((gflag & PRGRP) && (aid > 0)) || (!(gflag & PRGRP) && (aid < 0)))
1367 ABORT_WITH(tt, PRBADARG);
1369 code = SetMax(tt, aid, gflag);
1370 if (code != PRSUCCESS)
1371 ABORT_WITH(tt, code);
1373 code = ubik_EndTrans(tt);
1380 SPR_ListEntry(struct rx_call *call, afs_int32 aid, struct prcheckentry *aentry)
1383 afs_int32 cid = ANONYMOUSID;
1385 code = listEntry(call, aid, aentry, &cid);
1386 osi_auditU(call, PTS_LstEntEvent, code, AUD_ID, aid, AUD_END);
1387 ViceLog(125, ("PTS_ListEntry: code %d cid %d aid %d\n", code, cid, aid));
1392 listEntry(struct rx_call *call, afs_int32 aid, struct prcheckentry *aentry,
1396 struct ubik_trans *tt;
1398 struct prentry tentry;
1400 code = ReadPreamble(&tt);
1404 code = WhoIsThis(call, tt, cid);
1406 ABORT_WITH(tt, PRPERM);
1407 if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID)
1408 ABORT_WITH(tt, PRPERM);
1409 temp = FindByID(tt, aid);
1411 ABORT_WITH(tt, PRNOENT);
1412 code = pr_ReadEntry(tt, 0, temp, &tentry);
1414 ABORT_WITH(tt, code);
1415 if (!AccessOK(tt, *cid, &tentry, PRP_STATUS_MEM, PRP_STATUS_ANY))
1416 ABORT_WITH(tt, PRPERM);
1418 aentry->flags = tentry.flags >> PRIVATE_SHIFT;
1419 if (aentry->flags == 0) {
1420 if (tentry.flags & PRGRP)
1421 aentry->flags = prp_group_default >> PRIVATE_SHIFT;
1423 aentry->flags = prp_user_default >> PRIVATE_SHIFT;
1425 aentry->owner = tentry.owner;
1426 aentry->id = tentry.id;
1427 strncpy(aentry->name, tentry.name, PR_MAXNAMELEN);
1428 aentry->creator = tentry.creator;
1429 aentry->ngroups = tentry.ngroups;
1430 aentry->nusers = tentry.nusers;
1431 aentry->count = tentry.count;
1432 memset(aentry->reserved, 0, sizeof(aentry->reserved));
1433 code = ubik_EndTrans(tt);
1440 SPR_ListEntries(struct rx_call *call, afs_int32 flag, afs_int32 startindex,
1441 prentries *bulkentries, afs_int32 *nextstartindex)
1444 afs_int32 cid = ANONYMOUSID;
1446 code = listEntries(call, flag, startindex, bulkentries, nextstartindex, &cid);
1447 osi_auditU(call, PTS_LstEntsEvent, code, AUD_LONG, flag, AUD_END);
1448 ViceLog(125, ("PTS_ListEntries: code %d cid %d flag %d\n", code, cid, flag));
1453 listEntries(struct rx_call *call, afs_int32 flag, afs_int32 startindex,
1454 prentries *bulkentries, afs_int32 *nextstartindex, afs_int32 *cid)
1457 struct ubik_trans *tt;
1458 afs_int32 i, eof, pos, maxentries, f;
1459 struct prentry tentry;
1460 afs_int32 pollcount = 0;
1462 *nextstartindex = -1;
1463 bulkentries->prentries_val = 0;
1464 bulkentries->prentries_len = 0;
1466 code = ReadPreamble(&tt);
1470 /* Make sure we are an authenticated caller and that we are on the
1473 code = WhoIsThis(call, tt, cid);
1475 ABORT_WITH(tt, PRPERM);
1476 code = IsAMemberOf(tt, *cid, SYSADMINID);
1477 if (!code && !pr_noAuth)
1478 ABORT_WITH(tt, PRPERM);
1480 eof = ntohl(cheader.eofPtr) - sizeof(cheader);
1481 maxentries = eof / sizeof(struct prentry);
1482 for (i = startindex; i < maxentries; i++) {
1483 pos = i * sizeof(struct prentry) + sizeof(cheader);
1484 code = pr_ReadEntry(tt, 0, pos, &tentry);
1488 if (++pollcount > 50) {
1489 #ifndef AFS_PTHREAD_ENV
1495 f = (tentry.flags & PRTYPE);
1496 if (((flag & PRUSERS) && (f == 0)) || /* User entry */
1497 ((flag & PRGROUPS) && (f & PRGRP))) { /* Group entry */
1498 code = put_prentries(&tentry, bulkentries);
1500 break; /* Filled return array */
1507 *nextstartindex = i;
1511 if (bulkentries->prentries_val)
1512 free(bulkentries->prentries_val);
1513 bulkentries->prentries_val = 0;
1514 bulkentries->prentries_len = 0;
1515 ABORT_WITH(tt, code);
1517 code = ubik_EndTrans(tt);
1524 #define PR_MAXENTRIES 500
1526 put_prentries(struct prentry *tentry, prentries *bulkentries)
1528 struct prlistentries *entry;
1530 if (bulkentries->prentries_val == 0) {
1531 bulkentries->prentries_len = 0;
1532 bulkentries->prentries_val = malloc(PR_MAXENTRIES *
1533 sizeof(struct prlistentries));
1534 if (!bulkentries->prentries_val) {
1539 if (bulkentries->prentries_len >= PR_MAXENTRIES) {
1543 entry = bulkentries->prentries_val;
1544 entry += bulkentries->prentries_len;
1546 memset(entry, 0, sizeof(*entry));
1547 entry->flags = tentry->flags >> PRIVATE_SHIFT;
1548 if (entry->flags == 0) {
1551 flags & PRGRP) ? prp_group_default : prp_user_default) >>
1554 entry->owner = tentry->owner;
1555 entry->id = tentry->id;
1556 entry->creator = tentry->creator;
1557 entry->ngroups = tentry->ngroups;
1558 entry->nusers = tentry->nusers;
1559 entry->count = tentry->count;
1560 strncpy(entry->name, tentry->name, PR_MAXNAMELEN);
1561 bulkentries->prentries_len++;
1566 SPR_ChangeEntry(struct rx_call *call, afs_int32 aid, char *name, afs_int32 oid,
1570 afs_int32 cid = ANONYMOUSID;
1572 code = changeEntry(call, aid, name, oid, newid, &cid);
1573 osi_auditU(call, PTS_ChgEntEvent, code, AUD_ID, aid, AUD_STR, name,
1574 AUD_LONG, oid, AUD_LONG, newid, AUD_END);
1575 ViceLog(5, ("PTS_ChangeEntry: code %d cid %d aid %d name %s oid %d newid %d\n", code, cid, aid, name, oid, newid));
1580 changeEntry(struct rx_call *call, afs_int32 aid, char *name, afs_int32 oid,
1581 afs_int32 newid, afs_int32 *cid)
1584 struct ubik_trans *tt;
1591 if (aid == ANYUSERID || aid == AUTHUSERID || aid == ANONYMOUSID
1592 || aid == SYSADMINID)
1595 code = WritePreamble(&tt);
1599 code = WhoIsThis(call, tt, cid);
1601 ABORT_WITH(tt, PRPERM);
1602 pos = FindByID(tt, aid);
1604 ABORT_WITH(tt, PRNOENT);
1605 /* protection check in changeentry */
1606 code = ChangeEntry(tt, aid, *cid, name, oid, newid);
1607 if (code != PRSUCCESS)
1608 ABORT_WITH(tt, code);
1610 code = ubik_EndTrans(tt);
1615 SPR_SetFieldsEntry(struct rx_call *call,
1617 afs_int32 mask, /* specify which fields to update */
1618 afs_int32 flags, afs_int32 ngroups, afs_int32 nusers,
1619 afs_int32 spare1, afs_int32 spare2)
1622 afs_int32 cid = ANONYMOUSID;
1625 setFieldsEntry(call, id, mask, flags, ngroups, nusers, spare1,
1627 osi_auditU(call, PTS_SetFldEntEvent, code, AUD_ID, id, AUD_END);
1628 ViceLog(5, ("PTS_SetFieldsEntry: code %d cid %d id %d\n", code, cid, id));
1633 setFieldsEntry(struct rx_call *call,
1635 afs_int32 mask, /* specify which fields to update */
1636 afs_int32 flags, afs_int32 ngroups, afs_int32 nusers,
1637 afs_int32 spare1, afs_int32 spare2, afs_int32 *cid)
1640 struct ubik_trans *tt;
1642 struct prentry tentry;
1646 return 0; /* no-op */
1648 if (id == ANYUSERID || id == AUTHUSERID || id == ANONYMOUSID)
1651 code = WritePreamble(&tt);
1655 code = WhoIsThis(call, tt, cid);
1657 ABORT_WITH(tt, PRPERM);
1658 pos = FindByID(tt, id);
1660 ABORT_WITH(tt, PRNOENT);
1661 code = pr_ReadEntry(tt, 0, pos, &tentry);
1663 ABORT_WITH(tt, code);
1664 tflags = tentry.flags;
1666 if (mask & (PR_SF_NGROUPS | PR_SF_NUSERS)) {
1667 if (!AccessOK(tt, *cid, 0, 0, 0))
1668 ABORT_WITH(tt, PRPERM);
1669 if ((tflags & PRQUOTA) == 0) { /* default if only setting one */
1670 tentry.ngroups = tentry.nusers = 20;
1673 if (!AccessOK(tt, *cid, &tentry, 0, 0))
1674 ABORT_WITH(tt, PRPERM);
1677 if (mask & 0xffff) { /* if setting flag bits */
1678 afs_int32 flagsMask = mask & 0xffff;
1679 tflags &= ~(flagsMask << PRIVATE_SHIFT);
1680 tflags |= (flags & flagsMask) << PRIVATE_SHIFT;
1684 if (mask & PR_SF_NGROUPS) { /* setting group limit */
1686 ABORT_WITH(tt, PRBADARG);
1687 tentry.ngroups = ngroups;
1691 if (mask & PR_SF_NUSERS) { /* setting foreign user limit */
1693 ABORT_WITH(tt, PRBADARG);
1694 tentry.nusers = nusers;
1697 tentry.flags = tflags;
1699 code = pr_WriteEntry(tt, 0, pos, &tentry);
1701 ABORT_WITH(tt, code);
1703 code = ubik_EndTrans(tt);
1708 SPR_ListElements(struct rx_call *call, afs_int32 aid, prlist *alist,
1712 afs_int32 cid = ANONYMOUSID;
1714 code = listElements(call, aid, alist, over, &cid);
1715 osi_auditU(call, PTS_LstEleEvent, code, AUD_ID, aid, AUD_END);
1716 ViceLog(125, ("PTS_ListElements: code %d cid %d aid %d\n", code, cid, aid));
1721 listElements(struct rx_call *call, afs_int32 aid, prlist *alist,
1722 afs_int32 *over, afs_int32 *cid)
1725 struct ubik_trans *tt;
1727 struct prentry tentry;
1730 alist->prlist_len = 0;
1731 alist->prlist_val = NULL;
1733 code = ReadPreamble(&tt);
1737 code = WhoIsThis(call, tt, cid);
1739 ABORT_WITH(tt, PRPERM);
1741 temp = FindByID(tt, aid);
1743 ABORT_WITH(tt, PRNOENT);
1744 code = pr_ReadEntry(tt, 0, temp, &tentry);
1746 ABORT_WITH(tt, code);
1747 if (!AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1748 ABORT_WITH(tt, PRPERM);
1750 code = GetList(tt, &tentry, alist, 0);
1751 if (code != PRSUCCESS)
1752 ABORT_WITH(tt, code);
1754 code = ubik_EndTrans(tt);
1760 SPR_ListSuperGroups(struct rx_call *call, afs_int32 aid, prlist *alist,
1763 #if defined(SUPERGROUPS)
1765 afs_int32 cid = ANONYMOUSID;
1767 code = listSuperGroups(call, aid, alist, over, &cid);
1768 osi_auditU(call, PTS_LstSGrps, code, AUD_ID, aid, AUD_END);
1769 ViceLog(125, ("PTS_ListSuperGroups: code %d cid %d aid %d\n", code, cid, aid));
1772 return RXGEN_OPCODE;
1776 #if defined(SUPERGROUPS)
1778 listSuperGroups(struct rx_call *call, afs_int32 aid, prlist *alist,
1779 afs_int32 *over, afs_int32 *cid)
1782 struct ubik_trans *tt;
1784 struct prentry tentry;
1786 alist->prlist_len = 0;
1787 alist->prlist_val = (afs_int32 *) 0;
1789 code = ReadPreamble(&tt);
1793 code = WhoIsThis(call, tt, cid);
1795 ABORT_WITH(tt, PRPERM);
1796 if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID)
1797 ABORT_WITH(tt, PRPERM);
1799 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1801 ABORT_WITH(tt, code);
1803 temp = FindByID(tt, aid);
1805 ABORT_WITH(tt, PRNOENT);
1806 code = pr_ReadEntry(tt, 0, temp, &tentry);
1808 ABORT_WITH(tt, code);
1809 if (!AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1810 ABORT_WITH(tt, PRPERM);
1812 code = GetSGList(tt, &tentry, alist);
1814 if (code == PRTOOMANY)
1816 else if (code != PRSUCCESS)
1817 ABORT_WITH(tt, code);
1819 code = ubik_EndTrans(tt);
1824 #endif /* SUPERGROUPS */
1828 * List the entries owned by this id. If the id is zero,
1829 * return the orphans list. This will return up to PR_MAXGROUPS
1830 * at a time with the lastP available to get the rest. The
1831 * maximum value is enforced in GetOwnedChain().
1834 SPR_ListOwned(struct rx_call *call, afs_int32 aid, prlist *alist,
1838 afs_int32 cid = ANONYMOUSID;
1840 code = listOwned(call, aid, alist, lastP, &cid);
1841 osi_auditU(call, PTS_LstOwnEvent, code, AUD_ID, aid, AUD_END);
1842 ViceLog(125, ("PTS_ListOwned: code %d cid %d aid %d\n", code, cid, aid));
1847 listOwned(struct rx_call *call, afs_int32 aid, prlist *alist, afs_int32 *lastP,
1851 struct ubik_trans *tt;
1852 struct prentry tentry;
1856 alist->prlist_len = 0;
1857 alist->prlist_val = NULL;
1864 code = ReadPreamble(&tt);
1868 code = WhoIsThis(call, tt, cid);
1870 ABORT_WITH(tt, PRPERM);
1873 code = pr_ReadEntry(tt, 0, start, &tentry);
1874 if (!code && (tentry.owner == aid))
1875 head = start; /* pick up where we left off */
1880 afs_int32 loc = FindByID(tt, aid);
1882 ABORT_WITH(tt, PRNOENT);
1883 code = pr_ReadEntry(tt, 0, loc, &tentry);
1885 ABORT_WITH(tt, code);
1887 if (!AccessOK(tt, *cid, &tentry, -1, PRP_OWNED_ANY))
1888 ABORT_WITH(tt, PRPERM);
1889 head = tentry.owned;
1891 if (!AccessOK(tt, *cid, 0, 0, 0))
1892 ABORT_WITH(tt, PRPERM);
1893 head = ntohl(cheader.orphan);
1897 code = GetOwnedChain(tt, &head, alist);
1899 if (code == PRTOOMANY)
1902 ABORT_WITH(tt, code);
1905 code = ubik_EndTrans(tt);
1910 SPR_IsAMemberOf(struct rx_call *call, afs_int32 uid, afs_int32 gid,
1914 afs_int32 cid = ANONYMOUSID;
1916 code = isAMemberOf(call, uid, gid, flag, &cid);
1917 osi_auditU(call, PTS_IsMemOfEvent, code, AUD_LONG, uid, AUD_LONG, gid,
1919 ViceLog(125, ("PTS_IsAMemberOf: code %d cid %d uid %d gid %d\n", code, cid, uid, gid));
1924 isAMemberOf(struct rx_call *call, afs_int32 uid, afs_int32 gid, afs_int32 *flag,
1928 struct ubik_trans *tt;
1930 code = ReadPreamble(&tt);
1935 afs_int32 uloc = FindByID(tt, uid);
1936 afs_int32 gloc = FindByID(tt, gid);
1937 struct prentry uentry, gentry;
1940 ABORT_WITH(tt, PRNOENT);
1941 code = WhoIsThis(call, tt, cid);
1943 ABORT_WITH(tt, PRPERM);
1944 code = pr_ReadEntry(tt, 0, uloc, &uentry);
1946 ABORT_WITH(tt, code);
1947 code = pr_ReadEntry(tt, 0, gloc, &gentry);
1949 ABORT_WITH(tt, code);
1950 #if !defined(SUPERGROUPS)
1951 if ((uentry.flags & PRGRP) || !(gentry.flags & PRGRP))
1952 ABORT_WITH(tt, PRBADARG);
1954 if (!(gentry.flags & PRGRP))
1955 ABORT_WITH(tt, PRBADARG);
1957 if (!AccessOK(tt, *cid, &uentry, 0, PRP_MEMBER_ANY)
1958 && !AccessOK(tt, *cid, &gentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1959 ABORT_WITH(tt, PRPERM);
1962 *flag = IsAMemberOf(tt, uid, gid);
1963 code = ubik_EndTrans(tt);
1968 addWildCards(struct ubik_trans *tt, prlist *alist, afs_uint32 host)
1971 struct prentry tentry;
1973 unsigned wild = htonl(0xffffff00);
1974 struct in_addr iaddr;
1976 int size = 0, i, code;
1980 while ((host = (host & wild))) {
1981 wild = htonl(ntohl(wild) << 8);
1982 iaddr.s_addr = host;
1983 code = NameToID(tt, afs_inet_ntoa_r(iaddr.s_addr, hoststr), &hostid);
1984 if (code == PRSUCCESS && hostid != 0) {
1985 temp = FindByID(tt, hostid);
1987 code = pr_ReadEntry(tt, 0, temp, &tentry);
1988 if (code != PRSUCCESS)
1994 wlist.prlist_len = 0;
1995 wlist.prlist_val = NULL;
1997 code = GetList(tt, &tentry, &wlist, 0);
2000 added += wlist.prlist_len;
2001 for (i = 0; i < wlist.prlist_len; i++) {
2002 if (!inCPS(*alist, wlist.prlist_val[i]))
2003 if ((code = AddToPRList(alist, &size, wlist.prlist_val[i]))) {
2004 free(wlist.prlist_val);
2008 if (wlist.prlist_val)
2009 free(wlist.prlist_val);
2012 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
2017 WhoIsThisWithName(struct rx_call *acall, struct ubik_trans *at, afs_int32 *aid,
2020 afs_int32 islocal = 1;
2021 /* aid is set to the identity of the caller, if known, else ANONYMOUSID */
2022 /* returns -1 and sets aid to ANONYMOUSID on any failure */
2023 struct rx_connection *tconn;
2025 char tcell[MAXKTCREALMLEN];
2026 char name[MAXKTCNAMELEN];
2027 char inst[MAXKTCNAMELEN];
2032 tconn = rx_ConnectionOf(acall);
2033 code = rx_SecurityClassOf(tconn);
2034 if (code == RX_SECIDX_NULL)
2036 else if (code == RX_SECIDX_VAB) {
2037 goto done; /* no longer supported */
2038 } else if (code == RX_SECIDX_KAD) {
2039 if ((code = rxkad_GetServerInfo(rx_ConnectionOf(acall), NULL, NULL,
2040 name, inst, tcell, NULL)))
2044 code = afsconf_IsLocalRealmMatch(prdir, &islocal, name, inst, tcell);
2048 strncpy(vname, name, sizeof(vname));
2049 if ((ilen = strlen(inst))) {
2050 if (strlen(vname) + 1 + ilen >= sizeof(vname))
2053 strcat(vname, inst);
2056 if (strlen(vname) + strlen(tcell) + 1 >= sizeof(vname))
2059 strcat(vname, tcell);
2060 lcstring(vname, vname, sizeof(vname));
2061 NameToID(at, vname, aid);
2063 strcpy(aname, vname);
2067 if (strcmp(AUTH_SUPERUSER, vname) == 0)
2068 *aid = SYSADMINID; /* special case for the fileserver */
2070 lcstring(vname, vname, sizeof(vname));
2071 code = NameToID(at, vname, aid);
2075 /* If we reached here, we don't understand the security class of the
2076 * given call. But if the calling user is RX_ID_SUPERUSER, we can check
2077 * that without even needing to understand the security class. Remember
2078 * to only check for RX_ID_SUPERUSER specifically; we do not use
2079 * SYSADMINID for other admins. */
2081 struct rx_identity *id = NULL;
2082 is_super = afsconf_SuperIdentity(prdir, acall, &id);
2083 if (is_super && id->kind == RX_ID_SUPERUSER) {
2090 rx_identity_free(&id);
2094 if (code && !pr_noAuth)