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
81 #define IP_WILDCARDS 1 /* XXX Should be defined outside of here XXX */
83 extern int restricted;
84 extern struct ubik_dbase *dbase;
86 extern afs_int32 initd;
87 extern char *pr_realmName;
88 extern int prp_group_default;
89 extern int prp_user_default;
91 static afs_int32 iNewEntry(struct rx_call *call, char aname[], afs_int32 aid,
92 afs_int32 oid, afs_int32 *cid);
93 static afs_int32 newEntry(struct rx_call *call, char aname[], afs_int32 flag,
94 afs_int32 oid, afs_int32 *aid, afs_int32 *cid);
95 static afs_int32 whereIsIt(struct rx_call *call, afs_int32 aid, afs_int32 *apos,
97 static afs_int32 dumpEntry(struct rx_call *call, afs_int32 apos,
98 struct prdebugentry *aentry, afs_int32 *cid);
99 static afs_int32 addToGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid,
101 static afs_int32 nameToID(struct rx_call *call, namelist *aname, idlist *aid);
102 static afs_int32 idToName(struct rx_call *call, idlist *aid, namelist *aname);
103 static afs_int32 Delete(struct rx_call *call, afs_int32 aid, afs_int32 *cid);
104 static afs_int32 UpdateEntry(struct rx_call *call, afs_int32 aid, char *name,
105 struct PrUpdateEntry *uentry, afs_int32 *cid);
106 static afs_int32 removeFromGroup(struct rx_call *call, afs_int32 aid,
107 afs_int32 gid, afs_int32 *cid);
108 static afs_int32 getCPS(struct rx_call *call, afs_int32 aid, prlist *alist,
109 afs_int32 *over, afs_int32 *cid);
110 static afs_int32 getCPS2(struct rx_call *call, afs_int32 aid, afs_int32 ahost,
111 prlist *alist, afs_int32 *over, afs_int32 *cid);
112 static afs_int32 getHostCPS(struct rx_call *call, afs_int32 ahost,
113 prlist *alist, afs_int32 *over);
114 static afs_int32 listMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid);
115 static afs_int32 setMax(struct rx_call *call, afs_int32 aid, afs_int32 gflag,
117 static afs_int32 listEntry(struct rx_call *call, afs_int32 aid,
118 struct prcheckentry *aentry, afs_int32 *cid);
119 static afs_int32 listEntries(struct rx_call *call, afs_int32 flag,
120 afs_int32 startindex, prentries *bulkentries,
121 afs_int32 *nextstartindex, afs_int32 *cid);
122 static afs_int32 put_prentries(struct prentry *tentry, prentries *bulkentries);
123 static afs_int32 changeEntry(struct rx_call *call, afs_int32 aid, char *name,
124 afs_int32 oid, afs_int32 newid, afs_int32 *cid);
125 static afs_int32 setFieldsEntry(struct rx_call *call, afs_int32 id,
126 afs_int32 mask, afs_int32 flags,
127 afs_int32 ngroups, afs_int32 nusers,
128 afs_int32 spare1, afs_int32 spare2,
130 static afs_int32 listElements(struct rx_call *call, afs_int32 aid,
131 prlist *alist, afs_int32 *over, afs_int32 *cid);
132 #if defined(SUPERGROUPS)
133 static afs_int32 listSuperGroups(struct rx_call *call, afs_int32 aid,
134 prlist *alist, afs_int32 *over,
137 static afs_int32 listOwned(struct rx_call *call, afs_int32 aid, prlist *alist,
138 afs_int32 *lastP, afs_int32 *cid);
139 static afs_int32 isAMemberOf(struct rx_call *call, afs_int32 uid, afs_int32 gid,
140 afs_int32 *flag, afs_int32 *cid);
142 static afs_int32 addWildCards(struct ubik_trans *tt, prlist *alist,
145 static afs_int32 WhoIsThisWithName(struct rx_call *acall,
146 struct ubik_trans *at, afs_int32 *aid,
149 /* When abort, reset initd so that the header is read in on next call.
150 * Abort the transaction and return the code.
152 #define ABORT_WITH(tt,code) return(initd=0,ubik_AbortTrans(tt),code)
155 CreateOK(struct ubik_trans *ut, afs_int32 cid, afs_int32 oid, afs_int32 flag,
158 if (restricted && !admin)
161 if (flag & PRFOREIGN) {
162 /* Foreign users are recognized by the '@' sign and
163 * not by the PRFOREIGN flag.
166 } else if (flag & PRGRP) {
167 /* Allow anonymous group creation only if owner specified
168 * and running noAuth.
170 if (cid == ANONYMOUSID) {
171 if ((oid == 0) || !pr_noAuth)
174 } else { /* creating a user */
175 if (!admin && !pr_noAuth)
182 WhoIsThis(struct rx_call *acall, struct ubik_trans *at, afs_int32 *aid)
185 /* aid is set to the identity of the caller, if known, else ANONYMOUSID */
186 /* returns -1 and sets aid to ANONYMOUSID on any failure */
187 register struct rx_connection *tconn;
188 register afs_int32 code;
189 char tcell[MAXKTCREALMLEN];
190 char name[MAXKTCNAMELEN];
191 char inst[MAXKTCNAMELEN];
196 tconn = rx_ConnectionOf(acall);
197 code = rx_SecurityClassOf(tconn);
200 else if (code == 1) { /* vab class */
201 goto done; /* no longer supported */
202 } else if (code == 2) { /* kad class */
203 if ((code = rxkad_GetServerInfo(acall->conn, NULL, 0 /*was &exp */ ,
204 name, inst, tcell, NULL)))
207 /* This test is unnecessary, since rxkad_GetServerInfo already check.
208 * In addition, this is wrong since exp must be unsigned. */
209 if (exp < FT_ApproxTime())
213 foreign = afs_is_foreign_ticket_name(name,inst,tcell,pr_realmName);
215 strncpy(vname, name, sizeof(vname));
216 if ((ilen = strlen(inst))) {
217 if (strlen(vname) + 1 + ilen >= sizeof(vname))
223 if (strlen(vname) + strlen(tcell) + 1 >= sizeof(vname))
226 strcat(vname, tcell);
228 if (strcmp(AUTH_SUPERUSER, vname) == 0)
229 *aid = SYSADMINID; /* special case for the fileserver */
231 lcstring(vname, vname, sizeof(vname));
232 code = NameToID(at, vname, aid);
236 if (code && !pr_noAuth)
242 SPR_INewEntry(struct rx_call *call, char aname[], afs_int32 aid, afs_int32 oid)
245 afs_int32 cid = ANONYMOUSID;
247 code = iNewEntry(call, aname, aid, oid, &cid);
248 osi_auditU(call, PTS_INewEntEvent, code, AUD_ID, aid, AUD_STR, aname,
249 AUD_ID, oid, AUD_END);
250 ViceLog(5, ("PTS_INewEntry: code %d cid %d aid %d aname %s oid %d\n", code, cid, aid, aname, oid));
255 iNewEntry(struct rx_call *call, char aname[], afs_int32 aid, afs_int32 oid,
258 /* used primarily for conversion - not intended to be used as usual means
259 * of entering people into the database. */
260 struct ubik_trans *tt;
261 register afs_int32 code;
267 if (code != PRSUCCESS)
269 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
272 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
274 ABORT_WITH(tt, code);
275 code = read_DbHeader(tt);
277 ABORT_WITH(tt, code);
279 code = WhoIsThis(call, tt, cid);
281 ABORT_WITH(tt, PRPERM);
282 admin = IsAMemberOf(tt, *cid, SYSADMINID);
284 /* first verify the id is good */
286 ABORT_WITH(tt, PRPERM);
289 /* only sysadmin can reuse a group id */
290 if (!admin && !pr_noAuth && (aid != ntohl(cheader.maxGroup) - 1))
291 ABORT_WITH(tt, PRPERM);
293 if (FindByID(tt, aid))
294 ABORT_WITH(tt, PRIDEXIST);
296 /* check a few other things */
297 if (!CreateOK(tt, *cid, oid, gflag, admin))
298 ABORT_WITH(tt, PRPERM);
300 code = CreateEntry(tt, aname, &aid, 1, gflag, oid, *cid);
301 if (code != PRSUCCESS)
302 ABORT_WITH(tt, code);
304 /* finally, commit transaction */
305 code = ubik_EndTrans(tt);
313 SPR_NewEntry(struct rx_call *call, char aname[], afs_int32 flag, afs_int32 oid,
317 afs_int32 cid = ANONYMOUSID;
319 code = newEntry(call, aname, flag, oid, aid, &cid);
320 osi_auditU(call, PTS_NewEntEvent, code, AUD_ID, *aid, AUD_STR, aname,
321 AUD_ID, oid, AUD_END);
322 ViceLog(5, ("PTS_NewEntry: code %d cid %d aid %d aname %s oid %d\n", code, cid, *aid, aname, oid));
327 newEntry(struct rx_call *call, char aname[], afs_int32 flag, afs_int32 oid,
328 afs_int32 *aid, afs_int32 *cid)
330 register afs_int32 code;
331 struct ubik_trans *tt;
333 char cname[PR_MAXNAMELEN];
338 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
341 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
343 ABORT_WITH(tt, code);
344 code = read_DbHeader(tt);
346 ABORT_WITH(tt, code);
348 /* this is for cross-cell self registration. It is not added in the
349 * SPR_INewEntry because we want self-registration to only do
350 * automatic id assignment.
352 code = WhoIsThisWithName(call, tt, cid, cname);
353 if (code != 2) { /* 2 specifies that this is a foreign cell request */
355 ABORT_WITH(tt, PRPERM);
356 admin = IsAMemberOf(tt, *cid, SYSADMINID);
358 admin = ((!restricted && !strcmp(aname, cname))) || IsAMemberOf(tt, *cid, SYSADMINID);
359 oid = *cid = SYSADMINID;
361 if (!CreateOK(tt, *cid, oid, flag, admin))
362 ABORT_WITH(tt, PRPERM);
364 code = CreateEntry(tt, aname, aid, 0, flag, oid, *cid);
365 if (code != PRSUCCESS)
366 ABORT_WITH(tt, code);
368 code = ubik_EndTrans(tt);
377 SPR_WhereIsIt(struct rx_call *call, afs_int32 aid, afs_int32 *apos)
380 afs_int32 cid = ANONYMOUSID;
382 code = whereIsIt(call, aid, apos, &cid);
383 osi_auditU(call, PTS_WheIsItEvent, code, AUD_ID, aid, AUD_LONG, *apos,
385 ViceLog(125, ("PTS_WhereIsIt: code %d cid %d aid %d apos %d\n", code, cid, aid, *apos));
390 whereIsIt(struct rx_call *call, afs_int32 aid, afs_int32 *apos, afs_int32 *cid)
392 register afs_int32 code;
393 struct ubik_trans *tt;
397 if (code != PRSUCCESS)
399 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
402 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
404 ABORT_WITH(tt, code);
405 code = read_DbHeader(tt);
407 ABORT_WITH(tt, code);
409 code = WhoIsThis(call, tt, cid);
411 ABORT_WITH(tt, PRPERM);
413 temp = FindByID(tt, aid);
415 ABORT_WITH(tt, PRNOENT);
417 code = ubik_EndTrans(tt);
425 SPR_DumpEntry(struct rx_call *call, afs_int32 apos,
426 struct prdebugentry *aentry)
429 afs_int32 cid = ANONYMOUSID;
431 code = dumpEntry(call, apos, aentry, &cid);
432 osi_auditU(call, PTS_DmpEntEvent, code, AUD_LONG, apos, AUD_END);
433 ViceLog(125, ("PTS_DumpEntry: code %d cid %d apos %d\n", code, cid, apos));
438 dumpEntry(struct rx_call *call, afs_int32 apos, struct prdebugentry *aentry,
441 register afs_int32 code;
442 struct ubik_trans *tt;
445 if (code != PRSUCCESS)
447 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
450 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
452 ABORT_WITH(tt, code);
453 code = read_DbHeader(tt);
455 ABORT_WITH(tt, code);
457 code = WhoIsThis(call, tt, cid);
459 ABORT_WITH(tt, PRPERM);
460 code = pr_ReadEntry(tt, 0, apos, (struct prentry *)aentry);
462 ABORT_WITH(tt, code);
464 if (!AccessOK(tt, *cid, 0, PRP_STATUS_MEM, 0))
465 ABORT_WITH(tt, PRPERM);
467 /* Since prdebugentry is in the form of a prentry not a coentry, we will
468 * return the coentry slots in network order where the string is. */
470 if (aentry->flags & PRCONT) { /* wrong type, get coentry instead */
471 code = pr_ReadCoEntry(tt, 0, apos, aentry);
473 ABORT_WITH(tt, code);
476 code = ubik_EndTrans(tt);
483 SPR_AddToGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid)
486 afs_int32 cid = ANONYMOUSID;
488 code = addToGroup(call, aid, gid, &cid);
489 osi_auditU(call, PTS_AdToGrpEvent, code, AUD_ID, gid, AUD_ID, aid,
491 ViceLog(5, ("PTS_AddToGroup: code %d cid %d gid %d aid %d\n", code, cid, gid, aid));
496 addToGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid, afs_int32 *cid)
498 register afs_int32 code;
499 struct ubik_trans *tt;
502 struct prentry tentry;
503 struct prentry uentry;
506 if (code != PRSUCCESS)
508 if (gid == ANYUSERID || gid == AUTHUSERID)
510 if (aid == ANONYMOUSID)
512 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
515 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
517 ABORT_WITH(tt, code);
518 code = read_DbHeader(tt);
520 ABORT_WITH(tt, code);
522 code = WhoIsThis(call, tt, cid);
524 ABORT_WITH(tt, PRPERM);
525 tempu = FindByID(tt, aid);
527 ABORT_WITH(tt, PRNOENT);
528 memset(&uentry, 0, sizeof(uentry));
529 code = pr_ReadEntry(tt, 0, tempu, &uentry);
531 ABORT_WITH(tt, code);
533 #if !defined(SUPERGROUPS)
534 /* we don't allow groups as members of groups at present */
535 if (uentry.flags & PRGRP)
536 ABORT_WITH(tt, PRNOTUSER);
539 tempg = FindByID(tt, gid);
541 ABORT_WITH(tt, PRNOENT);
542 code = pr_ReadEntry(tt, 0, tempg, &tentry);
544 ABORT_WITH(tt, code);
545 /* make sure that this is a group */
546 if (!(tentry.flags & PRGRP))
547 ABORT_WITH(tt, PRNOTGROUP);
548 if (!AccessOK(tt, *cid, &tentry, PRP_ADD_MEM, PRP_ADD_ANY))
549 ABORT_WITH(tt, PRPERM);
551 code = AddToEntry(tt, &tentry, tempg, aid);
552 if (code != PRSUCCESS)
553 ABORT_WITH(tt, code);
555 #if defined(SUPERGROUPS)
556 if (uentry.flags & PRGRP)
557 code = AddToSGEntry(tt, &uentry, tempu, gid); /* mod group to be in sg */
560 /* now, modify the user's entry as well */
561 code = AddToEntry(tt, &uentry, tempu, gid);
562 if (code != PRSUCCESS)
563 ABORT_WITH(tt, code);
564 code = ubik_EndTrans(tt);
571 SPR_NameToID(struct rx_call *call, namelist *aname, idlist *aid)
575 code = nameToID(call, aname, aid);
576 osi_auditU(call, PTS_NmToIdEvent, code, AUD_END);
577 ViceLog(125, ("PTS_NameToID: code %d\n", code));
582 nameToID(struct rx_call *call, namelist *aname, idlist *aid)
584 register afs_int32 code;
585 struct ubik_trans *tt;
590 /* Initialize return struct */
592 aid->idlist_val = NULL;
594 size = aname->namelist_len;
600 aid->idlist_val = (afs_int32 *) malloc(size * sizeof(afs_int32));
601 if (!aid->idlist_val)
605 if (code != PRSUCCESS)
607 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
610 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
612 ABORT_WITH(tt, code);
613 code = read_DbHeader(tt);
615 ABORT_WITH(tt, code);
617 for (i = 0; i < aname->namelist_len; i++) {
619 char *nameinst, *cell;
621 strncpy(vname, aname->namelist_val[i], sizeof(vname));
622 vname[sizeof(vname)-1] ='\0';
625 cell = strchr(vname, '@');
631 if (cell && afs_is_foreign_ticket_name(nameinst,NULL,cell,pr_realmName))
632 code = NameToID(tt, aname->namelist_val[i], &aid->idlist_val[i]);
634 code = NameToID(tt, nameinst, &aid->idlist_val[i]);
636 if (code != PRSUCCESS)
637 aid->idlist_val[i] = ANONYMOUSID;
638 osi_audit(PTS_NmToIdEvent, code, AUD_STR,
639 aname->namelist_val[i], AUD_ID, aid->idlist_val[i],
641 ViceLog(125, ("PTS_NameToID: code %d aname %s aid %d\n", code,
642 aname->namelist_val[i], aid->idlist_val[i]));
644 #ifndef AFS_PTHREAD_ENV
650 aid->idlist_len = aname->namelist_len;
652 code = ubik_EndTrans(tt);
660 * Given an array of ids, find the name for each of them.
661 * The array of ids and names is unlimited.
664 SPR_IDToName(struct rx_call *call, idlist *aid, namelist *aname)
668 code = idToName(call, aid, aname);
669 osi_auditU(call, PTS_IdToNmEvent, code, AUD_END);
670 ViceLog(125, ("PTS_IDToName: code %d\n", code));
675 idToName(struct rx_call *call, idlist *aid, namelist *aname)
677 register afs_int32 code;
678 struct ubik_trans *tt;
683 /* leave this first for rpc stub */
684 size = aid->idlist_len;
689 aname->namelist_val = (prname *) malloc(size * PR_MAXNAMELEN);
690 aname->namelist_len = 0;
691 if (aname->namelist_val == 0)
693 if (aid->idlist_len == 0)
696 return PRTOOMANY; /* rxgen will probably handle this */
699 if (code != PRSUCCESS)
701 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
704 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
706 ABORT_WITH(tt, code);
707 code = read_DbHeader(tt);
709 ABORT_WITH(tt, code);
711 for (i = 0; i < aid->idlist_len; i++) {
712 code = IDToName(tt, aid->idlist_val[i], aname->namelist_val[i]);
713 if (code != PRSUCCESS)
714 sprintf(aname->namelist_val[i], "%d", aid->idlist_val[i]);
715 osi_audit(PTS_IdToNmEvent, code, AUD_ID, aid->idlist_val[i],
716 AUD_STR, aname->namelist_val[i], AUD_END);
717 ViceLog(125, ("PTS_idToName: code %d aid %d aname %s\n", code,
718 aid->idlist_val[i], aname->namelist_val[i]));
720 #ifndef AFS_PTHREAD_ENV
726 aname->namelist_len = aid->idlist_len;
728 code = ubik_EndTrans(tt);
735 SPR_Delete(struct rx_call *call, afs_int32 aid)
738 afs_int32 cid = ANONYMOUSID;
740 code = Delete(call, aid, &cid);
741 osi_auditU(call, PTS_DelEvent, code, AUD_ID, aid, AUD_END);
742 ViceLog(5, ("PTS_Delete: code %d cid %d aid %d\n", code, cid, aid));
747 Delete(struct rx_call *call, afs_int32 aid, afs_int32 *cid)
749 register afs_int32 code;
750 struct ubik_trans *tt;
751 struct prentry tentry;
758 if (code != PRSUCCESS)
760 if (aid == SYSADMINID || aid == ANYUSERID || aid == AUTHUSERID
761 || aid == ANONYMOUSID)
763 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
766 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
768 ABORT_WITH(tt, code);
769 code = read_DbHeader(tt);
771 ABORT_WITH(tt, code);
773 code = WhoIsThis(call, tt, cid);
775 ABORT_WITH(tt, PRPERM);
777 /* Read in entry to be deleted */
778 loc = FindByID(tt, aid);
780 ABORT_WITH(tt, PRNOENT);
781 code = pr_ReadEntry(tt, 0, loc, &tentry);
783 ABORT_WITH(tt, PRDBFAIL);
785 /* Do some access checking */
786 if (tentry.owner != *cid && !IsAMemberOf(tt, *cid, SYSADMINID)
787 && !IsAMemberOf(tt, *cid, tentry.owner) && !pr_noAuth)
788 ABORT_WITH(tt, PRPERM);
790 /* Delete each continuation block as a separate transaction so that no one
791 * transaction become to large to complete. */
794 struct contentry centry;
797 code = pr_ReadCoEntry(tt, 0, nptr, ¢ry);
799 ABORT_WITH(tt, PRDBFAIL);
800 for (i = 0; i < COSIZE; i++) {
801 if (centry.entries[i] == PRBADID)
803 if (centry.entries[i] == 0)
805 #if defined(SUPERGROUPS)
806 if (aid < 0 && centry.entries[i] < 0) /* Supergroup */
807 code = RemoveFromSGEntry(tt, aid, centry.entries[i]);
810 code = RemoveFromEntry(tt, aid, centry.entries[i]);
812 ABORT_WITH(tt, code);
813 tentry.count--; /* maintain count */
814 #ifndef AFS_PTHREAD_ENV
819 tentry.next = centry.next; /* thread out this block */
820 code = FreeBlock(tt, nptr); /* free continuation block */
822 ABORT_WITH(tt, code);
823 code = pr_WriteEntry(tt, 0, loc, &tentry); /* update main entry */
825 ABORT_WITH(tt, code);
827 /* end this trans and start a new one */
828 code = ubik_EndTrans(tt);
831 #ifndef AFS_PTHREAD_ENV
832 IOMGR_Poll(); /* just to keep the connection alive */
834 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
837 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
839 ABORT_WITH(tt, code);
841 /* re-read entry to get consistent uptodate info */
842 loc = FindByID(tt, aid);
844 ABORT_WITH(tt, PRNOENT);
845 code = pr_ReadEntry(tt, 0, loc, &tentry);
847 ABORT_WITH(tt, PRDBFAIL);
852 #if defined(SUPERGROUPS)
853 /* Delete each continuation block as a separate transaction
854 * so that no one transaction become too large to complete. */
856 struct prentryg *tentryg = (struct prentryg *)&tentry;
857 nptr = tentryg->nextsg;
859 struct contentry centry;
862 code = pr_ReadCoEntry(tt, 0, nptr, ¢ry);
864 ABORT_WITH(tt, PRDBFAIL);
865 for (i = 0; i < COSIZE; i++) {
866 if (centry.entries[i] == PRBADID)
868 if (centry.entries[i] == 0)
870 code = RemoveFromEntry(tt, aid, centry.entries[i]);
872 ABORT_WITH(tt, code);
873 tentryg->countsg--; /* maintain count */
874 #ifndef AFS_PTHREAD_ENV
879 tentryg->nextsg = centry.next; /* thread out this block */
880 code = FreeBlock(tt, nptr); /* free continuation block */
882 ABORT_WITH(tt, code);
883 code = pr_WriteEntry(tt, 0, loc, &tentry); /* update main entry */
885 ABORT_WITH(tt, code);
887 /* end this trans and start a new one */
888 code = ubik_EndTrans(tt);
891 #ifndef AFS_PTHREAD_ENV
892 IOMGR_Poll(); /* just to keep the connection alive */
895 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
898 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
900 ABORT_WITH(tt, code);
902 /* re-read entry to get consistent uptodate info */
903 loc = FindByID(tt, aid);
905 ABORT_WITH(tt, PRNOENT);
906 code = pr_ReadEntry(tt, 0, loc, &tentry);
908 ABORT_WITH(tt, PRDBFAIL);
910 nptr = tentryg->nextsg;
914 #endif /* SUPERGROUPS */
916 /* Then move the owned chain, except possibly ourself to the orphan list.
917 * Because this list can be very long and so exceed the size of a ubik
918 * transaction, we start a new transaction every 50 entries. */
922 struct prentry nentry;
924 code = pr_ReadEntry(tt, 0, nptr, &nentry);
926 ABORT_WITH(tt, PRDBFAIL);
927 nptr = tentry.owned = nentry.nextOwned; /* thread out */
929 if (nentry.id != tentry.id) { /* don't add us to orphan chain! */
930 code = AddToOrphan(tt, nentry.id);
932 ABORT_WITH(tt, code);
934 #ifndef AFS_PTHREAD_ENV
935 if ((count & 3) == 0)
941 code = pr_WriteEntry(tt, 0, loc, &tentry); /* update main entry */
943 ABORT_WITH(tt, code);
945 /* end this trans and start a new one */
946 code = ubik_EndTrans(tt);
949 #ifndef AFS_PTHREAD_ENV
950 IOMGR_Poll(); /* just to keep the connection alive */
952 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
955 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
957 ABORT_WITH(tt, code);
959 /* re-read entry to get consistent uptodate info */
960 loc = FindByID(tt, aid);
962 ABORT_WITH(tt, PRNOENT);
963 code = pr_ReadEntry(tt, 0, loc, &tentry);
965 ABORT_WITH(tt, PRDBFAIL);
970 /* now do what's left of the deletion stuff */
971 code = DeleteEntry(tt, &tentry, loc);
972 if (code != PRSUCCESS)
973 ABORT_WITH(tt, code);
975 code = ubik_EndTrans(tt);
982 SPR_UpdateEntry(struct rx_call *call, afs_int32 aid, char *name,
983 struct PrUpdateEntry *uentry)
986 afs_int32 cid = ANONYMOUSID;
988 code = UpdateEntry(call, aid, name, uentry, &cid);
989 osi_auditU(call, PTS_UpdEntEvent, code, AUD_ID, aid, AUD_STR, name, AUD_END);
990 ViceLog(5, ("PTS_UpdateEntry: code %d cid %d aid %d name %s\n", code, cid, aid, name));
995 UpdateEntry(struct rx_call *call, afs_int32 aid, char *name,
996 struct PrUpdateEntry *uentry, afs_int32 *cid)
998 register afs_int32 code;
999 struct ubik_trans *tt;
1000 struct prentry tentry;
1007 if (code != PRSUCCESS)
1011 if (aid == SYSADMINID || aid == ANYUSERID || aid == AUTHUSERID
1012 || aid == ANONYMOUSID)
1015 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1018 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1020 ABORT_WITH(tt, code);
1021 code = read_DbHeader(tt);
1023 ABORT_WITH(tt, code);
1025 code = WhoIsThis(call, tt, cid);
1027 ABORT_WITH(tt, PRPERM);
1028 code = IsAMemberOf(tt, *cid, SYSADMINID);
1029 if (!code && !pr_noAuth)
1030 ABORT_WITH(tt, PRPERM);
1032 /* Read in entry to be deleted */
1034 loc = FindByID(tt, aid);
1036 loc = FindByName(tt, name, &tentry);
1039 ABORT_WITH(tt, PRNOENT);
1040 code = pr_ReadEntry(tt, 0, loc, &tentry);
1042 ABORT_WITH(tt, PRDBFAIL);
1044 if (uentry->Mask & PRUPDATE_NAMEHASH) {
1046 code = RemoveFromNameHash(tt, tentry.name, &tloc);
1047 if (code != PRSUCCESS)
1048 ABORT_WITH(tt, PRDBFAIL);
1049 code = AddToNameHash(tt, tentry.name, loc);
1051 ABORT_WITH(tt, code);
1054 if (uentry->Mask & PRUPDATE_IDHASH) {
1058 code = RemoveFromIDHash(tt, id, &tloc);
1059 if (code != PRSUCCESS)
1060 ABORT_WITH(tt, PRDBFAIL);
1061 code = AddToIDHash(tt, id, loc);
1063 ABORT_WITH(tt, code);
1066 code = ubik_EndTrans(tt);
1073 SPR_RemoveFromGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid)
1076 afs_int32 cid = ANONYMOUSID;
1078 code = removeFromGroup(call, aid, gid, &cid);
1079 osi_auditU(call, PTS_RmFmGrpEvent, code, AUD_ID, gid, AUD_ID, aid,
1081 ViceLog(5, ("PTS_RemoveFromGroup: code %d cid %d gid %d aid %d\n", code, cid, gid, aid));
1086 removeFromGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid,
1089 register afs_int32 code;
1090 struct ubik_trans *tt;
1093 struct prentry uentry;
1094 struct prentry gentry;
1097 if (code != PRSUCCESS)
1099 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1102 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1104 ABORT_WITH(tt, code);
1105 code = read_DbHeader(tt);
1107 ABORT_WITH(tt, code);
1109 code = WhoIsThis(call, tt, cid);
1111 ABORT_WITH(tt, PRPERM);
1112 tempu = FindByID(tt, aid);
1114 ABORT_WITH(tt, PRNOENT);
1115 tempg = FindByID(tt, gid);
1117 ABORT_WITH(tt, PRNOENT);
1118 memset(&uentry, 0, sizeof(uentry));
1119 memset(&gentry, 0, sizeof(gentry));
1120 code = pr_ReadEntry(tt, 0, tempu, &uentry);
1122 ABORT_WITH(tt, code);
1123 code = pr_ReadEntry(tt, 0, tempg, &gentry);
1125 ABORT_WITH(tt, code);
1126 if (!(gentry.flags & PRGRP))
1127 ABORT_WITH(tt, PRNOTGROUP);
1128 #if !defined(SUPERGROUPS)
1129 if (uentry.flags & PRGRP)
1130 ABORT_WITH(tt, PRNOTUSER);
1132 if (!AccessOK(tt, *cid, &gentry, PRP_REMOVE_MEM, 0))
1133 ABORT_WITH(tt, PRPERM);
1134 code = RemoveFromEntry(tt, aid, gid);
1135 if (code != PRSUCCESS)
1136 ABORT_WITH(tt, code);
1137 #if defined(SUPERGROUPS)
1138 if (!(uentry.flags & PRGRP))
1140 code = RemoveFromEntry(tt, gid, aid);
1141 #if defined(SUPERGROUPS)
1143 code = RemoveFromSGEntry(tt, gid, aid);
1145 if (code != PRSUCCESS)
1146 ABORT_WITH(tt, code);
1148 code = ubik_EndTrans(tt);
1156 SPR_GetCPS(struct rx_call *call, afs_int32 aid, prlist *alist, afs_int32 *over)
1159 afs_int32 cid = ANONYMOUSID;
1161 code = getCPS(call, aid, alist, over, &cid);
1162 osi_auditU(call, PTS_GetCPSEvent, code, AUD_ID, aid, AUD_END);
1163 ViceLog(125, ("PTS_GetCPS: code %d cid %d aid %d\n", code, cid, aid));
1168 getCPS(struct rx_call *call, afs_int32 aid, prlist *alist, afs_int32 *over,
1171 register afs_int32 code;
1172 struct ubik_trans *tt;
1174 struct prentry tentry;
1177 alist->prlist_len = 0;
1178 alist->prlist_val = NULL;
1180 if (code != PRSUCCESS)
1182 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1185 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1187 ABORT_WITH(tt, code);
1188 code = read_DbHeader(tt);
1190 ABORT_WITH(tt, code);
1192 temp = FindByID(tt, aid);
1194 ABORT_WITH(tt, PRNOENT);
1195 code = pr_ReadEntry(tt, 0, temp, &tentry);
1197 ABORT_WITH(tt, code);
1199 /* afs does authenticate now */
1200 code = WhoIsThis(call, tt, cid);
1201 if (code || !AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1202 ABORT_WITH(tt, PRPERM);
1204 code = GetList(tt, &tentry, alist, 1);
1205 if (code != PRSUCCESS)
1206 ABORT_WITH(tt, code);
1208 code = ubik_EndTrans(tt);
1215 inCPS(prlist CPS, afs_int32 id)
1219 for (i = (CPS.prlist_len - 1); i >= 0; i--) {
1220 if (CPS.prlist_val[i] == id)
1225 #endif /* IP_WILDCARDS */
1229 SPR_GetCPS2(struct rx_call *call, afs_int32 aid, afs_int32 ahost,
1230 prlist *alist, afs_int32 *over)
1233 afs_int32 cid = ANONYMOUSID;
1235 code = getCPS2(call, aid, ahost, alist, over, &cid);
1236 osi_auditU(call, PTS_GetCPS2Event, code, AUD_ID, aid, AUD_HOST, ahost,
1238 ViceLog(125, ("PTS_GetCPS2: code %d cid %d aid %d ahost %d\n", code, cid, aid, ahost));
1243 getCPS2(struct rx_call *call, afs_int32 aid, afs_int32 ahost, prlist *alist,
1244 afs_int32 *over, afs_int32 *cid)
1246 register afs_int32 code;
1247 struct ubik_trans *tt;
1249 struct prentry tentry;
1250 struct prentry host_tentry;
1253 struct in_addr iaddr;
1256 iaddr.s_addr = ntohl(ahost);
1257 alist->prlist_len = 0;
1258 alist->prlist_val = NULL;
1260 if (code != PRSUCCESS)
1262 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1265 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1267 ABORT_WITH(tt, code);
1268 code = read_DbHeader(tt);
1270 ABORT_WITH(tt, code);
1272 if (aid != PRBADID) {
1273 temp = FindByID(tt, aid);
1275 ABORT_WITH(tt, PRNOENT);
1276 code = pr_ReadEntry(tt, 0, temp, &tentry);
1278 ABORT_WITH(tt, code);
1280 /* afs does authenticate now */
1281 code = WhoIsThis(call, tt, cid);
1283 || !AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1284 ABORT_WITH(tt, PRPERM);
1286 code = NameToID(tt, inet_ntoa(iaddr), &hostid);
1287 if (code == PRSUCCESS && hostid != 0) {
1288 temp = FindByID(tt, hostid);
1290 code = pr_ReadEntry(tt, 0, temp, &host_tentry);
1291 if (code == PRSUCCESS)
1294 fprintf(stderr, "pr_ReadEntry returned %d\n", code);
1296 fprintf(stderr, "FindByID Failed -- Not found\n");
1299 code = GetList2(tt, &tentry, &host_tentry, alist, 1);
1301 code = GetList(tt, &tentry, alist, 1);
1304 code = addWildCards(tt, alist, ntohl(ahost));
1305 #endif /* IP_WILDCARDS */
1306 if (code != PRSUCCESS)
1307 ABORT_WITH(tt, code);
1309 code = ubik_EndTrans(tt);
1315 SPR_GetHostCPS(struct rx_call *call, afs_int32 ahost, prlist *alist,
1320 code = getHostCPS(call, ahost, alist, over);
1321 osi_auditU(call, PTS_GetHCPSEvent, code, AUD_HOST, ahost, AUD_END);
1322 ViceLog(125, ("PTS_GetHostCPS: code %d ahost %d\n", code, ahost));
1327 getHostCPS(struct rx_call *call, afs_int32 ahost, prlist *alist,
1330 register afs_int32 code, temp;
1331 struct ubik_trans *tt;
1332 struct prentry host_tentry;
1334 struct in_addr iaddr;
1337 iaddr.s_addr = ntohl(ahost);
1338 alist->prlist_len = 0;
1339 alist->prlist_val = NULL;
1341 if (code != PRSUCCESS)
1343 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1346 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1348 ABORT_WITH(tt, code);
1349 code = read_DbHeader(tt);
1351 ABORT_WITH(tt, code);
1353 code = NameToID(tt, inet_ntoa(iaddr), &hostid);
1354 if (code == PRSUCCESS && hostid != 0) {
1355 temp = FindByID(tt, hostid);
1357 code = pr_ReadEntry(tt, 0, temp, &host_tentry);
1358 if (code == PRSUCCESS) {
1359 code = GetList(tt, &host_tentry, alist, 0);
1363 fprintf(stderr, "pr_ReadEntry returned %d\n", code);
1365 fprintf(stderr, "FindByID Failed -- Not found\n");
1368 code = addWildCards(tt, alist, ntohl(ahost));
1369 #endif /* IP_WILDCARDS */
1371 if (code != PRSUCCESS)
1372 ABORT_WITH(tt, code);
1374 code = ubik_EndTrans(tt);
1380 SPR_ListMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid)
1384 code = listMax(call, uid, gid);
1385 osi_auditU(call, PTS_LstMaxEvent, code, AUD_END);
1386 ViceLog(125, ("PTS_ListMax: code %d\n", code));
1391 listMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid)
1393 register afs_int32 code;
1394 struct ubik_trans *tt;
1397 if (code != PRSUCCESS)
1399 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1402 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1404 ABORT_WITH(tt, code);
1405 code = read_DbHeader(tt);
1407 ABORT_WITH(tt, code);
1409 code = GetMax(tt, uid, gid);
1410 if (code != PRSUCCESS)
1411 ABORT_WITH(tt, code);
1413 code = ubik_EndTrans(tt);
1420 SPR_SetMax(struct rx_call *call, afs_int32 aid, afs_int32 gflag)
1423 afs_int32 cid = ANONYMOUSID;
1425 code = setMax(call, aid, gflag, &cid);
1426 osi_auditU(call, PTS_SetMaxEvent, code, AUD_ID, aid, AUD_LONG, gflag,
1428 ViceLog(125, ("PTS_SetMax: code %d cid %d aid %d gflag %d\n", code, cid, aid, gflag));
1433 setMax(struct rx_call *call, afs_int32 aid, afs_int32 gflag, afs_int32 *cid)
1435 register afs_int32 code;
1436 struct ubik_trans *tt;
1439 if (code != PRSUCCESS)
1441 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1444 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1446 ABORT_WITH(tt, code);
1447 code = read_DbHeader(tt);
1449 ABORT_WITH(tt, code);
1451 code = WhoIsThis(call, tt, cid);
1453 ABORT_WITH(tt, PRPERM);
1454 if (!AccessOK(tt, *cid, 0, 0, 0))
1455 ABORT_WITH(tt, PRPERM);
1456 if (((gflag & PRGRP) && (aid > 0)) || (!(gflag & PRGRP) && (aid < 0)))
1457 ABORT_WITH(tt, PRBADARG);
1459 code = SetMax(tt, aid, gflag);
1460 if (code != PRSUCCESS)
1461 ABORT_WITH(tt, code);
1463 code = ubik_EndTrans(tt);
1470 SPR_ListEntry(struct rx_call *call, afs_int32 aid, struct prcheckentry *aentry)
1473 afs_int32 cid = ANONYMOUSID;
1475 code = listEntry(call, aid, aentry, &cid);
1476 osi_auditU(call, PTS_LstEntEvent, code, AUD_ID, aid, AUD_END);
1477 ViceLog(125, ("PTS_ListEntry: code %d cid %d aid %d\n", code, cid, aid));
1482 listEntry(struct rx_call *call, afs_int32 aid, struct prcheckentry *aentry,
1485 register afs_int32 code;
1486 struct ubik_trans *tt;
1488 struct prentry tentry;
1491 if (code != PRSUCCESS)
1493 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1496 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1498 ABORT_WITH(tt, code);
1499 code = read_DbHeader(tt);
1501 ABORT_WITH(tt, code);
1503 code = WhoIsThis(call, tt, cid);
1505 ABORT_WITH(tt, PRPERM);
1506 temp = FindByID(tt, aid);
1508 ABORT_WITH(tt, PRNOENT);
1509 code = pr_ReadEntry(tt, 0, temp, &tentry);
1511 ABORT_WITH(tt, code);
1512 if (!AccessOK(tt, *cid, &tentry, PRP_STATUS_MEM, PRP_STATUS_ANY))
1513 ABORT_WITH(tt, PRPERM);
1515 aentry->flags = tentry.flags >> PRIVATE_SHIFT;
1516 if (aentry->flags == 0) {
1517 if (tentry.flags & PRGRP)
1518 aentry->flags = prp_group_default >> PRIVATE_SHIFT;
1520 aentry->flags = prp_user_default >> PRIVATE_SHIFT;
1522 aentry->owner = tentry.owner;
1523 aentry->id = tentry.id;
1524 strncpy(aentry->name, tentry.name, PR_MAXNAMELEN);
1525 aentry->creator = tentry.creator;
1526 aentry->ngroups = tentry.ngroups;
1527 aentry->nusers = tentry.nusers;
1528 aentry->count = tentry.count;
1529 memset(aentry->reserved, 0, sizeof(aentry->reserved));
1530 code = ubik_EndTrans(tt);
1537 SPR_ListEntries(struct rx_call *call, afs_int32 flag, afs_int32 startindex,
1538 prentries *bulkentries, afs_int32 *nextstartindex)
1541 afs_int32 cid = ANONYMOUSID;
1543 code = listEntries(call, flag, startindex, bulkentries, nextstartindex, &cid);
1544 osi_auditU(call, PTS_LstEntsEvent, code, AUD_LONG, flag, AUD_END);
1545 ViceLog(125, ("PTS_ListEntries: code %d cid %d flag %d\n", code, cid, flag));
1550 listEntries(struct rx_call *call, afs_int32 flag, afs_int32 startindex,
1551 prentries *bulkentries, afs_int32 *nextstartindex, afs_int32 *cid)
1554 struct ubik_trans *tt;
1555 afs_int32 i, eof, pos, maxentries, f;
1556 struct prentry tentry;
1557 afs_int32 pollcount = 0;
1559 *nextstartindex = -1;
1560 bulkentries->prentries_val = 0;
1561 bulkentries->prentries_len = 0;
1564 if (code != PRSUCCESS)
1566 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1569 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1571 ABORT_WITH(tt, code);
1572 code = read_DbHeader(tt);
1574 ABORT_WITH(tt, code);
1576 /* Make sure we are an authenticated caller and that we are on the
1579 code = WhoIsThis(call, tt, cid);
1581 ABORT_WITH(tt, PRPERM);
1582 code = IsAMemberOf(tt, *cid, SYSADMINID);
1583 if (!code && !pr_noAuth)
1584 ABORT_WITH(tt, PRPERM);
1586 eof = ntohl(cheader.eofPtr) - sizeof(cheader);
1587 maxentries = eof / sizeof(struct prentry);
1588 for (i = startindex; i < maxentries; i++) {
1589 pos = i * sizeof(struct prentry) + sizeof(cheader);
1590 code = pr_ReadEntry(tt, 0, pos, &tentry);
1594 if (++pollcount > 50) {
1595 #ifndef AFS_PTHREAD_ENV
1601 f = (tentry.flags & PRTYPE);
1602 if (((flag & PRUSERS) && (f == 0)) || /* User entry */
1603 ((flag & PRGROUPS) && (f & PRGRP))) { /* Group entry */
1604 code = put_prentries(&tentry, bulkentries);
1606 break; /* Filled return array */
1613 *nextstartindex = i;
1617 if (bulkentries->prentries_val)
1618 free(bulkentries->prentries_val);
1619 bulkentries->prentries_val = 0;
1620 bulkentries->prentries_len = 0;
1621 ABORT_WITH(tt, code);
1623 code = ubik_EndTrans(tt);
1630 #define PR_MAXENTRIES 500
1632 put_prentries(struct prentry *tentry, prentries *bulkentries)
1634 struct prlistentries *entry;
1636 if (bulkentries->prentries_val == 0) {
1637 bulkentries->prentries_len = 0;
1638 bulkentries->prentries_val =
1639 (struct prlistentries *)malloc(PR_MAXENTRIES *
1640 sizeof(struct prentry));
1641 if (!bulkentries->prentries_val) {
1646 if (bulkentries->prentries_len >= PR_MAXENTRIES) {
1650 entry = (struct prlistentries *)bulkentries->prentries_val;
1651 entry += bulkentries->prentries_len;
1653 entry->flags = tentry->flags >> PRIVATE_SHIFT;
1654 if (entry->flags == 0) {
1657 flags & PRGRP) ? prp_group_default : prp_user_default) >>
1660 entry->owner = tentry->owner;
1661 entry->id = tentry->id;
1662 entry->creator = tentry->creator;
1663 entry->ngroups = tentry->ngroups;
1664 entry->nusers = tentry->nusers;
1665 entry->count = tentry->count;
1666 strncpy(entry->name, tentry->name, PR_MAXNAMELEN);
1667 memset(entry->reserved, 0, sizeof(entry->reserved));
1668 bulkentries->prentries_len++;
1673 SPR_ChangeEntry(struct rx_call *call, afs_int32 aid, char *name, afs_int32 oid,
1677 afs_int32 cid = ANONYMOUSID;
1679 code = changeEntry(call, aid, name, oid, newid, &cid);
1680 osi_auditU(call, PTS_ChgEntEvent, code, AUD_ID, aid, AUD_STR, name,
1681 AUD_LONG, oid, AUD_LONG, newid, AUD_END);
1682 ViceLog(5, ("PTS_ChangeEntry: code %d cid %d aid %d name %s oid %d newid %d\n", code, cid, aid, name, oid, newid));
1687 changeEntry(struct rx_call *call, afs_int32 aid, char *name, afs_int32 oid,
1688 afs_int32 newid, afs_int32 *cid)
1690 register afs_int32 code;
1691 struct ubik_trans *tt;
1701 if (aid == ANYUSERID || aid == AUTHUSERID || aid == ANONYMOUSID
1702 || aid == SYSADMINID)
1704 if (code != PRSUCCESS)
1706 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1709 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1711 ABORT_WITH(tt, code);
1712 code = read_DbHeader(tt);
1714 ABORT_WITH(tt, code);
1716 code = WhoIsThis(call, tt, cid);
1718 ABORT_WITH(tt, PRPERM);
1719 pos = FindByID(tt, aid);
1721 ABORT_WITH(tt, PRNOENT);
1722 /* protection check in changeentry */
1723 code = ChangeEntry(tt, aid, *cid, name, oid, newid);
1724 if (code != PRSUCCESS)
1725 ABORT_WITH(tt, code);
1727 code = ubik_EndTrans(tt);
1732 SPR_SetFieldsEntry(struct rx_call *call,
1734 afs_int32 mask, /* specify which fields to update */
1735 afs_int32 flags, afs_int32 ngroups, afs_int32 nusers,
1736 afs_int32 spare1, afs_int32 spare2)
1739 afs_int32 cid = ANONYMOUSID;
1742 setFieldsEntry(call, id, mask, flags, ngroups, nusers, spare1,
1744 osi_auditU(call, PTS_SetFldEntEvent, code, AUD_ID, id, AUD_END);
1745 ViceLog(5, ("PTS_SetFieldsEntry: code %d cid %d id %d\n", code, cid, id));
1750 setFieldsEntry(struct rx_call *call,
1752 afs_int32 mask, /* specify which fields to update */
1753 afs_int32 flags, afs_int32 ngroups, afs_int32 nusers,
1754 afs_int32 spare1, afs_int32 spare2, afs_int32 *cid)
1756 register afs_int32 code;
1757 struct ubik_trans *tt;
1759 struct prentry tentry;
1763 return 0; /* no-op */
1767 if (id == ANYUSERID || id == AUTHUSERID || id == ANONYMOUSID)
1769 if (code != PRSUCCESS)
1771 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1774 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1776 ABORT_WITH(tt, code);
1777 code = read_DbHeader(tt);
1779 ABORT_WITH(tt, code);
1781 code = WhoIsThis(call, tt, cid);
1783 ABORT_WITH(tt, PRPERM);
1784 pos = FindByID(tt, id);
1786 ABORT_WITH(tt, PRNOENT);
1787 code = pr_ReadEntry(tt, 0, pos, &tentry);
1789 ABORT_WITH(tt, code);
1790 tflags = tentry.flags;
1792 if (mask & (PR_SF_NGROUPS | PR_SF_NUSERS)) {
1793 if (!AccessOK(tt, *cid, 0, 0, 0))
1794 ABORT_WITH(tt, PRPERM);
1795 if ((tflags & PRQUOTA) == 0) { /* default if only setting one */
1796 tentry.ngroups = tentry.nusers = 20;
1799 if (!AccessOK(tt, *cid, &tentry, 0, 0))
1800 ABORT_WITH(tt, PRPERM);
1803 if (mask & 0xffff) { /* if setting flag bits */
1804 afs_int32 flagsMask = mask & 0xffff;
1805 tflags &= ~(flagsMask << PRIVATE_SHIFT);
1806 tflags |= (flags & flagsMask) << PRIVATE_SHIFT;
1810 if (mask & PR_SF_NGROUPS) { /* setting group limit */
1812 ABORT_WITH(tt, PRBADARG);
1813 tentry.ngroups = ngroups;
1817 if (mask & PR_SF_NUSERS) { /* setting foreign user limit */
1819 ABORT_WITH(tt, PRBADARG);
1820 tentry.nusers = nusers;
1823 tentry.flags = tflags;
1825 code = pr_WriteEntry(tt, 0, pos, &tentry);
1827 ABORT_WITH(tt, code);
1829 code = ubik_EndTrans(tt);
1834 SPR_ListElements(struct rx_call *call, afs_int32 aid, prlist *alist,
1838 afs_int32 cid = ANONYMOUSID;
1840 code = listElements(call, aid, alist, over, &cid);
1841 osi_auditU(call, PTS_LstEleEvent, code, AUD_ID, aid, AUD_END);
1842 ViceLog(125, ("PTS_ListElements: code %d cid %d aid %d\n", code, cid, aid));
1847 listElements(struct rx_call *call, afs_int32 aid, prlist *alist,
1848 afs_int32 *over, afs_int32 *cid)
1850 register afs_int32 code;
1851 struct ubik_trans *tt;
1853 struct prentry tentry;
1856 alist->prlist_len = 0;
1857 alist->prlist_val = NULL;
1860 if (code != PRSUCCESS)
1862 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1865 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1867 ABORT_WITH(tt, code);
1868 code = read_DbHeader(tt);
1870 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 = GetList(tt, &tentry, alist, 0);
1886 if (code != PRSUCCESS)
1887 ABORT_WITH(tt, code);
1889 code = ubik_EndTrans(tt);
1895 SPR_ListSuperGroups(struct rx_call *call, afs_int32 aid, prlist *alist,
1898 #if defined(SUPERGROUPS)
1900 afs_int32 cid = ANONYMOUSID;
1902 code = listSuperGroups(call, aid, alist, over, &cid);
1903 osi_auditU(call, PTS_LstSGrps, code, AUD_ID, aid, AUD_END);
1904 ViceLog(125, ("PTS_ListSuperGroups: code %d cid %d aid %d\n", code, cid, aid));
1907 return RXGEN_OPCODE;
1911 #if defined(SUPERGROUPS)
1913 listSuperGroups(struct rx_call *call, afs_int32 aid, prlist *alist,
1914 afs_int32 *over, afs_int32 *cid)
1916 register afs_int32 code;
1917 struct ubik_trans *tt;
1919 struct prentry tentry;
1921 alist->prlist_len = 0;
1922 alist->prlist_val = (afs_int32 *) 0;
1925 if (code != PRSUCCESS)
1927 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1930 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1932 ABORT_WITH(tt, code);
1933 code = WhoIsThis(call, tt, cid);
1935 ABORT_WITH(tt, PRPERM);
1937 temp = FindByID(tt, aid);
1939 ABORT_WITH(tt, PRNOENT);
1940 code = pr_ReadEntry(tt, 0, temp, &tentry);
1942 ABORT_WITH(tt, code);
1943 if (!AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1944 ABORT_WITH(tt, PRPERM);
1946 code = GetSGList(tt, &tentry, alist);
1948 if (code == PRTOOMANY)
1950 else if (code != PRSUCCESS)
1951 ABORT_WITH(tt, code);
1953 code = ubik_EndTrans(tt);
1959 #endif /* SUPERGROUPS */
1963 * List the entries owned by this id. If the id is zero,
1964 * return the orphans list. This will return up to PR_MAXGROUPS
1965 * at a time with the lastP available to get the rest. The
1966 * maximum value is enforced in GetOwnedChain().
1969 SPR_ListOwned(struct rx_call *call, afs_int32 aid, prlist *alist,
1973 afs_int32 cid = ANONYMOUSID;
1975 code = listOwned(call, aid, alist, lastP, &cid);
1976 osi_auditU(call, PTS_LstOwnEvent, code, AUD_ID, aid, AUD_END);
1977 ViceLog(125, ("PTS_ListOwned: code %d cid %d aid %d\n", code, cid, aid));
1982 listOwned(struct rx_call *call, afs_int32 aid, prlist *alist, afs_int32 *lastP,
1985 register afs_int32 code;
1986 struct ubik_trans *tt;
1987 struct prentry tentry;
1991 alist->prlist_len = 0;
1992 alist->prlist_val = NULL;
2000 if (code != PRSUCCESS)
2002 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
2005 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
2007 ABORT_WITH(tt, code);
2008 code = read_DbHeader(tt);
2010 ABORT_WITH(tt, code);
2012 code = WhoIsThis(call, tt, cid);
2014 ABORT_WITH(tt, PRPERM);
2017 code = pr_ReadEntry(tt, 0, start, &tentry);
2018 if (!code && (tentry.owner == aid))
2019 head = start; /* pick up where we left off */
2024 afs_int32 loc = FindByID(tt, aid);
2026 ABORT_WITH(tt, PRNOENT);
2027 code = pr_ReadEntry(tt, 0, loc, &tentry);
2029 ABORT_WITH(tt, code);
2031 if (!AccessOK(tt, *cid, &tentry, -1, PRP_OWNED_ANY))
2032 ABORT_WITH(tt, PRPERM);
2033 head = tentry.owned;
2035 if (!AccessOK(tt, *cid, 0, 0, 0))
2036 ABORT_WITH(tt, PRPERM);
2037 head = ntohl(cheader.orphan);
2041 code = GetOwnedChain(tt, &head, alist);
2043 if (code == PRTOOMANY)
2046 ABORT_WITH(tt, code);
2049 code = ubik_EndTrans(tt);
2054 SPR_IsAMemberOf(struct rx_call *call, afs_int32 uid, afs_int32 gid,
2058 afs_int32 cid = ANONYMOUSID;
2060 code = isAMemberOf(call, uid, gid, flag, &cid);
2061 osi_auditU(call, PTS_IsMemOfEvent, code, AUD_LONG, uid, AUD_LONG, gid,
2063 ViceLog(125, ("PTS_IsAMemberOf: code %d cid %d uid %d gid %d\n", code, cid, uid, gid));
2068 isAMemberOf(struct rx_call *call, afs_int32 uid, afs_int32 gid, afs_int32 *flag,
2071 register afs_int32 code;
2072 struct ubik_trans *tt;
2075 if (code != PRSUCCESS)
2077 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
2080 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
2082 ABORT_WITH(tt, code);
2083 code = read_DbHeader(tt);
2085 ABORT_WITH(tt, code);
2088 afs_int32 uloc = FindByID(tt, uid);
2089 afs_int32 gloc = FindByID(tt, gid);
2090 struct prentry uentry, gentry;
2093 ABORT_WITH(tt, PRNOENT);
2094 code = WhoIsThis(call, tt, cid);
2096 ABORT_WITH(tt, PRPERM);
2097 code = pr_ReadEntry(tt, 0, uloc, &uentry);
2099 ABORT_WITH(tt, code);
2100 code = pr_ReadEntry(tt, 0, gloc, &gentry);
2102 ABORT_WITH(tt, code);
2103 #if !defined(SUPERGROUPS)
2104 if ((uentry.flags & PRGRP) || !(gentry.flags & PRGRP))
2105 ABORT_WITH(tt, PRBADARG);
2107 if (!(gentry.flags & PRGRP))
2108 ABORT_WITH(tt, PRBADARG);
2110 if (!AccessOK(tt, *cid, &uentry, 0, PRP_MEMBER_ANY)
2111 && !AccessOK(tt, *cid, &gentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
2112 ABORT_WITH(tt, PRPERM);
2115 *flag = IsAMemberOf(tt, uid, gid);
2116 code = ubik_EndTrans(tt);
2122 addWildCards(struct ubik_trans *tt, prlist *alist, afs_int32 host)
2125 struct prentry tentry;
2127 unsigned wild = htonl(0xffffff00);
2128 struct in_addr iaddr;
2130 int size = 0, i, code;
2133 while ((host = (host & wild))) {
2134 wild = htonl(ntohl(wild) << 8);
2135 iaddr.s_addr = host;
2136 code = NameToID(tt, inet_ntoa(iaddr), &hostid);
2137 if (code == PRSUCCESS && hostid != 0) {
2138 temp = FindByID(tt, hostid);
2140 code = pr_ReadEntry(tt, 0, temp, &tentry);
2141 if (code != PRSUCCESS)
2147 wlist.prlist_len = 0;
2148 wlist.prlist_val = NULL;
2150 code = GetList(tt, &tentry, &wlist, 0);
2153 added += wlist.prlist_len;
2154 for (i = 0; i < wlist.prlist_len; i++) {
2155 if (!inCPS(*alist, wlist.prlist_val[i]))
2156 if ((code = AddToPRList(alist, &size, wlist.prlist_val[i]))) {
2157 free(wlist.prlist_val);
2161 if (wlist.prlist_val)
2162 free(wlist.prlist_val);
2165 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
2168 #endif /* IP_WILDCARDS */
2171 WhoIsThisWithName(struct rx_call *acall, struct ubik_trans *at, afs_int32 *aid,
2174 /* aid is set to the identity of the caller, if known, else ANONYMOUSID */
2175 /* returns -1 and sets aid to ANONYMOUSID on any failure */
2176 register struct rx_connection *tconn;
2177 register afs_int32 code;
2178 char tcell[MAXKTCREALMLEN];
2179 char name[MAXKTCNAMELEN];
2180 char inst[MAXKTCNAMELEN];
2185 tconn = rx_ConnectionOf(acall);
2186 code = rx_SecurityClassOf(tconn);
2189 else if (code == 1) { /* vab class */
2190 goto done; /* no longer supported */
2191 } else if (code == 2) { /* kad class */
2195 if ((code = rxkad_GetServerInfo(acall->conn, NULL, 0 /*was &exp */ ,
2196 name, inst, tcell, NULL)))
2200 strncpy(vname, name, sizeof(vname));
2201 if ((ilen = strlen(inst))) {
2202 if (strlen(vname) + 1 + ilen >= sizeof(vname))
2205 strcat(vname, inst);
2207 if ((clen = strlen(tcell))) {
2208 int foreign = afs_is_foreign_ticket_name(name,inst,tcell,pr_realmName);
2211 if (strlen(vname) + 1 + clen >= sizeof(vname))
2214 strcat(vname, tcell);
2215 lcstring(vname, vname, sizeof(vname));
2216 code = NameToID(at, vname, aid);
2217 strcpy(aname, vname);
2222 if (strcmp(AUTH_SUPERUSER, vname) == 0)
2223 *aid = SYSADMINID; /* special case for the fileserver */
2225 lcstring(vname, vname, sizeof(vname));
2226 code = NameToID(at, vname, aid);
2230 if (code && !pr_noAuth)