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>
58 #include <afs/afsutil.h>
67 #include <netinet/in.h>
68 #include <arpa/inet.h>
73 #include "ptprototypes.h"
74 #include "afs/audit.h"
76 #ifdef AFS_ATHENA_STDENV
80 extern int restricted;
81 extern struct ubik_dbase *dbase;
83 extern char *pr_realmName;
84 extern int prp_group_default;
85 extern int prp_user_default;
87 static afs_int32 iNewEntry(struct rx_call *call, char aname[], afs_int32 aid,
88 afs_int32 oid, afs_int32 *cid);
89 static afs_int32 newEntry(struct rx_call *call, char aname[], afs_int32 flag,
90 afs_int32 oid, afs_int32 *aid, afs_int32 *cid);
91 static afs_int32 whereIsIt(struct rx_call *call, afs_int32 aid, afs_int32 *apos,
93 static afs_int32 dumpEntry(struct rx_call *call, afs_int32 apos,
94 struct prdebugentry *aentry, afs_int32 *cid);
95 static afs_int32 addToGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid,
97 static afs_int32 nameToID(struct rx_call *call, namelist *aname, idlist *aid);
98 static afs_int32 idToName(struct rx_call *call, idlist *aid, namelist *aname);
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);
110 static afs_int32 listMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid);
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 afs_int32 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 (!admin && !pr_noAuth)
177 WhoIsThis(struct rx_call *acall, struct ubik_trans *at, afs_int32 *aid)
180 /* aid is set to the identity of the caller, if known, else ANONYMOUSID */
181 /* returns -1 and sets aid to ANONYMOUSID on any failure */
182 struct rx_connection *tconn;
184 char tcell[MAXKTCREALMLEN];
185 char name[MAXKTCNAMELEN];
186 char inst[MAXKTCNAMELEN];
191 tconn = rx_ConnectionOf(acall);
192 code = rx_SecurityClassOf(tconn);
195 else if (code == 1) { /* vab class */
196 goto done; /* no longer supported */
197 } else if (code == 2) { /* kad class */
198 if ((code = rxkad_GetServerInfo(acall->conn, NULL, 0 /*was &exp */ ,
199 name, inst, tcell, NULL)))
202 /* This test is unnecessary, since rxkad_GetServerInfo already check.
203 * In addition, this is wrong since exp must be unsigned. */
204 if (exp < FT_ApproxTime())
208 foreign = afs_is_foreign_ticket_name(name,inst,tcell,pr_realmName);
210 strncpy(vname, name, sizeof(vname));
211 if ((ilen = strlen(inst))) {
212 if (strlen(vname) + 1 + ilen >= sizeof(vname))
218 if (strlen(vname) + strlen(tcell) + 1 >= sizeof(vname))
221 strcat(vname, tcell);
223 if (strcmp(AUTH_SUPERUSER, vname) == 0)
224 *aid = SYSADMINID; /* special case for the fileserver */
226 lcstring(vname, vname, sizeof(vname));
227 code = NameToID(at, vname, aid);
231 if (code && !pr_noAuth)
237 SPR_INewEntry(struct rx_call *call, char aname[], afs_int32 aid, afs_int32 oid)
240 afs_int32 cid = ANONYMOUSID;
242 code = iNewEntry(call, aname, aid, oid, &cid);
243 osi_auditU(call, PTS_INewEntEvent, code, AUD_ID, aid, AUD_STR, aname,
244 AUD_ID, oid, AUD_END);
245 ViceLog(5, ("PTS_INewEntry: code %d cid %d aid %d aname %s oid %d\n", code, cid, aid, aname, oid));
250 iNewEntry(struct rx_call *call, char aname[], afs_int32 aid, afs_int32 oid,
253 /* used primarily for conversion - not intended to be used as usual means
254 * of entering people into the database. */
255 struct ubik_trans *tt;
262 if (code != PRSUCCESS)
264 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
267 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
269 ABORT_WITH(tt, code);
270 code = read_DbHeader(tt);
272 ABORT_WITH(tt, code);
274 code = WhoIsThis(call, tt, cid);
276 ABORT_WITH(tt, PRPERM);
277 admin = IsAMemberOf(tt, *cid, SYSADMINID);
279 /* first verify the id is good */
281 ABORT_WITH(tt, PRPERM);
284 /* only sysadmin can reuse a group id */
285 if (!admin && !pr_noAuth && (aid != ntohl(cheader.maxGroup) - 1))
286 ABORT_WITH(tt, PRPERM);
288 if (FindByID(tt, aid))
289 ABORT_WITH(tt, PRIDEXIST);
291 /* check a few other things */
292 if (!CreateOK(tt, *cid, oid, gflag, admin))
293 ABORT_WITH(tt, PRPERM);
295 code = CreateEntry(tt, aname, &aid, 1, gflag, oid, *cid);
296 if (code != PRSUCCESS)
297 ABORT_WITH(tt, code);
299 /* finally, commit transaction */
300 code = ubik_EndTrans(tt);
308 SPR_NewEntry(struct rx_call *call, char aname[], afs_int32 flag, afs_int32 oid,
312 afs_int32 cid = ANONYMOUSID;
314 code = newEntry(call, aname, flag, oid, aid, &cid);
315 osi_auditU(call, PTS_NewEntEvent, code, AUD_ID, *aid, AUD_STR, aname,
316 AUD_ID, oid, AUD_END);
317 ViceLog(5, ("PTS_NewEntry: code %d cid %d aid %d aname %s oid %d\n", code, cid, *aid, aname, oid));
322 newEntry(struct rx_call *call, char aname[], afs_int32 flag, afs_int32 oid,
323 afs_int32 *aid, afs_int32 *cid)
326 struct ubik_trans *tt;
328 char cname[PR_MAXNAMELEN];
333 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
336 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
338 ABORT_WITH(tt, code);
339 code = read_DbHeader(tt);
341 ABORT_WITH(tt, code);
343 /* this is for cross-cell self registration. It is not added in the
344 * SPR_INewEntry because we want self-registration to only do
345 * automatic id assignment.
347 code = WhoIsThisWithName(call, tt, cid, cname);
348 if (code != 2) { /* 2 specifies that this is a foreign cell request */
350 ABORT_WITH(tt, PRPERM);
351 admin = IsAMemberOf(tt, *cid, SYSADMINID);
353 admin = ((!restricted && !strcmp(aname, cname))) || IsAMemberOf(tt, *cid, SYSADMINID);
354 oid = *cid = SYSADMINID;
356 if (!CreateOK(tt, *cid, oid, flag, admin))
357 ABORT_WITH(tt, PRPERM);
359 code = CreateEntry(tt, aname, aid, 0, flag, oid, *cid);
360 if (code != PRSUCCESS)
361 ABORT_WITH(tt, code);
363 code = ubik_EndTrans(tt);
372 SPR_WhereIsIt(struct rx_call *call, afs_int32 aid, afs_int32 *apos)
375 afs_int32 cid = ANONYMOUSID;
377 code = whereIsIt(call, aid, apos, &cid);
378 osi_auditU(call, PTS_WheIsItEvent, code, AUD_ID, aid, AUD_LONG, *apos,
380 ViceLog(125, ("PTS_WhereIsIt: code %d cid %d aid %d apos %d\n", code, cid, aid, *apos));
385 whereIsIt(struct rx_call *call, afs_int32 aid, afs_int32 *apos, afs_int32 *cid)
388 struct ubik_trans *tt;
392 if (code != PRSUCCESS)
394 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
397 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
399 ABORT_WITH(tt, code);
400 code = read_DbHeader(tt);
402 ABORT_WITH(tt, code);
404 code = WhoIsThis(call, tt, cid);
406 ABORT_WITH(tt, PRPERM);
408 temp = FindByID(tt, aid);
410 ABORT_WITH(tt, PRNOENT);
412 code = ubik_EndTrans(tt);
420 SPR_DumpEntry(struct rx_call *call, afs_int32 apos,
421 struct prdebugentry *aentry)
424 afs_int32 cid = ANONYMOUSID;
426 code = dumpEntry(call, apos, aentry, &cid);
427 osi_auditU(call, PTS_DmpEntEvent, code, AUD_LONG, apos, AUD_END);
428 ViceLog(125, ("PTS_DumpEntry: code %d cid %d apos %d\n", code, cid, apos));
433 dumpEntry(struct rx_call *call, afs_int32 apos, struct prdebugentry *aentry,
437 struct ubik_trans *tt;
440 if (code != PRSUCCESS)
442 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
445 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
447 ABORT_WITH(tt, code);
448 code = read_DbHeader(tt);
450 ABORT_WITH(tt, code);
452 code = WhoIsThis(call, tt, cid);
454 ABORT_WITH(tt, PRPERM);
455 code = pr_ReadEntry(tt, 0, apos, (struct prentry *)aentry);
457 ABORT_WITH(tt, code);
459 if (!AccessOK(tt, *cid, 0, PRP_STATUS_MEM, 0))
460 ABORT_WITH(tt, PRPERM);
462 /* Since prdebugentry is in the form of a prentry not a coentry, we will
463 * return the coentry slots in network order where the string is. */
465 if (aentry->flags & PRCONT) { /* wrong type, get coentry instead */
466 code = pr_ReadCoEntry(tt, 0, apos, aentry);
468 ABORT_WITH(tt, code);
471 code = ubik_EndTrans(tt);
478 SPR_AddToGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid)
481 afs_int32 cid = ANONYMOUSID;
483 code = addToGroup(call, aid, gid, &cid);
484 osi_auditU(call, PTS_AdToGrpEvent, code, AUD_ID, gid, AUD_ID, aid,
486 ViceLog(5, ("PTS_AddToGroup: code %d cid %d gid %d aid %d\n", code, cid, gid, aid));
491 addToGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid, afs_int32 *cid)
494 struct ubik_trans *tt;
497 struct prentry tentry;
498 struct prentry uentry;
501 if (code != PRSUCCESS)
503 if (gid == ANYUSERID || gid == AUTHUSERID)
505 if (aid == ANONYMOUSID)
507 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
510 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
512 ABORT_WITH(tt, code);
513 code = read_DbHeader(tt);
515 ABORT_WITH(tt, code);
517 code = WhoIsThis(call, tt, cid);
519 ABORT_WITH(tt, PRPERM);
520 tempu = FindByID(tt, aid);
522 ABORT_WITH(tt, PRNOENT);
523 memset(&uentry, 0, sizeof(uentry));
524 code = pr_ReadEntry(tt, 0, tempu, &uentry);
526 ABORT_WITH(tt, code);
528 #if !defined(SUPERGROUPS)
529 /* we don't allow groups as members of groups at present */
530 if (uentry.flags & PRGRP)
531 ABORT_WITH(tt, PRNOTUSER);
534 tempg = FindByID(tt, gid);
536 ABORT_WITH(tt, PRNOENT);
537 code = pr_ReadEntry(tt, 0, tempg, &tentry);
539 ABORT_WITH(tt, code);
540 /* make sure that this is a group */
541 if (!(tentry.flags & PRGRP))
542 ABORT_WITH(tt, PRNOTGROUP);
543 if (!AccessOK(tt, *cid, &tentry, PRP_ADD_MEM, PRP_ADD_ANY))
544 ABORT_WITH(tt, PRPERM);
546 code = AddToEntry(tt, &tentry, tempg, aid);
547 if (code != PRSUCCESS)
548 ABORT_WITH(tt, code);
550 #if defined(SUPERGROUPS)
551 if (uentry.flags & PRGRP)
552 code = AddToSGEntry(tt, &uentry, tempu, gid); /* mod group to be in sg */
555 /* now, modify the user's entry as well */
556 code = AddToEntry(tt, &uentry, tempu, gid);
557 if (code != PRSUCCESS)
558 ABORT_WITH(tt, code);
559 code = ubik_EndTrans(tt);
566 SPR_NameToID(struct rx_call *call, namelist *aname, idlist *aid)
570 code = nameToID(call, aname, aid);
571 osi_auditU(call, PTS_NmToIdEvent, code, AUD_END);
572 ViceLog(125, ("PTS_NameToID: code %d\n", code));
577 nameToID(struct rx_call *call, namelist *aname, idlist *aid)
580 struct ubik_trans *tt;
585 /* Initialize return struct */
587 aid->idlist_val = NULL;
589 size = aname->namelist_len;
595 aid->idlist_val = (afs_int32 *) malloc(size * sizeof(afs_int32));
596 if (!aid->idlist_val)
600 if (code != PRSUCCESS)
602 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
605 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
607 ABORT_WITH(tt, code);
608 code = read_DbHeader(tt);
610 ABORT_WITH(tt, code);
612 for (i = 0; i < aname->namelist_len; i++) {
614 char *nameinst, *cell;
616 strncpy(vname, aname->namelist_val[i], sizeof(vname));
617 vname[sizeof(vname)-1] ='\0';
620 cell = strchr(vname, '@');
626 if (cell && afs_is_foreign_ticket_name(nameinst,NULL,cell,pr_realmName))
627 code = NameToID(tt, aname->namelist_val[i], &aid->idlist_val[i]);
629 code = NameToID(tt, nameinst, &aid->idlist_val[i]);
631 if (code != PRSUCCESS)
632 aid->idlist_val[i] = ANONYMOUSID;
633 osi_audit(PTS_NmToIdEvent, code, AUD_STR,
634 aname->namelist_val[i], AUD_ID, aid->idlist_val[i],
636 ViceLog(125, ("PTS_NameToID: code %d aname %s aid %d\n", code,
637 aname->namelist_val[i], aid->idlist_val[i]));
639 #ifndef AFS_PTHREAD_ENV
645 aid->idlist_len = aname->namelist_len;
647 code = ubik_EndTrans(tt);
655 * Given an array of ids, find the name for each of them.
656 * The array of ids and names is unlimited.
659 SPR_IDToName(struct rx_call *call, idlist *aid, namelist *aname)
663 code = idToName(call, aid, aname);
664 osi_auditU(call, PTS_IdToNmEvent, code, AUD_END);
665 ViceLog(125, ("PTS_IDToName: code %d\n", code));
670 idToName(struct rx_call *call, idlist *aid, namelist *aname)
673 struct ubik_trans *tt;
678 /* leave this first for rpc stub */
679 size = aid->idlist_len;
684 aname->namelist_val = (prname *) malloc(size * PR_MAXNAMELEN);
685 aname->namelist_len = 0;
686 if (aname->namelist_val == 0)
688 if (aid->idlist_len == 0)
691 return PRTOOMANY; /* rxgen will probably handle this */
694 if (code != PRSUCCESS)
696 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
699 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
701 ABORT_WITH(tt, code);
702 code = read_DbHeader(tt);
704 ABORT_WITH(tt, code);
706 for (i = 0; i < aid->idlist_len; i++) {
707 code = IDToName(tt, aid->idlist_val[i], aname->namelist_val[i]);
708 if (code != PRSUCCESS)
709 sprintf(aname->namelist_val[i], "%d", aid->idlist_val[i]);
710 osi_audit(PTS_IdToNmEvent, code, AUD_ID, aid->idlist_val[i],
711 AUD_STR, aname->namelist_val[i], AUD_END);
712 ViceLog(125, ("PTS_idToName: code %d aid %d aname %s\n", code,
713 aid->idlist_val[i], aname->namelist_val[i]));
715 #ifndef AFS_PTHREAD_ENV
721 aname->namelist_len = aid->idlist_len;
723 code = ubik_EndTrans(tt);
730 SPR_Delete(struct rx_call *call, afs_int32 aid)
733 afs_int32 cid = ANONYMOUSID;
735 code = Delete(call, aid, &cid);
736 osi_auditU(call, PTS_DelEvent, code, AUD_ID, aid, AUD_END);
737 ViceLog(5, ("PTS_Delete: code %d cid %d aid %d\n", code, cid, aid));
742 Delete(struct rx_call *call, afs_int32 aid, afs_int32 *cid)
745 struct ubik_trans *tt;
746 struct prentry tentry;
753 if (code != PRSUCCESS)
755 if (aid == SYSADMINID || aid == ANYUSERID || aid == AUTHUSERID
756 || aid == ANONYMOUSID)
758 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
761 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
763 ABORT_WITH(tt, code);
764 code = read_DbHeader(tt);
766 ABORT_WITH(tt, code);
768 code = WhoIsThis(call, tt, cid);
770 ABORT_WITH(tt, PRPERM);
772 /* Read in entry to be deleted */
773 loc = FindByID(tt, aid);
775 ABORT_WITH(tt, PRNOENT);
776 code = pr_ReadEntry(tt, 0, loc, &tentry);
778 ABORT_WITH(tt, PRDBFAIL);
780 /* Do some access checking */
781 if (tentry.owner != *cid && !IsAMemberOf(tt, *cid, SYSADMINID)
782 && !IsAMemberOf(tt, *cid, tentry.owner) && !pr_noAuth)
783 ABORT_WITH(tt, PRPERM);
785 /* Delete each continuation block as a separate transaction so that no one
786 * transaction become to large to complete. */
789 struct contentry centry;
792 code = pr_ReadCoEntry(tt, 0, nptr, ¢ry);
794 ABORT_WITH(tt, PRDBFAIL);
795 for (i = 0; i < COSIZE; i++) {
796 if (centry.entries[i] == PRBADID)
798 if (centry.entries[i] == 0)
800 #if defined(SUPERGROUPS)
801 if (aid < 0 && centry.entries[i] < 0) /* Supergroup */
802 code = RemoveFromSGEntry(tt, aid, centry.entries[i]);
805 code = RemoveFromEntry(tt, aid, centry.entries[i]);
807 ABORT_WITH(tt, code);
808 tentry.count--; /* maintain count */
809 #ifndef AFS_PTHREAD_ENV
814 tentry.next = centry.next; /* thread out this block */
815 code = FreeBlock(tt, nptr); /* free continuation block */
817 ABORT_WITH(tt, code);
818 code = pr_WriteEntry(tt, 0, loc, &tentry); /* update main entry */
820 ABORT_WITH(tt, code);
822 /* end this trans and start a new one */
823 code = ubik_EndTrans(tt);
826 #ifndef AFS_PTHREAD_ENV
827 IOMGR_Poll(); /* just to keep the connection alive */
829 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
832 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
834 ABORT_WITH(tt, code);
836 /* re-read entry to get consistent uptodate info */
837 loc = FindByID(tt, aid);
839 ABORT_WITH(tt, PRNOENT);
840 code = pr_ReadEntry(tt, 0, loc, &tentry);
842 ABORT_WITH(tt, PRDBFAIL);
847 #if defined(SUPERGROUPS)
848 /* Delete each continuation block as a separate transaction
849 * so that no one transaction become too large to complete. */
851 struct prentryg *tentryg = (struct prentryg *)&tentry;
852 nptr = tentryg->nextsg;
854 struct contentry centry;
857 code = pr_ReadCoEntry(tt, 0, nptr, ¢ry);
859 ABORT_WITH(tt, PRDBFAIL);
860 for (i = 0; i < COSIZE; i++) {
861 if (centry.entries[i] == PRBADID)
863 if (centry.entries[i] == 0)
865 code = RemoveFromEntry(tt, aid, centry.entries[i]);
867 ABORT_WITH(tt, code);
868 tentryg->countsg--; /* maintain count */
869 #ifndef AFS_PTHREAD_ENV
874 tentryg->nextsg = centry.next; /* thread out this block */
875 code = FreeBlock(tt, nptr); /* free continuation block */
877 ABORT_WITH(tt, code);
878 code = pr_WriteEntry(tt, 0, loc, &tentry); /* update main entry */
880 ABORT_WITH(tt, code);
882 /* end this trans and start a new one */
883 code = ubik_EndTrans(tt);
886 #ifndef AFS_PTHREAD_ENV
887 IOMGR_Poll(); /* just to keep the connection alive */
890 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
893 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
895 ABORT_WITH(tt, code);
897 /* re-read entry to get consistent uptodate info */
898 loc = FindByID(tt, aid);
900 ABORT_WITH(tt, PRNOENT);
901 code = pr_ReadEntry(tt, 0, loc, &tentry);
903 ABORT_WITH(tt, PRDBFAIL);
905 nptr = tentryg->nextsg;
909 #endif /* SUPERGROUPS */
911 /* Then move the owned chain, except possibly ourself to the orphan list.
912 * Because this list can be very long and so exceed the size of a ubik
913 * transaction, we start a new transaction every 50 entries. */
917 struct prentry nentry;
919 code = pr_ReadEntry(tt, 0, nptr, &nentry);
921 ABORT_WITH(tt, PRDBFAIL);
922 nptr = tentry.owned = nentry.nextOwned; /* thread out */
924 if (nentry.id != tentry.id) { /* don't add us to orphan chain! */
925 code = AddToOrphan(tt, nentry.id);
927 ABORT_WITH(tt, code);
929 #ifndef AFS_PTHREAD_ENV
930 if ((count & 3) == 0)
936 code = pr_WriteEntry(tt, 0, loc, &tentry); /* update main entry */
938 ABORT_WITH(tt, code);
940 /* end this trans and start a new one */
941 code = ubik_EndTrans(tt);
944 #ifndef AFS_PTHREAD_ENV
945 IOMGR_Poll(); /* just to keep the connection alive */
947 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
950 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
952 ABORT_WITH(tt, code);
954 /* re-read entry to get consistent uptodate info */
955 loc = FindByID(tt, aid);
957 ABORT_WITH(tt, PRNOENT);
958 code = pr_ReadEntry(tt, 0, loc, &tentry);
960 ABORT_WITH(tt, PRDBFAIL);
965 /* now do what's left of the deletion stuff */
966 code = DeleteEntry(tt, &tentry, loc);
967 if (code != PRSUCCESS)
968 ABORT_WITH(tt, code);
970 code = ubik_EndTrans(tt);
977 SPR_UpdateEntry(struct rx_call *call, afs_int32 aid, char *name,
978 struct PrUpdateEntry *uentry)
981 afs_int32 cid = ANONYMOUSID;
983 code = UpdateEntry(call, aid, name, uentry, &cid);
984 osi_auditU(call, PTS_UpdEntEvent, code, AUD_ID, aid, AUD_STR, name, AUD_END);
985 ViceLog(5, ("PTS_UpdateEntry: code %d cid %d aid %d name %s\n", code, cid, aid, name));
990 UpdateEntry(struct rx_call *call, afs_int32 aid, char *name,
991 struct PrUpdateEntry *uentry, afs_int32 *cid)
994 struct ubik_trans *tt;
995 struct prentry tentry;
1002 if (code != PRSUCCESS)
1006 if (aid == SYSADMINID || aid == ANYUSERID || aid == AUTHUSERID
1007 || aid == ANONYMOUSID)
1010 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1013 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1015 ABORT_WITH(tt, code);
1016 code = read_DbHeader(tt);
1018 ABORT_WITH(tt, code);
1020 code = WhoIsThis(call, tt, cid);
1022 ABORT_WITH(tt, PRPERM);
1023 code = IsAMemberOf(tt, *cid, SYSADMINID);
1024 if (!code && !pr_noAuth)
1025 ABORT_WITH(tt, PRPERM);
1027 /* Read in entry to be deleted */
1029 loc = FindByID(tt, aid);
1031 loc = FindByName(tt, name, &tentry);
1034 ABORT_WITH(tt, PRNOENT);
1035 code = pr_ReadEntry(tt, 0, loc, &tentry);
1037 ABORT_WITH(tt, PRDBFAIL);
1039 if (uentry->Mask & PRUPDATE_NAMEHASH) {
1041 code = RemoveFromNameHash(tt, tentry.name, &tloc);
1042 if (code != PRSUCCESS)
1043 ABORT_WITH(tt, PRDBFAIL);
1044 code = AddToNameHash(tt, tentry.name, loc);
1046 ABORT_WITH(tt, code);
1049 if (uentry->Mask & PRUPDATE_IDHASH) {
1053 code = RemoveFromIDHash(tt, id, &tloc);
1054 if (code != PRSUCCESS)
1055 ABORT_WITH(tt, PRDBFAIL);
1056 code = AddToIDHash(tt, id, loc);
1058 ABORT_WITH(tt, code);
1061 code = ubik_EndTrans(tt);
1068 SPR_RemoveFromGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid)
1071 afs_int32 cid = ANONYMOUSID;
1073 code = removeFromGroup(call, aid, gid, &cid);
1074 osi_auditU(call, PTS_RmFmGrpEvent, code, AUD_ID, gid, AUD_ID, aid,
1076 ViceLog(5, ("PTS_RemoveFromGroup: code %d cid %d gid %d aid %d\n", code, cid, gid, aid));
1081 removeFromGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid,
1085 struct ubik_trans *tt;
1088 struct prentry uentry;
1089 struct prentry gentry;
1092 if (code != PRSUCCESS)
1094 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1097 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1099 ABORT_WITH(tt, code);
1100 code = read_DbHeader(tt);
1102 ABORT_WITH(tt, code);
1104 code = WhoIsThis(call, tt, cid);
1106 ABORT_WITH(tt, PRPERM);
1107 tempu = FindByID(tt, aid);
1109 ABORT_WITH(tt, PRNOENT);
1110 tempg = FindByID(tt, gid);
1112 ABORT_WITH(tt, PRNOENT);
1113 memset(&uentry, 0, sizeof(uentry));
1114 memset(&gentry, 0, sizeof(gentry));
1115 code = pr_ReadEntry(tt, 0, tempu, &uentry);
1117 ABORT_WITH(tt, code);
1118 code = pr_ReadEntry(tt, 0, tempg, &gentry);
1120 ABORT_WITH(tt, code);
1121 if (!(gentry.flags & PRGRP))
1122 ABORT_WITH(tt, PRNOTGROUP);
1123 #if !defined(SUPERGROUPS)
1124 if (uentry.flags & PRGRP)
1125 ABORT_WITH(tt, PRNOTUSER);
1127 if (!AccessOK(tt, *cid, &gentry, PRP_REMOVE_MEM, 0))
1128 ABORT_WITH(tt, PRPERM);
1129 code = RemoveFromEntry(tt, aid, gid);
1130 if (code != PRSUCCESS)
1131 ABORT_WITH(tt, code);
1132 #if defined(SUPERGROUPS)
1133 if (!(uentry.flags & PRGRP))
1135 code = RemoveFromEntry(tt, gid, aid);
1136 #if defined(SUPERGROUPS)
1138 code = RemoveFromSGEntry(tt, gid, aid);
1140 if (code != PRSUCCESS)
1141 ABORT_WITH(tt, code);
1143 code = ubik_EndTrans(tt);
1151 SPR_GetCPS(struct rx_call *call, afs_int32 aid, prlist *alist, afs_int32 *over)
1154 afs_int32 cid = ANONYMOUSID;
1156 code = getCPS(call, aid, alist, over, &cid);
1157 osi_auditU(call, PTS_GetCPSEvent, code, AUD_ID, aid, AUD_END);
1158 ViceLog(125, ("PTS_GetCPS: code %d cid %d aid %d\n", code, cid, aid));
1163 getCPS(struct rx_call *call, afs_int32 aid, prlist *alist, afs_int32 *over,
1167 struct ubik_trans *tt;
1169 struct prentry tentry;
1172 alist->prlist_len = 0;
1173 alist->prlist_val = NULL;
1175 if (code != PRSUCCESS)
1177 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1180 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1182 ABORT_WITH(tt, code);
1183 code = read_DbHeader(tt);
1185 ABORT_WITH(tt, code);
1187 temp = FindByID(tt, aid);
1189 ABORT_WITH(tt, PRNOENT);
1190 code = pr_ReadEntry(tt, 0, temp, &tentry);
1192 ABORT_WITH(tt, code);
1194 /* afs does authenticate now */
1195 code = WhoIsThis(call, tt, cid);
1196 if (code || !AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1197 ABORT_WITH(tt, PRPERM);
1199 code = GetList(tt, &tentry, alist, 1);
1200 if (code != PRSUCCESS)
1201 ABORT_WITH(tt, code);
1203 code = ubik_EndTrans(tt);
1209 inCPS(prlist CPS, afs_int32 id)
1213 for (i = (CPS.prlist_len - 1); i >= 0; i--) {
1214 if (CPS.prlist_val[i] == id)
1222 SPR_GetCPS2(struct rx_call *call, afs_int32 aid, afs_int32 ahost,
1223 prlist *alist, afs_int32 *over)
1226 afs_int32 cid = ANONYMOUSID;
1228 code = getCPS2(call, aid, ahost, alist, over, &cid);
1229 osi_auditU(call, PTS_GetCPS2Event, code, AUD_ID, aid, AUD_HOST, ahost,
1231 ViceLog(125, ("PTS_GetCPS2: code %d cid %d aid %d ahost %d\n", code, cid, aid, ahost));
1236 getCPS2(struct rx_call *call, afs_int32 aid, afs_uint32 ahost, prlist *alist,
1237 afs_int32 *over, afs_int32 *cid)
1240 struct ubik_trans *tt;
1242 struct prentry tentry;
1243 struct prentry host_tentry;
1246 struct in_addr iaddr;
1249 iaddr.s_addr = ntohl(ahost);
1250 alist->prlist_len = 0;
1251 alist->prlist_val = NULL;
1253 if (code != PRSUCCESS)
1255 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1258 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1260 ABORT_WITH(tt, code);
1261 code = read_DbHeader(tt);
1263 ABORT_WITH(tt, code);
1265 if (aid != PRBADID) {
1266 temp = FindByID(tt, aid);
1268 ABORT_WITH(tt, PRNOENT);
1269 code = pr_ReadEntry(tt, 0, temp, &tentry);
1271 ABORT_WITH(tt, code);
1273 /* afs does authenticate now */
1274 code = WhoIsThis(call, tt, cid);
1276 || !AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1277 ABORT_WITH(tt, PRPERM);
1279 code = NameToID(tt, inet_ntoa(iaddr), &hostid);
1280 if (code == PRSUCCESS && hostid != 0) {
1281 temp = FindByID(tt, hostid);
1283 code = pr_ReadEntry(tt, 0, temp, &host_tentry);
1284 if (code == PRSUCCESS)
1287 fprintf(stderr, "pr_ReadEntry returned %d\n", code);
1289 fprintf(stderr, "FindByID Failed -- Not found\n");
1292 code = GetList2(tt, &tentry, &host_tentry, alist, 1);
1294 code = GetList(tt, &tentry, alist, 1);
1296 code = addWildCards(tt, alist, ntohl(ahost));
1297 if (code != PRSUCCESS)
1298 ABORT_WITH(tt, code);
1300 code = ubik_EndTrans(tt);
1306 SPR_GetHostCPS(struct rx_call *call, afs_int32 ahost, prlist *alist,
1311 code = getHostCPS(call, ahost, alist, over);
1312 osi_auditU(call, PTS_GetHCPSEvent, code, AUD_HOST, ahost, AUD_END);
1313 ViceLog(125, ("PTS_GetHostCPS: code %d ahost %d\n", code, ahost));
1318 getHostCPS(struct rx_call *call, afs_uint32 ahost, prlist *alist,
1321 afs_int32 code, temp;
1322 struct ubik_trans *tt;
1323 struct prentry host_tentry;
1325 struct in_addr iaddr;
1328 iaddr.s_addr = ntohl(ahost);
1329 alist->prlist_len = 0;
1330 alist->prlist_val = NULL;
1332 if (code != PRSUCCESS)
1334 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1337 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1339 ABORT_WITH(tt, code);
1340 code = read_DbHeader(tt);
1342 ABORT_WITH(tt, code);
1344 code = NameToID(tt, inet_ntoa(iaddr), &hostid);
1345 if (code == PRSUCCESS && hostid != 0) {
1346 temp = FindByID(tt, hostid);
1348 code = pr_ReadEntry(tt, 0, temp, &host_tentry);
1349 if (code == PRSUCCESS) {
1350 code = GetList(tt, &host_tentry, alist, 0);
1354 fprintf(stderr, "pr_ReadEntry returned %d\n", code);
1356 fprintf(stderr, "FindByID Failed -- Not found\n");
1358 code = addWildCards(tt, alist, ntohl(ahost));
1360 if (code != PRSUCCESS)
1361 ABORT_WITH(tt, code);
1363 code = ubik_EndTrans(tt);
1369 SPR_ListMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid)
1373 code = listMax(call, uid, gid);
1374 osi_auditU(call, PTS_LstMaxEvent, code, AUD_END);
1375 ViceLog(125, ("PTS_ListMax: code %d\n", code));
1380 listMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid)
1383 struct ubik_trans *tt;
1386 if (code != PRSUCCESS)
1388 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1391 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1393 ABORT_WITH(tt, code);
1394 code = read_DbHeader(tt);
1396 ABORT_WITH(tt, code);
1398 code = GetMax(tt, uid, gid);
1399 if (code != PRSUCCESS)
1400 ABORT_WITH(tt, code);
1402 code = ubik_EndTrans(tt);
1409 SPR_SetMax(struct rx_call *call, afs_int32 aid, afs_int32 gflag)
1412 afs_int32 cid = ANONYMOUSID;
1414 code = setMax(call, aid, gflag, &cid);
1415 osi_auditU(call, PTS_SetMaxEvent, code, AUD_ID, aid, AUD_LONG, gflag,
1417 ViceLog(125, ("PTS_SetMax: code %d cid %d aid %d gflag %d\n", code, cid, aid, gflag));
1422 setMax(struct rx_call *call, afs_int32 aid, afs_int32 gflag, afs_int32 *cid)
1425 struct ubik_trans *tt;
1428 if (code != PRSUCCESS)
1430 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1433 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1435 ABORT_WITH(tt, code);
1436 code = read_DbHeader(tt);
1438 ABORT_WITH(tt, code);
1440 code = WhoIsThis(call, tt, cid);
1442 ABORT_WITH(tt, PRPERM);
1443 if (!AccessOK(tt, *cid, 0, 0, 0))
1444 ABORT_WITH(tt, PRPERM);
1445 if (((gflag & PRGRP) && (aid > 0)) || (!(gflag & PRGRP) && (aid < 0)))
1446 ABORT_WITH(tt, PRBADARG);
1448 code = SetMax(tt, aid, gflag);
1449 if (code != PRSUCCESS)
1450 ABORT_WITH(tt, code);
1452 code = ubik_EndTrans(tt);
1459 SPR_ListEntry(struct rx_call *call, afs_int32 aid, struct prcheckentry *aentry)
1462 afs_int32 cid = ANONYMOUSID;
1464 code = listEntry(call, aid, aentry, &cid);
1465 osi_auditU(call, PTS_LstEntEvent, code, AUD_ID, aid, AUD_END);
1466 ViceLog(125, ("PTS_ListEntry: code %d cid %d aid %d\n", code, cid, aid));
1471 listEntry(struct rx_call *call, afs_int32 aid, struct prcheckentry *aentry,
1475 struct ubik_trans *tt;
1477 struct prentry tentry;
1480 if (code != PRSUCCESS)
1482 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1485 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1487 ABORT_WITH(tt, code);
1488 code = read_DbHeader(tt);
1490 ABORT_WITH(tt, code);
1492 code = WhoIsThis(call, tt, cid);
1494 ABORT_WITH(tt, PRPERM);
1495 temp = FindByID(tt, aid);
1497 ABORT_WITH(tt, PRNOENT);
1498 code = pr_ReadEntry(tt, 0, temp, &tentry);
1500 ABORT_WITH(tt, code);
1501 if (!AccessOK(tt, *cid, &tentry, PRP_STATUS_MEM, PRP_STATUS_ANY))
1502 ABORT_WITH(tt, PRPERM);
1504 aentry->flags = tentry.flags >> PRIVATE_SHIFT;
1505 if (aentry->flags == 0) {
1506 if (tentry.flags & PRGRP)
1507 aentry->flags = prp_group_default >> PRIVATE_SHIFT;
1509 aentry->flags = prp_user_default >> PRIVATE_SHIFT;
1511 aentry->owner = tentry.owner;
1512 aentry->id = tentry.id;
1513 strncpy(aentry->name, tentry.name, PR_MAXNAMELEN);
1514 aentry->creator = tentry.creator;
1515 aentry->ngroups = tentry.ngroups;
1516 aentry->nusers = tentry.nusers;
1517 aentry->count = tentry.count;
1518 memset(aentry->reserved, 0, sizeof(aentry->reserved));
1519 code = ubik_EndTrans(tt);
1526 SPR_ListEntries(struct rx_call *call, afs_int32 flag, afs_int32 startindex,
1527 prentries *bulkentries, afs_int32 *nextstartindex)
1530 afs_int32 cid = ANONYMOUSID;
1532 code = listEntries(call, flag, startindex, bulkentries, nextstartindex, &cid);
1533 osi_auditU(call, PTS_LstEntsEvent, code, AUD_LONG, flag, AUD_END);
1534 ViceLog(125, ("PTS_ListEntries: code %d cid %d flag %d\n", code, cid, flag));
1539 listEntries(struct rx_call *call, afs_int32 flag, afs_int32 startindex,
1540 prentries *bulkentries, afs_int32 *nextstartindex, afs_int32 *cid)
1543 struct ubik_trans *tt;
1544 afs_int32 i, eof, pos, maxentries, f;
1545 struct prentry tentry;
1546 afs_int32 pollcount = 0;
1548 *nextstartindex = -1;
1549 bulkentries->prentries_val = 0;
1550 bulkentries->prentries_len = 0;
1553 if (code != PRSUCCESS)
1555 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1558 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1560 ABORT_WITH(tt, code);
1561 code = read_DbHeader(tt);
1563 ABORT_WITH(tt, code);
1565 /* Make sure we are an authenticated caller and that we are on the
1568 code = WhoIsThis(call, tt, cid);
1570 ABORT_WITH(tt, PRPERM);
1571 code = IsAMemberOf(tt, *cid, SYSADMINID);
1572 if (!code && !pr_noAuth)
1573 ABORT_WITH(tt, PRPERM);
1575 eof = ntohl(cheader.eofPtr) - sizeof(cheader);
1576 maxentries = eof / sizeof(struct prentry);
1577 for (i = startindex; i < maxentries; i++) {
1578 pos = i * sizeof(struct prentry) + sizeof(cheader);
1579 code = pr_ReadEntry(tt, 0, pos, &tentry);
1583 if (++pollcount > 50) {
1584 #ifndef AFS_PTHREAD_ENV
1590 f = (tentry.flags & PRTYPE);
1591 if (((flag & PRUSERS) && (f == 0)) || /* User entry */
1592 ((flag & PRGROUPS) && (f & PRGRP))) { /* Group entry */
1593 code = put_prentries(&tentry, bulkentries);
1595 break; /* Filled return array */
1602 *nextstartindex = i;
1606 if (bulkentries->prentries_val)
1607 free(bulkentries->prentries_val);
1608 bulkentries->prentries_val = 0;
1609 bulkentries->prentries_len = 0;
1610 ABORT_WITH(tt, code);
1612 code = ubik_EndTrans(tt);
1619 #define PR_MAXENTRIES 500
1621 put_prentries(struct prentry *tentry, prentries *bulkentries)
1623 struct prlistentries *entry;
1625 if (bulkentries->prentries_val == 0) {
1626 bulkentries->prentries_len = 0;
1627 bulkentries->prentries_val =
1628 (struct prlistentries *)malloc(PR_MAXENTRIES *
1629 sizeof(struct prentry));
1630 if (!bulkentries->prentries_val) {
1635 if (bulkentries->prentries_len >= PR_MAXENTRIES) {
1639 entry = (struct prlistentries *)bulkentries->prentries_val;
1640 entry += bulkentries->prentries_len;
1642 entry->flags = tentry->flags >> PRIVATE_SHIFT;
1643 if (entry->flags == 0) {
1646 flags & PRGRP) ? prp_group_default : prp_user_default) >>
1649 entry->owner = tentry->owner;
1650 entry->id = tentry->id;
1651 entry->creator = tentry->creator;
1652 entry->ngroups = tentry->ngroups;
1653 entry->nusers = tentry->nusers;
1654 entry->count = tentry->count;
1655 strncpy(entry->name, tentry->name, PR_MAXNAMELEN);
1656 memset(entry->reserved, 0, sizeof(entry->reserved));
1657 bulkentries->prentries_len++;
1662 SPR_ChangeEntry(struct rx_call *call, afs_int32 aid, char *name, afs_int32 oid,
1666 afs_int32 cid = ANONYMOUSID;
1668 code = changeEntry(call, aid, name, oid, newid, &cid);
1669 osi_auditU(call, PTS_ChgEntEvent, code, AUD_ID, aid, AUD_STR, name,
1670 AUD_LONG, oid, AUD_LONG, newid, AUD_END);
1671 ViceLog(5, ("PTS_ChangeEntry: code %d cid %d aid %d name %s oid %d newid %d\n", code, cid, aid, name, oid, newid));
1676 changeEntry(struct rx_call *call, afs_int32 aid, char *name, afs_int32 oid,
1677 afs_int32 newid, afs_int32 *cid)
1680 struct ubik_trans *tt;
1690 if (aid == ANYUSERID || aid == AUTHUSERID || aid == ANONYMOUSID
1691 || aid == SYSADMINID)
1693 if (code != PRSUCCESS)
1695 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1698 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1700 ABORT_WITH(tt, code);
1701 code = read_DbHeader(tt);
1703 ABORT_WITH(tt, code);
1705 code = WhoIsThis(call, tt, cid);
1707 ABORT_WITH(tt, PRPERM);
1708 pos = FindByID(tt, aid);
1710 ABORT_WITH(tt, PRNOENT);
1711 /* protection check in changeentry */
1712 code = ChangeEntry(tt, aid, *cid, name, oid, newid);
1713 if (code != PRSUCCESS)
1714 ABORT_WITH(tt, code);
1716 code = ubik_EndTrans(tt);
1721 SPR_SetFieldsEntry(struct rx_call *call,
1723 afs_int32 mask, /* specify which fields to update */
1724 afs_int32 flags, afs_int32 ngroups, afs_int32 nusers,
1725 afs_int32 spare1, afs_int32 spare2)
1728 afs_int32 cid = ANONYMOUSID;
1731 setFieldsEntry(call, id, mask, flags, ngroups, nusers, spare1,
1733 osi_auditU(call, PTS_SetFldEntEvent, code, AUD_ID, id, AUD_END);
1734 ViceLog(5, ("PTS_SetFieldsEntry: code %d cid %d id %d\n", code, cid, id));
1739 setFieldsEntry(struct rx_call *call,
1741 afs_int32 mask, /* specify which fields to update */
1742 afs_int32 flags, afs_int32 ngroups, afs_int32 nusers,
1743 afs_int32 spare1, afs_int32 spare2, afs_int32 *cid)
1746 struct ubik_trans *tt;
1748 struct prentry tentry;
1752 return 0; /* no-op */
1756 if (id == ANYUSERID || id == AUTHUSERID || id == ANONYMOUSID)
1758 if (code != PRSUCCESS)
1760 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1763 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1765 ABORT_WITH(tt, code);
1766 code = read_DbHeader(tt);
1768 ABORT_WITH(tt, code);
1770 code = WhoIsThis(call, tt, cid);
1772 ABORT_WITH(tt, PRPERM);
1773 pos = FindByID(tt, id);
1775 ABORT_WITH(tt, PRNOENT);
1776 code = pr_ReadEntry(tt, 0, pos, &tentry);
1778 ABORT_WITH(tt, code);
1779 tflags = tentry.flags;
1781 if (mask & (PR_SF_NGROUPS | PR_SF_NUSERS)) {
1782 if (!AccessOK(tt, *cid, 0, 0, 0))
1783 ABORT_WITH(tt, PRPERM);
1784 if ((tflags & PRQUOTA) == 0) { /* default if only setting one */
1785 tentry.ngroups = tentry.nusers = 20;
1788 if (!AccessOK(tt, *cid, &tentry, 0, 0))
1789 ABORT_WITH(tt, PRPERM);
1792 if (mask & 0xffff) { /* if setting flag bits */
1793 afs_int32 flagsMask = mask & 0xffff;
1794 tflags &= ~(flagsMask << PRIVATE_SHIFT);
1795 tflags |= (flags & flagsMask) << PRIVATE_SHIFT;
1799 if (mask & PR_SF_NGROUPS) { /* setting group limit */
1801 ABORT_WITH(tt, PRBADARG);
1802 tentry.ngroups = ngroups;
1806 if (mask & PR_SF_NUSERS) { /* setting foreign user limit */
1808 ABORT_WITH(tt, PRBADARG);
1809 tentry.nusers = nusers;
1812 tentry.flags = tflags;
1814 code = pr_WriteEntry(tt, 0, pos, &tentry);
1816 ABORT_WITH(tt, code);
1818 code = ubik_EndTrans(tt);
1823 SPR_ListElements(struct rx_call *call, afs_int32 aid, prlist *alist,
1827 afs_int32 cid = ANONYMOUSID;
1829 code = listElements(call, aid, alist, over, &cid);
1830 osi_auditU(call, PTS_LstEleEvent, code, AUD_ID, aid, AUD_END);
1831 ViceLog(125, ("PTS_ListElements: code %d cid %d aid %d\n", code, cid, aid));
1836 listElements(struct rx_call *call, afs_int32 aid, prlist *alist,
1837 afs_int32 *over, afs_int32 *cid)
1840 struct ubik_trans *tt;
1842 struct prentry tentry;
1845 alist->prlist_len = 0;
1846 alist->prlist_val = NULL;
1849 if (code != PRSUCCESS)
1851 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1854 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1856 ABORT_WITH(tt, code);
1857 code = read_DbHeader(tt);
1859 ABORT_WITH(tt, code);
1861 code = WhoIsThis(call, tt, cid);
1863 ABORT_WITH(tt, PRPERM);
1865 temp = FindByID(tt, aid);
1867 ABORT_WITH(tt, PRNOENT);
1868 code = pr_ReadEntry(tt, 0, temp, &tentry);
1870 ABORT_WITH(tt, code);
1871 if (!AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1872 ABORT_WITH(tt, PRPERM);
1874 code = GetList(tt, &tentry, alist, 0);
1875 if (code != PRSUCCESS)
1876 ABORT_WITH(tt, code);
1878 code = ubik_EndTrans(tt);
1884 SPR_ListSuperGroups(struct rx_call *call, afs_int32 aid, prlist *alist,
1887 #if defined(SUPERGROUPS)
1889 afs_int32 cid = ANONYMOUSID;
1891 code = listSuperGroups(call, aid, alist, over, &cid);
1892 osi_auditU(call, PTS_LstSGrps, code, AUD_ID, aid, AUD_END);
1893 ViceLog(125, ("PTS_ListSuperGroups: code %d cid %d aid %d\n", code, cid, aid));
1896 return RXGEN_OPCODE;
1900 #if defined(SUPERGROUPS)
1902 listSuperGroups(struct rx_call *call, afs_int32 aid, prlist *alist,
1903 afs_int32 *over, afs_int32 *cid)
1906 struct ubik_trans *tt;
1908 struct prentry tentry;
1910 alist->prlist_len = 0;
1911 alist->prlist_val = (afs_int32 *) 0;
1914 if (code != PRSUCCESS)
1916 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1919 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1921 ABORT_WITH(tt, code);
1922 code = WhoIsThis(call, tt, cid);
1924 ABORT_WITH(tt, PRPERM);
1926 temp = FindByID(tt, aid);
1928 ABORT_WITH(tt, PRNOENT);
1929 code = pr_ReadEntry(tt, 0, temp, &tentry);
1931 ABORT_WITH(tt, code);
1932 if (!AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1933 ABORT_WITH(tt, PRPERM);
1935 code = GetSGList(tt, &tentry, alist);
1937 if (code == PRTOOMANY)
1939 else if (code != PRSUCCESS)
1940 ABORT_WITH(tt, code);
1942 code = ubik_EndTrans(tt);
1948 #endif /* SUPERGROUPS */
1952 * List the entries owned by this id. If the id is zero,
1953 * return the orphans list. This will return up to PR_MAXGROUPS
1954 * at a time with the lastP available to get the rest. The
1955 * maximum value is enforced in GetOwnedChain().
1958 SPR_ListOwned(struct rx_call *call, afs_int32 aid, prlist *alist,
1962 afs_int32 cid = ANONYMOUSID;
1964 code = listOwned(call, aid, alist, lastP, &cid);
1965 osi_auditU(call, PTS_LstOwnEvent, code, AUD_ID, aid, AUD_END);
1966 ViceLog(125, ("PTS_ListOwned: code %d cid %d aid %d\n", code, cid, aid));
1971 listOwned(struct rx_call *call, afs_int32 aid, prlist *alist, afs_int32 *lastP,
1975 struct ubik_trans *tt;
1976 struct prentry tentry;
1980 alist->prlist_len = 0;
1981 alist->prlist_val = NULL;
1989 if (code != PRSUCCESS)
1991 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1994 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1996 ABORT_WITH(tt, code);
1997 code = read_DbHeader(tt);
1999 ABORT_WITH(tt, code);
2001 code = WhoIsThis(call, tt, cid);
2003 ABORT_WITH(tt, PRPERM);
2006 code = pr_ReadEntry(tt, 0, start, &tentry);
2007 if (!code && (tentry.owner == aid))
2008 head = start; /* pick up where we left off */
2013 afs_int32 loc = FindByID(tt, aid);
2015 ABORT_WITH(tt, PRNOENT);
2016 code = pr_ReadEntry(tt, 0, loc, &tentry);
2018 ABORT_WITH(tt, code);
2020 if (!AccessOK(tt, *cid, &tentry, -1, PRP_OWNED_ANY))
2021 ABORT_WITH(tt, PRPERM);
2022 head = tentry.owned;
2024 if (!AccessOK(tt, *cid, 0, 0, 0))
2025 ABORT_WITH(tt, PRPERM);
2026 head = ntohl(cheader.orphan);
2030 code = GetOwnedChain(tt, &head, alist);
2032 if (code == PRTOOMANY)
2035 ABORT_WITH(tt, code);
2038 code = ubik_EndTrans(tt);
2043 SPR_IsAMemberOf(struct rx_call *call, afs_int32 uid, afs_int32 gid,
2047 afs_int32 cid = ANONYMOUSID;
2049 code = isAMemberOf(call, uid, gid, flag, &cid);
2050 osi_auditU(call, PTS_IsMemOfEvent, code, AUD_LONG, uid, AUD_LONG, gid,
2052 ViceLog(125, ("PTS_IsAMemberOf: code %d cid %d uid %d gid %d\n", code, cid, uid, gid));
2057 isAMemberOf(struct rx_call *call, afs_int32 uid, afs_int32 gid, afs_int32 *flag,
2061 struct ubik_trans *tt;
2064 if (code != PRSUCCESS)
2066 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
2069 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
2071 ABORT_WITH(tt, code);
2072 code = read_DbHeader(tt);
2074 ABORT_WITH(tt, code);
2077 afs_int32 uloc = FindByID(tt, uid);
2078 afs_int32 gloc = FindByID(tt, gid);
2079 struct prentry uentry, gentry;
2082 ABORT_WITH(tt, PRNOENT);
2083 code = WhoIsThis(call, tt, cid);
2085 ABORT_WITH(tt, PRPERM);
2086 code = pr_ReadEntry(tt, 0, uloc, &uentry);
2088 ABORT_WITH(tt, code);
2089 code = pr_ReadEntry(tt, 0, gloc, &gentry);
2091 ABORT_WITH(tt, code);
2092 #if !defined(SUPERGROUPS)
2093 if ((uentry.flags & PRGRP) || !(gentry.flags & PRGRP))
2094 ABORT_WITH(tt, PRBADARG);
2096 if (!(gentry.flags & PRGRP))
2097 ABORT_WITH(tt, PRBADARG);
2099 if (!AccessOK(tt, *cid, &uentry, 0, PRP_MEMBER_ANY)
2100 && !AccessOK(tt, *cid, &gentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
2101 ABORT_WITH(tt, PRPERM);
2104 *flag = IsAMemberOf(tt, uid, gid);
2105 code = ubik_EndTrans(tt);
2110 addWildCards(struct ubik_trans *tt, prlist *alist, afs_uint32 host)
2113 struct prentry tentry;
2115 unsigned wild = htonl(0xffffff00);
2116 struct in_addr iaddr;
2118 int size = 0, i, code;
2121 while ((host = (host & wild))) {
2122 wild = htonl(ntohl(wild) << 8);
2123 iaddr.s_addr = host;
2124 code = NameToID(tt, inet_ntoa(iaddr), &hostid);
2125 if (code == PRSUCCESS && hostid != 0) {
2126 temp = FindByID(tt, hostid);
2128 code = pr_ReadEntry(tt, 0, temp, &tentry);
2129 if (code != PRSUCCESS)
2135 wlist.prlist_len = 0;
2136 wlist.prlist_val = NULL;
2138 code = GetList(tt, &tentry, &wlist, 0);
2141 added += wlist.prlist_len;
2142 for (i = 0; i < wlist.prlist_len; i++) {
2143 if (!inCPS(*alist, wlist.prlist_val[i]))
2144 if ((code = AddToPRList(alist, &size, wlist.prlist_val[i]))) {
2145 free(wlist.prlist_val);
2149 if (wlist.prlist_val)
2150 free(wlist.prlist_val);
2153 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
2158 WhoIsThisWithName(struct rx_call *acall, struct ubik_trans *at, afs_int32 *aid,
2161 /* aid is set to the identity of the caller, if known, else ANONYMOUSID */
2162 /* returns -1 and sets aid to ANONYMOUSID on any failure */
2163 struct rx_connection *tconn;
2165 char tcell[MAXKTCREALMLEN];
2166 char name[MAXKTCNAMELEN];
2167 char inst[MAXKTCNAMELEN];
2172 tconn = rx_ConnectionOf(acall);
2173 code = rx_SecurityClassOf(tconn);
2176 else if (code == 1) { /* vab class */
2177 goto done; /* no longer supported */
2178 } else if (code == 2) { /* kad class */
2182 if ((code = rxkad_GetServerInfo(acall->conn, NULL, 0 /*was &exp */ ,
2183 name, inst, tcell, NULL)))
2187 strncpy(vname, name, sizeof(vname));
2188 if ((ilen = strlen(inst))) {
2189 if (strlen(vname) + 1 + ilen >= sizeof(vname))
2192 strcat(vname, inst);
2194 if ((clen = strlen(tcell))) {
2195 int foreign = afs_is_foreign_ticket_name(name,inst,tcell,pr_realmName);
2198 if (strlen(vname) + 1 + clen >= sizeof(vname))
2201 strcat(vname, tcell);
2202 lcstring(vname, vname, sizeof(vname));
2203 code = NameToID(at, vname, aid);
2204 strcpy(aname, vname);
2209 if (strcmp(AUTH_SUPERUSER, vname) == 0)
2210 *aid = SYSADMINID; /* special case for the fileserver */
2212 lcstring(vname, vname, sizeof(vname));
2213 code = NameToID(at, vname, aid);
2217 if (code && !pr_noAuth)