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 <netinet/in.h>
69 #include <arpa/inet.h>
74 #include "ptprototypes.h"
75 #include "afs/audit.h"
77 #ifdef AFS_ATHENA_STDENV
81 extern int restricted;
82 extern struct ubik_dbase *dbase;
84 extern char *pr_realmName;
85 extern int prp_group_default;
86 extern int prp_user_default;
88 static afs_int32 iNewEntry(struct rx_call *call, char aname[], afs_int32 aid,
89 afs_int32 oid, afs_int32 *cid);
90 static afs_int32 newEntry(struct rx_call *call, char aname[], afs_int32 flag,
91 afs_int32 oid, afs_int32 *aid, afs_int32 *cid);
92 static afs_int32 whereIsIt(struct rx_call *call, afs_int32 aid, afs_int32 *apos,
94 static afs_int32 dumpEntry(struct rx_call *call, afs_int32 apos,
95 struct prdebugentry *aentry, afs_int32 *cid);
96 static afs_int32 addToGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid,
98 static afs_int32 nameToID(struct rx_call *call, namelist *aname, idlist *aid);
99 static afs_int32 idToName(struct rx_call *call, idlist *aid, namelist *aname);
100 static afs_int32 Delete(struct rx_call *call, afs_int32 aid, afs_int32 *cid);
101 static afs_int32 UpdateEntry(struct rx_call *call, afs_int32 aid, char *name,
102 struct PrUpdateEntry *uentry, afs_int32 *cid);
103 static afs_int32 removeFromGroup(struct rx_call *call, afs_int32 aid,
104 afs_int32 gid, afs_int32 *cid);
105 static afs_int32 getCPS(struct rx_call *call, afs_int32 aid, prlist *alist,
106 afs_int32 *over, afs_int32 *cid);
107 static afs_int32 getCPS2(struct rx_call *call, afs_int32 aid, afs_uint32 ahost,
108 prlist *alist, afs_int32 *over, afs_int32 *cid);
109 static afs_int32 getHostCPS(struct rx_call *call, afs_uint32 ahost,
110 prlist *alist, afs_int32 *over);
111 static afs_int32 listMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid);
112 static afs_int32 setMax(struct rx_call *call, afs_int32 aid, afs_int32 gflag,
114 static afs_int32 listEntry(struct rx_call *call, afs_int32 aid,
115 struct prcheckentry *aentry, afs_int32 *cid);
116 static afs_int32 listEntries(struct rx_call *call, afs_int32 flag,
117 afs_int32 startindex, prentries *bulkentries,
118 afs_int32 *nextstartindex, afs_int32 *cid);
119 static afs_int32 put_prentries(struct prentry *tentry, prentries *bulkentries);
120 static afs_int32 changeEntry(struct rx_call *call, afs_int32 aid, char *name,
121 afs_int32 oid, afs_int32 newid, afs_int32 *cid);
122 static afs_int32 setFieldsEntry(struct rx_call *call, afs_int32 id,
123 afs_int32 mask, afs_int32 flags,
124 afs_int32 ngroups, afs_int32 nusers,
125 afs_int32 spare1, afs_int32 spare2,
127 static afs_int32 listElements(struct rx_call *call, afs_int32 aid,
128 prlist *alist, afs_int32 *over, afs_int32 *cid);
129 #if defined(SUPERGROUPS)
130 static afs_int32 listSuperGroups(struct rx_call *call, afs_int32 aid,
131 prlist *alist, afs_int32 *over,
134 static afs_int32 listOwned(struct rx_call *call, afs_int32 aid, prlist *alist,
135 afs_int32 *lastP, afs_int32 *cid);
136 static afs_int32 isAMemberOf(struct rx_call *call, afs_int32 uid, afs_int32 gid,
137 afs_int32 *flag, afs_int32 *cid);
138 static afs_int32 addWildCards(struct ubik_trans *tt, prlist *alist,
140 static afs_int32 WhoIsThisWithName(struct rx_call *acall,
141 struct ubik_trans *at, afs_int32 *aid,
144 /* when we abort, the ubik cachedVersion will be reset, so we'll read in the
145 * header on the next call.
146 * Abort the transaction and return the code.
148 #define ABORT_WITH(tt,code) return(ubik_AbortTrans(tt),code)
151 CreateOK(struct ubik_trans *ut, afs_int32 cid, afs_int32 oid, afs_int32 flag,
154 if (restricted && !admin)
157 if (flag & PRFOREIGN) {
158 /* Foreign users are recognized by the '@' sign and
159 * not by the PRFOREIGN flag.
162 } else if (flag & PRGRP) {
163 /* Allow anonymous group creation only if owner specified
164 * and running noAuth.
166 if (cid == ANONYMOUSID) {
167 if ((oid == 0) || !pr_noAuth)
170 } else { /* creating a user */
171 if (!admin && !pr_noAuth)
178 WhoIsThis(struct rx_call *acall, struct ubik_trans *at, afs_int32 *aid)
180 int code = WhoIsThisWithName(acall, at, aid, NULL);
181 if (code == 2 && *aid == ANONYMOUSID)
187 SPR_INewEntry(struct rx_call *call, char aname[], afs_int32 aid, afs_int32 oid)
190 afs_int32 cid = ANONYMOUSID;
192 code = iNewEntry(call, aname, aid, oid, &cid);
193 osi_auditU(call, PTS_INewEntEvent, code, AUD_ID, aid, AUD_STR, aname,
194 AUD_ID, oid, AUD_END);
195 ViceLog(5, ("PTS_INewEntry: code %d cid %d aid %d aname %s oid %d\n", code, cid, aid, aname, oid));
200 iNewEntry(struct rx_call *call, char aname[], afs_int32 aid, afs_int32 oid,
203 /* used primarily for conversion - not intended to be used as usual means
204 * of entering people into the database. */
205 struct ubik_trans *tt;
212 if (code != PRSUCCESS)
214 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
217 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
219 ABORT_WITH(tt, code);
220 code = read_DbHeader(tt);
222 ABORT_WITH(tt, code);
224 code = WhoIsThis(call, tt, cid);
226 ABORT_WITH(tt, PRPERM);
227 admin = IsAMemberOf(tt, *cid, SYSADMINID);
229 /* first verify the id is good */
231 ABORT_WITH(tt, PRPERM);
234 /* only sysadmin can reuse a group id */
235 if (!admin && !pr_noAuth && (aid != ntohl(cheader.maxGroup) - 1))
236 ABORT_WITH(tt, PRPERM);
238 if (FindByID(tt, aid))
239 ABORT_WITH(tt, PRIDEXIST);
241 /* check a few other things */
242 if (!CreateOK(tt, *cid, oid, gflag, admin))
243 ABORT_WITH(tt, PRPERM);
245 code = CreateEntry(tt, aname, &aid, 1, gflag, oid, *cid);
246 if (code != PRSUCCESS)
247 ABORT_WITH(tt, code);
249 /* finally, commit transaction */
250 code = ubik_EndTrans(tt);
258 SPR_NewEntry(struct rx_call *call, char aname[], afs_int32 flag, afs_int32 oid,
262 afs_int32 cid = ANONYMOUSID;
264 code = newEntry(call, aname, flag, oid, aid, &cid);
265 osi_auditU(call, PTS_NewEntEvent, code, AUD_ID, *aid, AUD_STR, aname,
266 AUD_ID, oid, AUD_END);
267 ViceLog(5, ("PTS_NewEntry: code %d cid %d aid %d aname %s oid %d\n", code, cid, *aid, aname, oid));
272 newEntry(struct rx_call *call, char aname[], afs_int32 flag, afs_int32 oid,
273 afs_int32 *aid, afs_int32 *cid)
276 struct ubik_trans *tt;
278 char cname[PR_MAXNAMELEN];
283 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
286 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
288 ABORT_WITH(tt, code);
289 code = read_DbHeader(tt);
291 ABORT_WITH(tt, code);
293 /* this is for cross-cell self registration. It is not added in the
294 * SPR_INewEntry because we want self-registration to only do
295 * automatic id assignment.
297 code = WhoIsThisWithName(call, tt, cid, cname);
298 if (code != 2) { /* 2 specifies that this is a foreign cell request */
300 ABORT_WITH(tt, PRPERM);
301 admin = IsAMemberOf(tt, *cid, SYSADMINID);
303 admin = ((!restricted && !strcmp(aname, cname))) || IsAMemberOf(tt, *cid, SYSADMINID);
304 oid = *cid = SYSADMINID;
306 if (!CreateOK(tt, *cid, oid, flag, admin))
307 ABORT_WITH(tt, PRPERM);
309 code = CreateEntry(tt, aname, aid, 0, flag, oid, *cid);
310 if (code != PRSUCCESS)
311 ABORT_WITH(tt, code);
313 code = ubik_EndTrans(tt);
322 SPR_WhereIsIt(struct rx_call *call, afs_int32 aid, afs_int32 *apos)
325 afs_int32 cid = ANONYMOUSID;
327 code = whereIsIt(call, aid, apos, &cid);
328 osi_auditU(call, PTS_WheIsItEvent, code, AUD_ID, aid, AUD_LONG, *apos,
330 ViceLog(125, ("PTS_WhereIsIt: code %d cid %d aid %d apos %d\n", code, cid, aid, *apos));
335 whereIsIt(struct rx_call *call, afs_int32 aid, afs_int32 *apos, afs_int32 *cid)
338 struct ubik_trans *tt;
342 if (code != PRSUCCESS)
344 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
347 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
349 ABORT_WITH(tt, code);
350 code = read_DbHeader(tt);
352 ABORT_WITH(tt, code);
354 code = WhoIsThis(call, tt, cid);
356 ABORT_WITH(tt, PRPERM);
358 temp = FindByID(tt, aid);
360 ABORT_WITH(tt, PRNOENT);
362 code = ubik_EndTrans(tt);
370 SPR_DumpEntry(struct rx_call *call, afs_int32 apos,
371 struct prdebugentry *aentry)
374 afs_int32 cid = ANONYMOUSID;
376 code = dumpEntry(call, apos, aentry, &cid);
377 osi_auditU(call, PTS_DmpEntEvent, code, AUD_LONG, apos, AUD_END);
378 ViceLog(125, ("PTS_DumpEntry: code %d cid %d apos %d\n", code, cid, apos));
383 dumpEntry(struct rx_call *call, afs_int32 apos, struct prdebugentry *aentry,
387 struct ubik_trans *tt;
390 if (code != PRSUCCESS)
392 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
395 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
397 ABORT_WITH(tt, code);
398 code = read_DbHeader(tt);
400 ABORT_WITH(tt, code);
402 code = WhoIsThis(call, tt, cid);
404 ABORT_WITH(tt, PRPERM);
405 code = pr_ReadEntry(tt, 0, apos, (struct prentry *)aentry);
407 ABORT_WITH(tt, code);
409 if (!AccessOK(tt, *cid, 0, PRP_STATUS_MEM, 0))
410 ABORT_WITH(tt, PRPERM);
412 /* Since prdebugentry is in the form of a prentry not a coentry, we will
413 * return the coentry slots in network order where the string is. */
415 if (aentry->flags & PRCONT) { /* wrong type, get coentry instead */
416 code = pr_ReadCoEntry(tt, 0, apos, aentry);
418 ABORT_WITH(tt, code);
421 code = ubik_EndTrans(tt);
428 SPR_AddToGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid)
431 afs_int32 cid = ANONYMOUSID;
433 code = addToGroup(call, aid, gid, &cid);
434 osi_auditU(call, PTS_AdToGrpEvent, code, AUD_ID, gid, AUD_ID, aid,
436 ViceLog(5, ("PTS_AddToGroup: code %d cid %d gid %d aid %d\n", code, cid, gid, aid));
441 addToGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid, afs_int32 *cid)
444 struct ubik_trans *tt;
447 struct prentry tentry;
448 struct prentry uentry;
451 if (code != PRSUCCESS)
453 if (gid == ANYUSERID || gid == AUTHUSERID)
455 if (aid == ANONYMOUSID)
457 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
460 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
462 ABORT_WITH(tt, code);
463 code = read_DbHeader(tt);
465 ABORT_WITH(tt, code);
467 code = WhoIsThis(call, tt, cid);
469 ABORT_WITH(tt, PRPERM);
470 tempu = FindByID(tt, aid);
472 ABORT_WITH(tt, PRNOENT);
473 memset(&uentry, 0, sizeof(uentry));
474 code = pr_ReadEntry(tt, 0, tempu, &uentry);
476 ABORT_WITH(tt, code);
478 #if !defined(SUPERGROUPS)
479 /* we don't allow groups as members of groups at present */
480 if (uentry.flags & PRGRP)
481 ABORT_WITH(tt, PRNOTUSER);
484 tempg = FindByID(tt, gid);
486 ABORT_WITH(tt, PRNOENT);
487 code = pr_ReadEntry(tt, 0, tempg, &tentry);
489 ABORT_WITH(tt, code);
490 /* make sure that this is a group */
491 if (!(tentry.flags & PRGRP))
492 ABORT_WITH(tt, PRNOTGROUP);
493 if (!AccessOK(tt, *cid, &tentry, PRP_ADD_MEM, PRP_ADD_ANY))
494 ABORT_WITH(tt, PRPERM);
496 code = AddToEntry(tt, &tentry, tempg, aid);
497 if (code != PRSUCCESS)
498 ABORT_WITH(tt, code);
500 #if defined(SUPERGROUPS)
501 if (uentry.flags & PRGRP)
502 code = AddToSGEntry(tt, &uentry, tempu, gid); /* mod group to be in sg */
505 /* now, modify the user's entry as well */
506 code = AddToEntry(tt, &uentry, tempu, gid);
507 if (code != PRSUCCESS)
508 ABORT_WITH(tt, code);
509 code = ubik_EndTrans(tt);
516 SPR_NameToID(struct rx_call *call, namelist *aname, idlist *aid)
520 code = nameToID(call, aname, aid);
521 osi_auditU(call, PTS_NmToIdEvent, code, AUD_END);
522 ViceLog(125, ("PTS_NameToID: code %d\n", code));
527 nameToID(struct rx_call *call, namelist *aname, idlist *aid)
530 struct ubik_trans *tt;
535 /* Initialize return struct */
537 aid->idlist_val = NULL;
539 size = aname->namelist_len;
545 aid->idlist_val = (afs_int32 *) malloc(size * sizeof(afs_int32));
546 if (!aid->idlist_val)
550 if (code != PRSUCCESS)
552 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
555 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
557 ABORT_WITH(tt, code);
558 code = read_DbHeader(tt);
560 ABORT_WITH(tt, code);
562 for (i = 0; i < aname->namelist_len; i++) {
564 char *nameinst, *cell;
566 strncpy(vname, aname->namelist_val[i], sizeof(vname));
567 vname[sizeof(vname)-1] ='\0';
570 cell = strchr(vname, '@');
576 if (cell && afs_is_foreign_ticket_name(nameinst,NULL,cell,pr_realmName))
577 code = NameToID(tt, aname->namelist_val[i], &aid->idlist_val[i]);
579 code = NameToID(tt, nameinst, &aid->idlist_val[i]);
581 if (code != PRSUCCESS)
582 aid->idlist_val[i] = ANONYMOUSID;
583 osi_audit(PTS_NmToIdEvent, code, AUD_STR,
584 aname->namelist_val[i], AUD_ID, aid->idlist_val[i],
586 ViceLog(125, ("PTS_NameToID: code %d aname %s aid %d\n", code,
587 aname->namelist_val[i], aid->idlist_val[i]));
589 #ifndef AFS_PTHREAD_ENV
595 aid->idlist_len = aname->namelist_len;
597 code = ubik_EndTrans(tt);
605 * Given an array of ids, find the name for each of them.
606 * The array of ids and names is unlimited.
609 SPR_IDToName(struct rx_call *call, idlist *aid, namelist *aname)
613 code = idToName(call, aid, aname);
614 osi_auditU(call, PTS_IdToNmEvent, code, AUD_END);
615 ViceLog(125, ("PTS_IDToName: code %d\n", code));
620 idToName(struct rx_call *call, idlist *aid, namelist *aname)
623 struct ubik_trans *tt;
628 /* leave this first for rpc stub */
629 size = aid->idlist_len;
634 aname->namelist_val = (prname *) malloc(size * PR_MAXNAMELEN);
635 aname->namelist_len = 0;
636 if (aname->namelist_val == 0)
638 if (aid->idlist_len == 0)
641 return PRTOOMANY; /* rxgen will probably handle this */
644 if (code != PRSUCCESS)
646 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
649 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
651 ABORT_WITH(tt, code);
652 code = read_DbHeader(tt);
654 ABORT_WITH(tt, code);
656 for (i = 0; i < aid->idlist_len; i++) {
657 code = IDToName(tt, aid->idlist_val[i], aname->namelist_val[i]);
658 if (code != PRSUCCESS)
659 sprintf(aname->namelist_val[i], "%d", aid->idlist_val[i]);
660 osi_audit(PTS_IdToNmEvent, code, AUD_ID, aid->idlist_val[i],
661 AUD_STR, aname->namelist_val[i], AUD_END);
662 ViceLog(125, ("PTS_idToName: code %d aid %d aname %s\n", code,
663 aid->idlist_val[i], aname->namelist_val[i]));
665 #ifndef AFS_PTHREAD_ENV
671 aname->namelist_len = aid->idlist_len;
673 code = ubik_EndTrans(tt);
680 SPR_Delete(struct rx_call *call, afs_int32 aid)
683 afs_int32 cid = ANONYMOUSID;
685 code = Delete(call, aid, &cid);
686 osi_auditU(call, PTS_DelEvent, code, AUD_ID, aid, AUD_END);
687 ViceLog(5, ("PTS_Delete: code %d cid %d aid %d\n", code, cid, aid));
692 Delete(struct rx_call *call, afs_int32 aid, afs_int32 *cid)
695 struct ubik_trans *tt;
696 struct prentry tentry;
703 if (code != PRSUCCESS)
705 if (aid == SYSADMINID || aid == ANYUSERID || aid == AUTHUSERID
706 || aid == ANONYMOUSID)
708 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
711 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
713 ABORT_WITH(tt, code);
714 code = read_DbHeader(tt);
716 ABORT_WITH(tt, code);
718 code = WhoIsThis(call, tt, cid);
720 ABORT_WITH(tt, PRPERM);
722 /* Read in entry to be deleted */
723 loc = FindByID(tt, aid);
725 ABORT_WITH(tt, PRNOENT);
726 code = pr_ReadEntry(tt, 0, loc, &tentry);
728 ABORT_WITH(tt, PRDBFAIL);
730 /* Do some access checking */
731 if (tentry.owner != *cid && !IsAMemberOf(tt, *cid, SYSADMINID)
732 && !IsAMemberOf(tt, *cid, tentry.owner) && !pr_noAuth)
733 ABORT_WITH(tt, PRPERM);
735 /* Delete each continuation block as a separate transaction so that no one
736 * transaction become to large to complete. */
739 struct contentry centry;
742 code = pr_ReadCoEntry(tt, 0, nptr, ¢ry);
744 ABORT_WITH(tt, PRDBFAIL);
745 for (i = 0; i < COSIZE; i++) {
746 if (centry.entries[i] == PRBADID)
748 if (centry.entries[i] == 0)
750 #if defined(SUPERGROUPS)
751 if (aid < 0 && centry.entries[i] < 0) /* Supergroup */
752 code = RemoveFromSGEntry(tt, aid, centry.entries[i]);
755 code = RemoveFromEntry(tt, aid, centry.entries[i]);
757 ABORT_WITH(tt, code);
758 tentry.count--; /* maintain count */
759 #ifndef AFS_PTHREAD_ENV
764 tentry.next = centry.next; /* thread out this block */
765 code = FreeBlock(tt, nptr); /* free continuation block */
767 ABORT_WITH(tt, code);
768 code = pr_WriteEntry(tt, 0, loc, &tentry); /* update main entry */
770 ABORT_WITH(tt, code);
772 /* end this trans and start a new one */
773 code = ubik_EndTrans(tt);
776 #ifndef AFS_PTHREAD_ENV
777 IOMGR_Poll(); /* just to keep the connection alive */
779 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
782 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
784 ABORT_WITH(tt, code);
786 /* re-read entry to get consistent uptodate info */
787 loc = FindByID(tt, aid);
789 ABORT_WITH(tt, PRNOENT);
790 code = pr_ReadEntry(tt, 0, loc, &tentry);
792 ABORT_WITH(tt, PRDBFAIL);
797 #if defined(SUPERGROUPS)
798 /* Delete each continuation block as a separate transaction
799 * so that no one transaction become too large to complete. */
801 struct prentryg *tentryg = (struct prentryg *)&tentry;
802 nptr = tentryg->nextsg;
804 struct contentry centry;
807 code = pr_ReadCoEntry(tt, 0, nptr, ¢ry);
809 ABORT_WITH(tt, PRDBFAIL);
810 for (i = 0; i < COSIZE; i++) {
811 if (centry.entries[i] == PRBADID)
813 if (centry.entries[i] == 0)
815 code = RemoveFromEntry(tt, aid, centry.entries[i]);
817 ABORT_WITH(tt, code);
818 tentryg->countsg--; /* maintain count */
819 #ifndef AFS_PTHREAD_ENV
824 tentryg->nextsg = centry.next; /* thread out this block */
825 code = FreeBlock(tt, nptr); /* free continuation block */
827 ABORT_WITH(tt, code);
828 code = pr_WriteEntry(tt, 0, loc, &tentry); /* update main entry */
830 ABORT_WITH(tt, code);
832 /* end this trans and start a new one */
833 code = ubik_EndTrans(tt);
836 #ifndef AFS_PTHREAD_ENV
837 IOMGR_Poll(); /* just to keep the connection alive */
840 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
843 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
845 ABORT_WITH(tt, code);
847 /* re-read entry to get consistent uptodate info */
848 loc = FindByID(tt, aid);
850 ABORT_WITH(tt, PRNOENT);
851 code = pr_ReadEntry(tt, 0, loc, &tentry);
853 ABORT_WITH(tt, PRDBFAIL);
855 nptr = tentryg->nextsg;
859 #endif /* SUPERGROUPS */
861 /* Then move the owned chain, except possibly ourself to the orphan list.
862 * Because this list can be very long and so exceed the size of a ubik
863 * transaction, we start a new transaction every 50 entries. */
867 struct prentry nentry;
869 code = pr_ReadEntry(tt, 0, nptr, &nentry);
871 ABORT_WITH(tt, PRDBFAIL);
872 nptr = tentry.owned = nentry.nextOwned; /* thread out */
874 if (nentry.id != tentry.id) { /* don't add us to orphan chain! */
875 code = AddToOrphan(tt, nentry.id);
877 ABORT_WITH(tt, code);
879 #ifndef AFS_PTHREAD_ENV
880 if ((count & 3) == 0)
886 code = pr_WriteEntry(tt, 0, loc, &tentry); /* update main entry */
888 ABORT_WITH(tt, code);
890 /* end this trans and start a new one */
891 code = ubik_EndTrans(tt);
894 #ifndef AFS_PTHREAD_ENV
895 IOMGR_Poll(); /* just to keep the connection alive */
897 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
900 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
902 ABORT_WITH(tt, code);
904 /* re-read entry to get consistent uptodate info */
905 loc = FindByID(tt, aid);
907 ABORT_WITH(tt, PRNOENT);
908 code = pr_ReadEntry(tt, 0, loc, &tentry);
910 ABORT_WITH(tt, PRDBFAIL);
915 /* now do what's left of the deletion stuff */
916 code = DeleteEntry(tt, &tentry, loc);
917 if (code != PRSUCCESS)
918 ABORT_WITH(tt, code);
920 code = ubik_EndTrans(tt);
927 SPR_UpdateEntry(struct rx_call *call, afs_int32 aid, char *name,
928 struct PrUpdateEntry *uentry)
931 afs_int32 cid = ANONYMOUSID;
933 code = UpdateEntry(call, aid, name, uentry, &cid);
934 osi_auditU(call, PTS_UpdEntEvent, code, AUD_ID, aid, AUD_STR, name, AUD_END);
935 ViceLog(5, ("PTS_UpdateEntry: code %d cid %d aid %d name %s\n", code, cid, aid, name));
940 UpdateEntry(struct rx_call *call, afs_int32 aid, char *name,
941 struct PrUpdateEntry *uentry, afs_int32 *cid)
944 struct ubik_trans *tt;
945 struct prentry tentry;
952 if (code != PRSUCCESS)
956 if (aid == SYSADMINID || aid == ANYUSERID || aid == AUTHUSERID
957 || aid == ANONYMOUSID)
960 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
963 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
965 ABORT_WITH(tt, code);
966 code = read_DbHeader(tt);
968 ABORT_WITH(tt, code);
970 code = WhoIsThis(call, tt, cid);
972 ABORT_WITH(tt, PRPERM);
973 code = IsAMemberOf(tt, *cid, SYSADMINID);
974 if (!code && !pr_noAuth)
975 ABORT_WITH(tt, PRPERM);
977 /* Read in entry to be deleted */
979 loc = FindByID(tt, aid);
981 loc = FindByName(tt, name, &tentry);
984 ABORT_WITH(tt, PRNOENT);
985 code = pr_ReadEntry(tt, 0, loc, &tentry);
987 ABORT_WITH(tt, PRDBFAIL);
989 if (uentry->Mask & PRUPDATE_NAMEHASH) {
991 code = RemoveFromNameHash(tt, tentry.name, &tloc);
992 if (code != PRSUCCESS)
993 ABORT_WITH(tt, PRDBFAIL);
994 code = AddToNameHash(tt, tentry.name, loc);
996 ABORT_WITH(tt, code);
999 if (uentry->Mask & PRUPDATE_IDHASH) {
1003 code = RemoveFromIDHash(tt, id, &tloc);
1004 if (code != PRSUCCESS)
1005 ABORT_WITH(tt, PRDBFAIL);
1006 code = AddToIDHash(tt, id, loc);
1008 ABORT_WITH(tt, code);
1011 code = ubik_EndTrans(tt);
1018 SPR_RemoveFromGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid)
1021 afs_int32 cid = ANONYMOUSID;
1023 code = removeFromGroup(call, aid, gid, &cid);
1024 osi_auditU(call, PTS_RmFmGrpEvent, code, AUD_ID, gid, AUD_ID, aid,
1026 ViceLog(5, ("PTS_RemoveFromGroup: code %d cid %d gid %d aid %d\n", code, cid, gid, aid));
1031 removeFromGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid,
1035 struct ubik_trans *tt;
1038 struct prentry uentry;
1039 struct prentry gentry;
1042 if (code != PRSUCCESS)
1044 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1047 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1049 ABORT_WITH(tt, code);
1050 code = read_DbHeader(tt);
1052 ABORT_WITH(tt, code);
1054 code = WhoIsThis(call, tt, cid);
1056 ABORT_WITH(tt, PRPERM);
1057 tempu = FindByID(tt, aid);
1059 ABORT_WITH(tt, PRNOENT);
1060 tempg = FindByID(tt, gid);
1062 ABORT_WITH(tt, PRNOENT);
1063 memset(&uentry, 0, sizeof(uentry));
1064 memset(&gentry, 0, sizeof(gentry));
1065 code = pr_ReadEntry(tt, 0, tempu, &uentry);
1067 ABORT_WITH(tt, code);
1068 code = pr_ReadEntry(tt, 0, tempg, &gentry);
1070 ABORT_WITH(tt, code);
1071 if (!(gentry.flags & PRGRP))
1072 ABORT_WITH(tt, PRNOTGROUP);
1073 #if !defined(SUPERGROUPS)
1074 if (uentry.flags & PRGRP)
1075 ABORT_WITH(tt, PRNOTUSER);
1077 if (!AccessOK(tt, *cid, &gentry, PRP_REMOVE_MEM, 0))
1078 ABORT_WITH(tt, PRPERM);
1079 code = RemoveFromEntry(tt, aid, gid);
1080 if (code != PRSUCCESS)
1081 ABORT_WITH(tt, code);
1082 #if defined(SUPERGROUPS)
1083 if (!(uentry.flags & PRGRP))
1085 code = RemoveFromEntry(tt, gid, aid);
1086 #if defined(SUPERGROUPS)
1088 code = RemoveFromSGEntry(tt, gid, aid);
1090 if (code != PRSUCCESS)
1091 ABORT_WITH(tt, code);
1093 code = ubik_EndTrans(tt);
1101 SPR_GetCPS(struct rx_call *call, afs_int32 aid, prlist *alist, afs_int32 *over)
1104 afs_int32 cid = ANONYMOUSID;
1106 code = getCPS(call, aid, alist, over, &cid);
1107 osi_auditU(call, PTS_GetCPSEvent, code, AUD_ID, aid, AUD_END);
1108 ViceLog(125, ("PTS_GetCPS: code %d cid %d aid %d\n", code, cid, aid));
1113 getCPS(struct rx_call *call, afs_int32 aid, prlist *alist, afs_int32 *over,
1117 struct ubik_trans *tt;
1119 struct prentry tentry;
1122 alist->prlist_len = 0;
1123 alist->prlist_val = NULL;
1125 if (code != PRSUCCESS)
1127 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1130 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1132 ABORT_WITH(tt, code);
1133 code = read_DbHeader(tt);
1135 ABORT_WITH(tt, code);
1137 temp = FindByID(tt, aid);
1139 ABORT_WITH(tt, PRNOENT);
1140 code = pr_ReadEntry(tt, 0, temp, &tentry);
1142 ABORT_WITH(tt, code);
1144 /* afs does authenticate now */
1145 code = WhoIsThis(call, tt, cid);
1146 if (code || !AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1147 ABORT_WITH(tt, PRPERM);
1149 code = GetList(tt, &tentry, alist, 1);
1150 if (code != PRSUCCESS)
1151 ABORT_WITH(tt, code);
1153 code = ubik_EndTrans(tt);
1159 inCPS(prlist CPS, afs_int32 id)
1163 for (i = (CPS.prlist_len - 1); i >= 0; i--) {
1164 if (CPS.prlist_val[i] == id)
1172 SPR_GetCPS2(struct rx_call *call, afs_int32 aid, afs_int32 ahost,
1173 prlist *alist, afs_int32 *over)
1176 afs_int32 cid = ANONYMOUSID;
1178 code = getCPS2(call, aid, ahost, alist, over, &cid);
1179 osi_auditU(call, PTS_GetCPS2Event, code, AUD_ID, aid, AUD_HOST, htonl(ahost),
1181 ViceLog(125, ("PTS_GetCPS2: code %d cid %d aid %d ahost %d\n", code, cid, aid, ahost));
1186 getCPS2(struct rx_call *call, afs_int32 aid, afs_uint32 ahost, prlist *alist,
1187 afs_int32 *over, afs_int32 *cid)
1190 struct ubik_trans *tt;
1192 struct prentry tentry;
1193 struct prentry host_tentry;
1196 struct in_addr iaddr;
1199 iaddr.s_addr = ntohl(ahost);
1200 alist->prlist_len = 0;
1201 alist->prlist_val = NULL;
1203 if (code != PRSUCCESS)
1205 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1208 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1210 ABORT_WITH(tt, code);
1211 code = read_DbHeader(tt);
1213 ABORT_WITH(tt, code);
1215 if (aid != PRBADID) {
1216 temp = FindByID(tt, aid);
1218 ABORT_WITH(tt, PRNOENT);
1219 code = pr_ReadEntry(tt, 0, temp, &tentry);
1221 ABORT_WITH(tt, code);
1223 /* afs does authenticate now */
1224 code = WhoIsThis(call, tt, cid);
1226 || !AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1227 ABORT_WITH(tt, PRPERM);
1229 code = NameToID(tt, inet_ntoa(iaddr), &hostid);
1230 if (code == PRSUCCESS && hostid != 0) {
1231 temp = FindByID(tt, hostid);
1233 code = pr_ReadEntry(tt, 0, temp, &host_tentry);
1234 if (code == PRSUCCESS)
1237 fprintf(stderr, "pr_ReadEntry returned %d\n", code);
1239 fprintf(stderr, "FindByID Failed -- Not found\n");
1242 code = GetList2(tt, &tentry, &host_tentry, alist, 1);
1244 code = GetList(tt, &tentry, alist, 1);
1246 code = addWildCards(tt, alist, ntohl(ahost));
1247 if (code != PRSUCCESS)
1248 ABORT_WITH(tt, code);
1250 code = ubik_EndTrans(tt);
1256 SPR_GetHostCPS(struct rx_call *call, afs_int32 ahost, prlist *alist,
1261 code = getHostCPS(call, ahost, alist, over);
1262 osi_auditU(call, PTS_GetHCPSEvent, code, AUD_HOST, htonl(ahost), AUD_END);
1263 ViceLog(125, ("PTS_GetHostCPS: code %d ahost %d\n", code, ahost));
1268 getHostCPS(struct rx_call *call, afs_uint32 ahost, prlist *alist,
1271 afs_int32 code, temp;
1272 struct ubik_trans *tt;
1273 struct prentry host_tentry;
1275 struct in_addr iaddr;
1278 iaddr.s_addr = ntohl(ahost);
1279 alist->prlist_len = 0;
1280 alist->prlist_val = NULL;
1282 if (code != PRSUCCESS)
1284 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1287 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1289 ABORT_WITH(tt, code);
1290 code = read_DbHeader(tt);
1292 ABORT_WITH(tt, code);
1294 code = NameToID(tt, inet_ntoa(iaddr), &hostid);
1295 if (code == PRSUCCESS && hostid != 0) {
1296 temp = FindByID(tt, hostid);
1298 code = pr_ReadEntry(tt, 0, temp, &host_tentry);
1299 if (code == PRSUCCESS) {
1300 code = GetList(tt, &host_tentry, alist, 0);
1304 fprintf(stderr, "pr_ReadEntry returned %d\n", code);
1306 fprintf(stderr, "FindByID Failed -- Not found\n");
1308 code = addWildCards(tt, alist, ntohl(ahost));
1310 if (code != PRSUCCESS)
1311 ABORT_WITH(tt, code);
1313 code = ubik_EndTrans(tt);
1319 SPR_ListMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid)
1323 code = listMax(call, uid, gid);
1324 osi_auditU(call, PTS_LstMaxEvent, code, AUD_END);
1325 ViceLog(125, ("PTS_ListMax: code %d\n", code));
1330 listMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid)
1333 struct ubik_trans *tt;
1336 if (code != PRSUCCESS)
1338 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1341 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1343 ABORT_WITH(tt, code);
1344 code = read_DbHeader(tt);
1346 ABORT_WITH(tt, code);
1348 code = GetMax(tt, uid, gid);
1349 if (code != PRSUCCESS)
1350 ABORT_WITH(tt, code);
1352 code = ubik_EndTrans(tt);
1359 SPR_SetMax(struct rx_call *call, afs_int32 aid, afs_int32 gflag)
1362 afs_int32 cid = ANONYMOUSID;
1364 code = setMax(call, aid, gflag, &cid);
1365 osi_auditU(call, PTS_SetMaxEvent, code, AUD_ID, aid, AUD_LONG, gflag,
1367 ViceLog(125, ("PTS_SetMax: code %d cid %d aid %d gflag %d\n", code, cid, aid, gflag));
1372 setMax(struct rx_call *call, afs_int32 aid, afs_int32 gflag, afs_int32 *cid)
1375 struct ubik_trans *tt;
1378 if (code != PRSUCCESS)
1380 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1383 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1385 ABORT_WITH(tt, code);
1386 code = read_DbHeader(tt);
1388 ABORT_WITH(tt, code);
1390 code = WhoIsThis(call, tt, cid);
1392 ABORT_WITH(tt, PRPERM);
1393 if (!AccessOK(tt, *cid, 0, 0, 0))
1394 ABORT_WITH(tt, PRPERM);
1395 if (((gflag & PRGRP) && (aid > 0)) || (!(gflag & PRGRP) && (aid < 0)))
1396 ABORT_WITH(tt, PRBADARG);
1398 code = SetMax(tt, aid, gflag);
1399 if (code != PRSUCCESS)
1400 ABORT_WITH(tt, code);
1402 code = ubik_EndTrans(tt);
1409 SPR_ListEntry(struct rx_call *call, afs_int32 aid, struct prcheckentry *aentry)
1412 afs_int32 cid = ANONYMOUSID;
1414 code = listEntry(call, aid, aentry, &cid);
1415 osi_auditU(call, PTS_LstEntEvent, code, AUD_ID, aid, AUD_END);
1416 ViceLog(125, ("PTS_ListEntry: code %d cid %d aid %d\n", code, cid, aid));
1421 listEntry(struct rx_call *call, afs_int32 aid, struct prcheckentry *aentry,
1425 struct ubik_trans *tt;
1427 struct prentry tentry;
1430 if (code != PRSUCCESS)
1432 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1435 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1437 ABORT_WITH(tt, code);
1438 code = read_DbHeader(tt);
1440 ABORT_WITH(tt, code);
1442 code = WhoIsThis(call, tt, cid);
1444 ABORT_WITH(tt, PRPERM);
1445 temp = FindByID(tt, aid);
1447 ABORT_WITH(tt, PRNOENT);
1448 code = pr_ReadEntry(tt, 0, temp, &tentry);
1450 ABORT_WITH(tt, code);
1451 if (!AccessOK(tt, *cid, &tentry, PRP_STATUS_MEM, PRP_STATUS_ANY))
1452 ABORT_WITH(tt, PRPERM);
1454 aentry->flags = tentry.flags >> PRIVATE_SHIFT;
1455 if (aentry->flags == 0) {
1456 if (tentry.flags & PRGRP)
1457 aentry->flags = prp_group_default >> PRIVATE_SHIFT;
1459 aentry->flags = prp_user_default >> PRIVATE_SHIFT;
1461 aentry->owner = tentry.owner;
1462 aentry->id = tentry.id;
1463 strncpy(aentry->name, tentry.name, PR_MAXNAMELEN);
1464 aentry->creator = tentry.creator;
1465 aentry->ngroups = tentry.ngroups;
1466 aentry->nusers = tentry.nusers;
1467 aentry->count = tentry.count;
1468 memset(aentry->reserved, 0, sizeof(aentry->reserved));
1469 code = ubik_EndTrans(tt);
1476 SPR_ListEntries(struct rx_call *call, afs_int32 flag, afs_int32 startindex,
1477 prentries *bulkentries, afs_int32 *nextstartindex)
1480 afs_int32 cid = ANONYMOUSID;
1482 code = listEntries(call, flag, startindex, bulkentries, nextstartindex, &cid);
1483 osi_auditU(call, PTS_LstEntsEvent, code, AUD_LONG, flag, AUD_END);
1484 ViceLog(125, ("PTS_ListEntries: code %d cid %d flag %d\n", code, cid, flag));
1489 listEntries(struct rx_call *call, afs_int32 flag, afs_int32 startindex,
1490 prentries *bulkentries, afs_int32 *nextstartindex, afs_int32 *cid)
1493 struct ubik_trans *tt;
1494 afs_int32 i, eof, pos, maxentries, f;
1495 struct prentry tentry;
1496 afs_int32 pollcount = 0;
1498 *nextstartindex = -1;
1499 bulkentries->prentries_val = 0;
1500 bulkentries->prentries_len = 0;
1503 if (code != PRSUCCESS)
1505 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1508 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1510 ABORT_WITH(tt, code);
1511 code = read_DbHeader(tt);
1513 ABORT_WITH(tt, code);
1515 /* Make sure we are an authenticated caller and that we are on the
1518 code = WhoIsThis(call, tt, cid);
1520 ABORT_WITH(tt, PRPERM);
1521 code = IsAMemberOf(tt, *cid, SYSADMINID);
1522 if (!code && !pr_noAuth)
1523 ABORT_WITH(tt, PRPERM);
1525 eof = ntohl(cheader.eofPtr) - sizeof(cheader);
1526 maxentries = eof / sizeof(struct prentry);
1527 for (i = startindex; i < maxentries; i++) {
1528 pos = i * sizeof(struct prentry) + sizeof(cheader);
1529 code = pr_ReadEntry(tt, 0, pos, &tentry);
1533 if (++pollcount > 50) {
1534 #ifndef AFS_PTHREAD_ENV
1540 f = (tentry.flags & PRTYPE);
1541 if (((flag & PRUSERS) && (f == 0)) || /* User entry */
1542 ((flag & PRGROUPS) && (f & PRGRP))) { /* Group entry */
1543 code = put_prentries(&tentry, bulkentries);
1545 break; /* Filled return array */
1552 *nextstartindex = i;
1556 if (bulkentries->prentries_val)
1557 free(bulkentries->prentries_val);
1558 bulkentries->prentries_val = 0;
1559 bulkentries->prentries_len = 0;
1560 ABORT_WITH(tt, code);
1562 code = ubik_EndTrans(tt);
1569 #define PR_MAXENTRIES 500
1571 put_prentries(struct prentry *tentry, prentries *bulkentries)
1573 struct prlistentries *entry;
1575 if (bulkentries->prentries_val == 0) {
1576 bulkentries->prentries_len = 0;
1577 bulkentries->prentries_val =
1578 (struct prlistentries *)malloc(PR_MAXENTRIES *
1579 sizeof(struct prentry));
1580 if (!bulkentries->prentries_val) {
1585 if (bulkentries->prentries_len >= PR_MAXENTRIES) {
1589 entry = (struct prlistentries *)bulkentries->prentries_val;
1590 entry += bulkentries->prentries_len;
1592 entry->flags = tentry->flags >> PRIVATE_SHIFT;
1593 if (entry->flags == 0) {
1596 flags & PRGRP) ? prp_group_default : prp_user_default) >>
1599 entry->owner = tentry->owner;
1600 entry->id = tentry->id;
1601 entry->creator = tentry->creator;
1602 entry->ngroups = tentry->ngroups;
1603 entry->nusers = tentry->nusers;
1604 entry->count = tentry->count;
1605 strncpy(entry->name, tentry->name, PR_MAXNAMELEN);
1606 memset(entry->reserved, 0, sizeof(entry->reserved));
1607 bulkentries->prentries_len++;
1612 SPR_ChangeEntry(struct rx_call *call, afs_int32 aid, char *name, afs_int32 oid,
1616 afs_int32 cid = ANONYMOUSID;
1618 code = changeEntry(call, aid, name, oid, newid, &cid);
1619 osi_auditU(call, PTS_ChgEntEvent, code, AUD_ID, aid, AUD_STR, name,
1620 AUD_LONG, oid, AUD_LONG, newid, AUD_END);
1621 ViceLog(5, ("PTS_ChangeEntry: code %d cid %d aid %d name %s oid %d newid %d\n", code, cid, aid, name, oid, newid));
1626 changeEntry(struct rx_call *call, afs_int32 aid, char *name, afs_int32 oid,
1627 afs_int32 newid, afs_int32 *cid)
1630 struct ubik_trans *tt;
1640 if (aid == ANYUSERID || aid == AUTHUSERID || aid == ANONYMOUSID
1641 || aid == SYSADMINID)
1643 if (code != PRSUCCESS)
1645 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1648 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1650 ABORT_WITH(tt, code);
1651 code = read_DbHeader(tt);
1653 ABORT_WITH(tt, code);
1655 code = WhoIsThis(call, tt, cid);
1657 ABORT_WITH(tt, PRPERM);
1658 pos = FindByID(tt, aid);
1660 ABORT_WITH(tt, PRNOENT);
1661 /* protection check in changeentry */
1662 code = ChangeEntry(tt, aid, *cid, name, oid, newid);
1663 if (code != PRSUCCESS)
1664 ABORT_WITH(tt, code);
1666 code = ubik_EndTrans(tt);
1671 SPR_SetFieldsEntry(struct rx_call *call,
1673 afs_int32 mask, /* specify which fields to update */
1674 afs_int32 flags, afs_int32 ngroups, afs_int32 nusers,
1675 afs_int32 spare1, afs_int32 spare2)
1678 afs_int32 cid = ANONYMOUSID;
1681 setFieldsEntry(call, id, mask, flags, ngroups, nusers, spare1,
1683 osi_auditU(call, PTS_SetFldEntEvent, code, AUD_ID, id, AUD_END);
1684 ViceLog(5, ("PTS_SetFieldsEntry: code %d cid %d id %d\n", code, cid, id));
1689 setFieldsEntry(struct rx_call *call,
1691 afs_int32 mask, /* specify which fields to update */
1692 afs_int32 flags, afs_int32 ngroups, afs_int32 nusers,
1693 afs_int32 spare1, afs_int32 spare2, afs_int32 *cid)
1696 struct ubik_trans *tt;
1698 struct prentry tentry;
1702 return 0; /* no-op */
1706 if (id == ANYUSERID || id == AUTHUSERID || id == ANONYMOUSID)
1708 if (code != PRSUCCESS)
1710 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1713 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1715 ABORT_WITH(tt, code);
1716 code = read_DbHeader(tt);
1718 ABORT_WITH(tt, code);
1720 code = WhoIsThis(call, tt, cid);
1722 ABORT_WITH(tt, PRPERM);
1723 pos = FindByID(tt, id);
1725 ABORT_WITH(tt, PRNOENT);
1726 code = pr_ReadEntry(tt, 0, pos, &tentry);
1728 ABORT_WITH(tt, code);
1729 tflags = tentry.flags;
1731 if (mask & (PR_SF_NGROUPS | PR_SF_NUSERS)) {
1732 if (!AccessOK(tt, *cid, 0, 0, 0))
1733 ABORT_WITH(tt, PRPERM);
1734 if ((tflags & PRQUOTA) == 0) { /* default if only setting one */
1735 tentry.ngroups = tentry.nusers = 20;
1738 if (!AccessOK(tt, *cid, &tentry, 0, 0))
1739 ABORT_WITH(tt, PRPERM);
1742 if (mask & 0xffff) { /* if setting flag bits */
1743 afs_int32 flagsMask = mask & 0xffff;
1744 tflags &= ~(flagsMask << PRIVATE_SHIFT);
1745 tflags |= (flags & flagsMask) << PRIVATE_SHIFT;
1749 if (mask & PR_SF_NGROUPS) { /* setting group limit */
1751 ABORT_WITH(tt, PRBADARG);
1752 tentry.ngroups = ngroups;
1756 if (mask & PR_SF_NUSERS) { /* setting foreign user limit */
1758 ABORT_WITH(tt, PRBADARG);
1759 tentry.nusers = nusers;
1762 tentry.flags = tflags;
1764 code = pr_WriteEntry(tt, 0, pos, &tentry);
1766 ABORT_WITH(tt, code);
1768 code = ubik_EndTrans(tt);
1773 SPR_ListElements(struct rx_call *call, afs_int32 aid, prlist *alist,
1777 afs_int32 cid = ANONYMOUSID;
1779 code = listElements(call, aid, alist, over, &cid);
1780 osi_auditU(call, PTS_LstEleEvent, code, AUD_ID, aid, AUD_END);
1781 ViceLog(125, ("PTS_ListElements: code %d cid %d aid %d\n", code, cid, aid));
1786 listElements(struct rx_call *call, afs_int32 aid, prlist *alist,
1787 afs_int32 *over, afs_int32 *cid)
1790 struct ubik_trans *tt;
1792 struct prentry tentry;
1795 alist->prlist_len = 0;
1796 alist->prlist_val = NULL;
1799 if (code != PRSUCCESS)
1801 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1804 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1806 ABORT_WITH(tt, code);
1807 code = read_DbHeader(tt);
1809 ABORT_WITH(tt, code);
1811 code = WhoIsThis(call, tt, cid);
1813 ABORT_WITH(tt, PRPERM);
1815 temp = FindByID(tt, aid);
1817 ABORT_WITH(tt, PRNOENT);
1818 code = pr_ReadEntry(tt, 0, temp, &tentry);
1820 ABORT_WITH(tt, code);
1821 if (!AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1822 ABORT_WITH(tt, PRPERM);
1824 code = GetList(tt, &tentry, alist, 0);
1825 if (code != PRSUCCESS)
1826 ABORT_WITH(tt, code);
1828 code = ubik_EndTrans(tt);
1834 SPR_ListSuperGroups(struct rx_call *call, afs_int32 aid, prlist *alist,
1837 #if defined(SUPERGROUPS)
1839 afs_int32 cid = ANONYMOUSID;
1841 code = listSuperGroups(call, aid, alist, over, &cid);
1842 osi_auditU(call, PTS_LstSGrps, code, AUD_ID, aid, AUD_END);
1843 ViceLog(125, ("PTS_ListSuperGroups: code %d cid %d aid %d\n", code, cid, aid));
1846 return RXGEN_OPCODE;
1850 #if defined(SUPERGROUPS)
1852 listSuperGroups(struct rx_call *call, afs_int32 aid, prlist *alist,
1853 afs_int32 *over, afs_int32 *cid)
1856 struct ubik_trans *tt;
1858 struct prentry tentry;
1860 alist->prlist_len = 0;
1861 alist->prlist_val = (afs_int32 *) 0;
1864 if (code != PRSUCCESS)
1866 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1869 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1871 ABORT_WITH(tt, code);
1872 code = WhoIsThis(call, tt, cid);
1874 ABORT_WITH(tt, PRPERM);
1876 temp = FindByID(tt, aid);
1878 ABORT_WITH(tt, PRNOENT);
1879 code = pr_ReadEntry(tt, 0, temp, &tentry);
1881 ABORT_WITH(tt, code);
1882 if (!AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1883 ABORT_WITH(tt, PRPERM);
1885 code = GetSGList(tt, &tentry, alist);
1887 if (code == PRTOOMANY)
1889 else if (code != PRSUCCESS)
1890 ABORT_WITH(tt, code);
1892 code = ubik_EndTrans(tt);
1898 #endif /* SUPERGROUPS */
1902 * List the entries owned by this id. If the id is zero,
1903 * return the orphans list. This will return up to PR_MAXGROUPS
1904 * at a time with the lastP available to get the rest. The
1905 * maximum value is enforced in GetOwnedChain().
1908 SPR_ListOwned(struct rx_call *call, afs_int32 aid, prlist *alist,
1912 afs_int32 cid = ANONYMOUSID;
1914 code = listOwned(call, aid, alist, lastP, &cid);
1915 osi_auditU(call, PTS_LstOwnEvent, code, AUD_ID, aid, AUD_END);
1916 ViceLog(125, ("PTS_ListOwned: code %d cid %d aid %d\n", code, cid, aid));
1921 listOwned(struct rx_call *call, afs_int32 aid, prlist *alist, afs_int32 *lastP,
1925 struct ubik_trans *tt;
1926 struct prentry tentry;
1930 alist->prlist_len = 0;
1931 alist->prlist_val = NULL;
1939 if (code != PRSUCCESS)
1941 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1944 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1946 ABORT_WITH(tt, code);
1947 code = read_DbHeader(tt);
1949 ABORT_WITH(tt, code);
1951 code = WhoIsThis(call, tt, cid);
1953 ABORT_WITH(tt, PRPERM);
1956 code = pr_ReadEntry(tt, 0, start, &tentry);
1957 if (!code && (tentry.owner == aid))
1958 head = start; /* pick up where we left off */
1963 afs_int32 loc = FindByID(tt, aid);
1965 ABORT_WITH(tt, PRNOENT);
1966 code = pr_ReadEntry(tt, 0, loc, &tentry);
1968 ABORT_WITH(tt, code);
1970 if (!AccessOK(tt, *cid, &tentry, -1, PRP_OWNED_ANY))
1971 ABORT_WITH(tt, PRPERM);
1972 head = tentry.owned;
1974 if (!AccessOK(tt, *cid, 0, 0, 0))
1975 ABORT_WITH(tt, PRPERM);
1976 head = ntohl(cheader.orphan);
1980 code = GetOwnedChain(tt, &head, alist);
1982 if (code == PRTOOMANY)
1985 ABORT_WITH(tt, code);
1988 code = ubik_EndTrans(tt);
1993 SPR_IsAMemberOf(struct rx_call *call, afs_int32 uid, afs_int32 gid,
1997 afs_int32 cid = ANONYMOUSID;
1999 code = isAMemberOf(call, uid, gid, flag, &cid);
2000 osi_auditU(call, PTS_IsMemOfEvent, code, AUD_LONG, uid, AUD_LONG, gid,
2002 ViceLog(125, ("PTS_IsAMemberOf: code %d cid %d uid %d gid %d\n", code, cid, uid, gid));
2007 isAMemberOf(struct rx_call *call, afs_int32 uid, afs_int32 gid, afs_int32 *flag,
2011 struct ubik_trans *tt;
2014 if (code != PRSUCCESS)
2016 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
2019 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
2021 ABORT_WITH(tt, code);
2022 code = read_DbHeader(tt);
2024 ABORT_WITH(tt, code);
2027 afs_int32 uloc = FindByID(tt, uid);
2028 afs_int32 gloc = FindByID(tt, gid);
2029 struct prentry uentry, gentry;
2032 ABORT_WITH(tt, PRNOENT);
2033 code = WhoIsThis(call, tt, cid);
2035 ABORT_WITH(tt, PRPERM);
2036 code = pr_ReadEntry(tt, 0, uloc, &uentry);
2038 ABORT_WITH(tt, code);
2039 code = pr_ReadEntry(tt, 0, gloc, &gentry);
2041 ABORT_WITH(tt, code);
2042 #if !defined(SUPERGROUPS)
2043 if ((uentry.flags & PRGRP) || !(gentry.flags & PRGRP))
2044 ABORT_WITH(tt, PRBADARG);
2046 if (!(gentry.flags & PRGRP))
2047 ABORT_WITH(tt, PRBADARG);
2049 if (!AccessOK(tt, *cid, &uentry, 0, PRP_MEMBER_ANY)
2050 && !AccessOK(tt, *cid, &gentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
2051 ABORT_WITH(tt, PRPERM);
2054 *flag = IsAMemberOf(tt, uid, gid);
2055 code = ubik_EndTrans(tt);
2060 addWildCards(struct ubik_trans *tt, prlist *alist, afs_uint32 host)
2063 struct prentry tentry;
2065 unsigned wild = htonl(0xffffff00);
2066 struct in_addr iaddr;
2068 int size = 0, i, code;
2071 while ((host = (host & wild))) {
2072 wild = htonl(ntohl(wild) << 8);
2073 iaddr.s_addr = host;
2074 code = NameToID(tt, inet_ntoa(iaddr), &hostid);
2075 if (code == PRSUCCESS && hostid != 0) {
2076 temp = FindByID(tt, hostid);
2078 code = pr_ReadEntry(tt, 0, temp, &tentry);
2079 if (code != PRSUCCESS)
2085 wlist.prlist_len = 0;
2086 wlist.prlist_val = NULL;
2088 code = GetList(tt, &tentry, &wlist, 0);
2091 added += wlist.prlist_len;
2092 for (i = 0; i < wlist.prlist_len; i++) {
2093 if (!inCPS(*alist, wlist.prlist_val[i]))
2094 if ((code = AddToPRList(alist, &size, wlist.prlist_val[i]))) {
2095 free(wlist.prlist_val);
2099 if (wlist.prlist_val)
2100 free(wlist.prlist_val);
2103 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
2108 WhoIsThisWithName(struct rx_call *acall, struct ubik_trans *at, afs_int32 *aid,
2112 /* aid is set to the identity of the caller, if known, else ANONYMOUSID */
2113 /* returns -1 and sets aid to ANONYMOUSID on any failure */
2114 struct rx_connection *tconn;
2116 char tcell[MAXKTCREALMLEN];
2117 char name[MAXKTCNAMELEN];
2118 char inst[MAXKTCNAMELEN];
2123 tconn = rx_ConnectionOf(acall);
2124 code = rx_SecurityClassOf(tconn);
2127 else if (code == 1) { /* vab class */
2128 goto done; /* no longer supported */
2129 } else if (code == 2) { /* kad class */
2130 if ((code = rxkad_GetServerInfo(acall->conn, NULL, NULL,
2131 name, inst, tcell, NULL)))
2135 foreign = afs_is_foreign_ticket_name(name, inst, tcell,
2138 strncpy(vname, name, sizeof(vname));
2139 if ((ilen = strlen(inst))) {
2140 if (strlen(vname) + 1 + ilen >= sizeof(vname))
2143 strcat(vname, inst);
2146 if (strlen(vname) + strlen(tcell) + 1 >= sizeof(vname))
2149 strcat(vname, tcell);
2150 lcstring(vname, vname, sizeof(vname));
2151 code = NameToID(at, vname, aid);
2153 strcpy(aname, vname);
2157 if (strcmp(AUTH_SUPERUSER, vname) == 0)
2158 *aid = SYSADMINID; /* special case for the fileserver */
2160 lcstring(vname, vname, sizeof(vname));
2161 code = NameToID(at, vname, aid);
2165 if (code && !pr_noAuth)