2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
11 * (3) function addToGroup
13 * 1. Eliminate the code that tests for adding groups
14 * to groups. This is an error in normal AFS.
15 * 2. If adding a group to a group call AddToSGEntry
16 * to add the id of the group it's a member of.
20 * 1. Print a messsage if an error is returned from
21 * FindByID() and PTDEBUG is defined.
22 * 2. If removing a group from a group call
23 * RemoveFromSGEntry to remove the id of the
24 * group it's a member of.
25 * 3. Remove supergroup continuation records.
27 * (5) function RemoveFromGroup
29 * 1. Eliminate the code that tests for adding groups
30 * to groups. This is an error in normal AFS.
31 * 2. If removing a group from a group call
32 * RemoveFromSGEntry to remove the id of the
33 * group it's a member of.
35 * (6) Add new functions PR_ListSuperGroups and
38 * (7) function isAMemberOf
40 * 1. Allow groups to be members of groups.
42 * Transarc does not currently use opcodes past 520, but
43 * they *could* decide at any time to use more opcodes.
44 * If they did, then one part of our local mods,
45 * ListSupergroups, would break. I've therefore
46 * renumbered it to 530, and put logic in to enable the
47 * old opcode to work (for now).
50 #include <afsconfig.h>
51 #include <afs/param.h>
60 #include <afs/afsutil.h>
69 #include <netinet/in.h>
70 #include <arpa/inet.h>
75 #include "ptprototypes.h"
76 #include "afs/audit.h"
78 #ifdef AFS_ATHENA_STDENV
83 #define IP_WILDCARDS 1 /* XXX Should be defined outside of here XXX */
85 extern int restricted;
86 extern struct ubik_dbase *dbase;
88 extern afs_int32 initd;
89 extern char *pr_realmName;
90 extern int prp_group_default;
91 extern int prp_user_default;
93 static afs_int32 iNewEntry(struct rx_call *call, char aname[], afs_int32 aid,
94 afs_int32 oid, afs_int32 *cid);
95 static afs_int32 newEntry(struct rx_call *call, char aname[], afs_int32 flag,
96 afs_int32 oid, afs_int32 *aid, afs_int32 *cid);
97 static afs_int32 whereIsIt(struct rx_call *call, afs_int32 aid, afs_int32 *apos,
99 static afs_int32 dumpEntry(struct rx_call *call, afs_int32 apos,
100 struct prdebugentry *aentry, afs_int32 *cid);
101 static afs_int32 addToGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid,
103 static afs_int32 nameToID(struct rx_call *call, namelist *aname, idlist *aid);
104 static afs_int32 idToName(struct rx_call *call, idlist *aid, namelist *aname);
105 static afs_int32 Delete(struct rx_call *call, afs_int32 aid, afs_int32 *cid);
106 static afs_int32 UpdateEntry(struct rx_call *call, afs_int32 aid, char *name,
107 struct PrUpdateEntry *uentry, afs_int32 *cid);
108 static afs_int32 removeFromGroup(struct rx_call *call, afs_int32 aid,
109 afs_int32 gid, afs_int32 *cid);
110 static afs_int32 getCPS(struct rx_call *call, afs_int32 aid, prlist *alist,
111 afs_int32 *over, afs_int32 *cid);
112 static afs_int32 getCPS2(struct rx_call *call, afs_int32 aid, afs_int32 ahost,
113 prlist *alist, afs_int32 *over, afs_int32 *cid);
114 static afs_int32 getHostCPS(struct rx_call *call, afs_int32 ahost,
115 prlist *alist, afs_int32 *over);
116 static afs_int32 listMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid);
117 static afs_int32 setMax(struct rx_call *call, afs_int32 aid, afs_int32 gflag,
119 static afs_int32 listEntry(struct rx_call *call, afs_int32 aid,
120 struct prcheckentry *aentry, afs_int32 *cid);
121 static afs_int32 listEntries(struct rx_call *call, afs_int32 flag,
122 afs_int32 startindex, prentries *bulkentries,
123 afs_int32 *nextstartindex, afs_int32 *cid);
124 static afs_int32 put_prentries(struct prentry *tentry, prentries *bulkentries);
125 static afs_int32 changeEntry(struct rx_call *call, afs_int32 aid, char *name,
126 afs_int32 oid, afs_int32 newid, afs_int32 *cid);
127 static afs_int32 setFieldsEntry(struct rx_call *call, afs_int32 id,
128 afs_int32 mask, afs_int32 flags,
129 afs_int32 ngroups, afs_int32 nusers,
130 afs_int32 spare1, afs_int32 spare2,
132 static afs_int32 listElements(struct rx_call *call, afs_int32 aid,
133 prlist *alist, afs_int32 *over, afs_int32 *cid);
134 #if defined(SUPERGROUPS)
135 static afs_int32 listSuperGroups(struct rx_call *call, afs_int32 aid,
136 prlist *alist, afs_int32 *over,
139 static afs_int32 listOwned(struct rx_call *call, afs_int32 aid, prlist *alist,
140 afs_int32 *lastP, afs_int32 *cid);
141 static afs_int32 isAMemberOf(struct rx_call *call, afs_int32 uid, afs_int32 gid,
142 afs_int32 *flag, afs_int32 *cid);
144 static afs_int32 addWildCards(struct ubik_trans *tt, prlist *alist,
147 static afs_int32 WhoIsThisWithName(struct rx_call *acall,
148 struct ubik_trans *at, afs_int32 *aid,
151 /* When abort, reset initd so that the header is read in on next call.
152 * Abort the transaction and return the code.
154 #define ABORT_WITH(tt,code) return(initd=0,ubik_AbortTrans(tt),code)
157 CreateOK(struct ubik_trans *ut, afs_int32 cid, afs_int32 oid, afs_int32 flag,
160 if (restricted && !admin)
163 if (flag & PRFOREIGN) {
164 /* Foreign users are recognized by the '@' sign and
165 * not by the PRFOREIGN flag.
168 } else if (flag & PRGRP) {
169 /* Allow anonymous group creation only if owner specified
170 * and running noAuth.
172 if (cid == ANONYMOUSID) {
173 if ((oid == 0) || !pr_noAuth)
176 } else { /* creating a user */
177 if (!admin && !pr_noAuth)
184 WhoIsThis(struct rx_call *acall, struct ubik_trans *at, afs_int32 *aid)
187 /* aid is set to the identity of the caller, if known, else ANONYMOUSID */
188 /* returns -1 and sets aid to ANONYMOUSID on any failure */
189 register struct rx_connection *tconn;
190 register afs_int32 code;
191 char tcell[MAXKTCREALMLEN];
192 char name[MAXKTCNAMELEN];
193 char inst[MAXKTCNAMELEN];
198 tconn = rx_ConnectionOf(acall);
199 code = rx_SecurityClassOf(tconn);
202 else if (code == 1) { /* vab class */
203 goto done; /* no longer supported */
204 } else if (code == 2) { /* kad class */
205 if ((code = rxkad_GetServerInfo(acall->conn, NULL, 0 /*was &exp */ ,
206 name, inst, tcell, NULL)))
209 /* This test is unnecessary, since rxkad_GetServerInfo already check.
210 * In addition, this is wrong since exp must be unsigned. */
211 if (exp < FT_ApproxTime())
215 foreign = afs_is_foreign_ticket_name(name,inst,tcell,pr_realmName);
217 strncpy(vname, name, sizeof(vname));
218 if ((ilen = strlen(inst))) {
219 if (strlen(vname) + 1 + ilen >= sizeof(vname))
225 if (strlen(vname) + strlen(tcell) + 1 >= sizeof(vname))
228 strcat(vname, tcell);
230 if (strcmp(AUTH_SUPERUSER, vname) == 0)
231 *aid = SYSADMINID; /* special case for the fileserver */
233 lcstring(vname, vname, sizeof(vname));
234 code = NameToID(at, vname, aid);
238 if (code && !pr_noAuth)
244 SPR_INewEntry(struct rx_call *call, char aname[], afs_int32 aid, afs_int32 oid)
247 afs_int32 cid = ANONYMOUSID;
249 code = iNewEntry(call, aname, aid, oid, &cid);
250 osi_auditU(call, PTS_INewEntEvent, code, AUD_ID, aid, AUD_STR, aname,
251 AUD_ID, oid, AUD_END);
252 ViceLog(5, ("PTS_INewEntry: code %d cid %d aid %d aname %s oid %d\n", code, cid, aid, aname, oid));
257 iNewEntry(struct rx_call *call, char aname[], afs_int32 aid, afs_int32 oid,
260 /* used primarily for conversion - not intended to be used as usual means
261 * of entering people into the database. */
262 struct ubik_trans *tt;
263 register afs_int32 code;
269 if (code != PRSUCCESS)
271 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
274 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
276 ABORT_WITH(tt, code);
277 code = read_DbHeader(tt);
279 ABORT_WITH(tt, code);
281 code = WhoIsThis(call, tt, cid);
283 ABORT_WITH(tt, PRPERM);
284 admin = IsAMemberOf(tt, *cid, SYSADMINID);
286 /* first verify the id is good */
288 ABORT_WITH(tt, PRPERM);
291 /* only sysadmin can reuse a group id */
292 if (!admin && !pr_noAuth && (aid != ntohl(cheader.maxGroup) - 1))
293 ABORT_WITH(tt, PRPERM);
295 if (FindByID(tt, aid))
296 ABORT_WITH(tt, PRIDEXIST);
298 /* check a few other things */
299 if (!CreateOK(tt, *cid, oid, gflag, admin))
300 ABORT_WITH(tt, PRPERM);
302 code = CreateEntry(tt, aname, &aid, 1, gflag, oid, *cid);
303 if (code != PRSUCCESS)
304 ABORT_WITH(tt, code);
306 /* finally, commit transaction */
307 code = ubik_EndTrans(tt);
315 SPR_NewEntry(struct rx_call *call, char aname[], afs_int32 flag, afs_int32 oid,
319 afs_int32 cid = ANONYMOUSID;
321 code = newEntry(call, aname, flag, oid, aid, &cid);
322 osi_auditU(call, PTS_NewEntEvent, code, AUD_ID, *aid, AUD_STR, aname,
323 AUD_ID, oid, AUD_END);
324 ViceLog(5, ("PTS_NewEntry: code %d cid %d aid %d aname %s oid %d\n", code, cid, *aid, aname, oid));
329 newEntry(struct rx_call *call, char aname[], afs_int32 flag, afs_int32 oid,
330 afs_int32 *aid, afs_int32 *cid)
332 register afs_int32 code;
333 struct ubik_trans *tt;
335 char cname[PR_MAXNAMELEN];
340 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
343 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
345 ABORT_WITH(tt, code);
346 code = read_DbHeader(tt);
348 ABORT_WITH(tt, code);
350 /* this is for cross-cell self registration. It is not added in the
351 * SPR_INewEntry because we want self-registration to only do
352 * automatic id assignment.
354 code = WhoIsThisWithName(call, tt, cid, cname);
355 if (code != 2) { /* 2 specifies that this is a foreign cell request */
357 ABORT_WITH(tt, PRPERM);
358 admin = IsAMemberOf(tt, *cid, SYSADMINID);
360 admin = ((!restricted && !strcmp(aname, cname))) || IsAMemberOf(tt, *cid, SYSADMINID);
361 oid = *cid = SYSADMINID;
363 if (!CreateOK(tt, *cid, oid, flag, admin))
364 ABORT_WITH(tt, PRPERM);
366 code = CreateEntry(tt, aname, aid, 0, flag, oid, *cid);
367 if (code != PRSUCCESS)
368 ABORT_WITH(tt, code);
370 code = ubik_EndTrans(tt);
379 SPR_WhereIsIt(struct rx_call *call, afs_int32 aid, afs_int32 *apos)
382 afs_int32 cid = ANONYMOUSID;
384 code = whereIsIt(call, aid, apos, &cid);
385 osi_auditU(call, PTS_WheIsItEvent, code, AUD_ID, aid, AUD_LONG, *apos,
387 ViceLog(125, ("PTS_WhereIsIt: code %d cid %d aid %d apos %d\n", code, cid, aid, *apos));
392 whereIsIt(struct rx_call *call, afs_int32 aid, afs_int32 *apos, afs_int32 *cid)
394 register afs_int32 code;
395 struct ubik_trans *tt;
399 if (code != PRSUCCESS)
401 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
404 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
406 ABORT_WITH(tt, code);
407 code = read_DbHeader(tt);
409 ABORT_WITH(tt, code);
411 code = WhoIsThis(call, tt, cid);
413 ABORT_WITH(tt, PRPERM);
415 temp = FindByID(tt, aid);
417 ABORT_WITH(tt, PRNOENT);
419 code = ubik_EndTrans(tt);
427 SPR_DumpEntry(struct rx_call *call, afs_int32 apos,
428 struct prdebugentry *aentry)
431 afs_int32 cid = ANONYMOUSID;
433 code = dumpEntry(call, apos, aentry, &cid);
434 osi_auditU(call, PTS_DmpEntEvent, code, AUD_LONG, apos, AUD_END);
435 ViceLog(125, ("PTS_DumpEntry: code %d cid %d apos %d\n", code, cid, apos));
440 dumpEntry(struct rx_call *call, afs_int32 apos, struct prdebugentry *aentry,
443 register afs_int32 code;
444 struct ubik_trans *tt;
447 if (code != PRSUCCESS)
449 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
452 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
454 ABORT_WITH(tt, code);
455 code = read_DbHeader(tt);
457 ABORT_WITH(tt, code);
459 code = WhoIsThis(call, tt, cid);
461 ABORT_WITH(tt, PRPERM);
462 code = pr_ReadEntry(tt, 0, apos, (struct prentry *)aentry);
464 ABORT_WITH(tt, code);
466 if (!AccessOK(tt, *cid, 0, PRP_STATUS_MEM, 0))
467 ABORT_WITH(tt, PRPERM);
469 /* Since prdebugentry is in the form of a prentry not a coentry, we will
470 * return the coentry slots in network order where the string is. */
472 if (aentry->flags & PRCONT) { /* wrong type, get coentry instead */
473 code = pr_ReadCoEntry(tt, 0, apos, aentry);
475 ABORT_WITH(tt, code);
478 code = ubik_EndTrans(tt);
485 SPR_AddToGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid)
488 afs_int32 cid = ANONYMOUSID;
490 code = addToGroup(call, aid, gid, &cid);
491 osi_auditU(call, PTS_AdToGrpEvent, code, AUD_ID, gid, AUD_ID, aid,
493 ViceLog(5, ("PTS_AddToGroup: code %d cid %d gid %d aid %d\n", code, cid, gid, aid));
498 addToGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid, afs_int32 *cid)
500 register afs_int32 code;
501 struct ubik_trans *tt;
504 struct prentry tentry;
505 struct prentry uentry;
508 if (code != PRSUCCESS)
510 if (gid == ANYUSERID || gid == AUTHUSERID)
512 if (aid == ANONYMOUSID)
514 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
517 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
519 ABORT_WITH(tt, code);
520 code = read_DbHeader(tt);
522 ABORT_WITH(tt, code);
524 code = WhoIsThis(call, tt, cid);
526 ABORT_WITH(tt, PRPERM);
527 tempu = FindByID(tt, aid);
529 ABORT_WITH(tt, PRNOENT);
530 memset(&uentry, 0, sizeof(uentry));
531 code = pr_ReadEntry(tt, 0, tempu, &uentry);
533 ABORT_WITH(tt, code);
535 #if !defined(SUPERGROUPS)
536 /* we don't allow groups as members of groups at present */
537 if (uentry.flags & PRGRP)
538 ABORT_WITH(tt, PRNOTUSER);
541 tempg = FindByID(tt, gid);
543 ABORT_WITH(tt, PRNOENT);
544 code = pr_ReadEntry(tt, 0, tempg, &tentry);
546 ABORT_WITH(tt, code);
547 /* make sure that this is a group */
548 if (!(tentry.flags & PRGRP))
549 ABORT_WITH(tt, PRNOTGROUP);
550 if (!AccessOK(tt, *cid, &tentry, PRP_ADD_MEM, PRP_ADD_ANY))
551 ABORT_WITH(tt, PRPERM);
553 code = AddToEntry(tt, &tentry, tempg, aid);
554 if (code != PRSUCCESS)
555 ABORT_WITH(tt, code);
557 #if defined(SUPERGROUPS)
558 if (uentry.flags & PRGRP)
559 code = AddToSGEntry(tt, &uentry, tempu, gid); /* mod group to be in sg */
562 /* now, modify the user's entry as well */
563 code = AddToEntry(tt, &uentry, tempu, gid);
564 if (code != PRSUCCESS)
565 ABORT_WITH(tt, code);
566 code = ubik_EndTrans(tt);
573 SPR_NameToID(struct rx_call *call, namelist *aname, idlist *aid)
577 code = nameToID(call, aname, aid);
578 osi_auditU(call, PTS_NmToIdEvent, code, AUD_END);
579 ViceLog(125, ("PTS_NameToID: code %d\n", code));
584 nameToID(struct rx_call *call, namelist *aname, idlist *aid)
586 register afs_int32 code;
587 struct ubik_trans *tt;
592 /* Initialize return struct */
594 aid->idlist_val = NULL;
596 size = aname->namelist_len;
602 aid->idlist_val = (afs_int32 *) malloc(size * sizeof(afs_int32));
603 if (!aid->idlist_val)
607 if (code != PRSUCCESS)
609 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
612 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
614 ABORT_WITH(tt, code);
615 code = read_DbHeader(tt);
617 ABORT_WITH(tt, code);
619 for (i = 0; i < aname->namelist_len; i++) {
621 char *nameinst, *cell;
623 strncpy(vname, aname->namelist_val[i], sizeof(vname));
624 vname[sizeof(vname)-1] ='\0';
627 cell = strchr(vname, '@');
633 if (cell && afs_is_foreign_ticket_name(nameinst,NULL,cell,pr_realmName))
634 code = NameToID(tt, aname->namelist_val[i], &aid->idlist_val[i]);
636 code = NameToID(tt, nameinst, &aid->idlist_val[i]);
638 if (code != PRSUCCESS)
639 aid->idlist_val[i] = ANONYMOUSID;
640 osi_audit(PTS_NmToIdEvent, code, AUD_STR,
641 aname->namelist_val[i], AUD_ID, aid->idlist_val[i],
643 ViceLog(125, ("PTS_NameToID: code %d aname %s aid %d\n", code,
644 aname->namelist_val[i], aid->idlist_val[i]));
646 #ifndef AFS_PTHREAD_ENV
652 aid->idlist_len = aname->namelist_len;
654 code = ubik_EndTrans(tt);
662 * Given an array of ids, find the name for each of them.
663 * The array of ids and names is unlimited.
666 SPR_IDToName(struct rx_call *call, idlist *aid, namelist *aname)
670 code = idToName(call, aid, aname);
671 osi_auditU(call, PTS_IdToNmEvent, code, AUD_END);
672 ViceLog(125, ("PTS_IDToName: code %d\n", code));
677 idToName(struct rx_call *call, idlist *aid, namelist *aname)
679 register afs_int32 code;
680 struct ubik_trans *tt;
685 /* leave this first for rpc stub */
686 size = aid->idlist_len;
691 aname->namelist_val = (prname *) malloc(size * PR_MAXNAMELEN);
692 aname->namelist_len = 0;
693 if (aname->namelist_val == 0)
695 if (aid->idlist_len == 0)
698 return PRTOOMANY; /* rxgen will probably handle this */
701 if (code != PRSUCCESS)
703 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
706 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
708 ABORT_WITH(tt, code);
709 code = read_DbHeader(tt);
711 ABORT_WITH(tt, code);
713 for (i = 0; i < aid->idlist_len; i++) {
714 code = IDToName(tt, aid->idlist_val[i], aname->namelist_val[i]);
715 if (code != PRSUCCESS)
716 sprintf(aname->namelist_val[i], "%d", aid->idlist_val[i]);
717 osi_audit(PTS_IdToNmEvent, code, AUD_ID, aid->idlist_val[i],
718 AUD_STR, aname->namelist_val[i], AUD_END);
719 ViceLog(125, ("PTS_idToName: code %d aid %d aname %s\n", code,
720 aid->idlist_val[i], aname->namelist_val[i]));
722 #ifndef AFS_PTHREAD_ENV
728 aname->namelist_len = aid->idlist_len;
730 code = ubik_EndTrans(tt);
737 SPR_Delete(struct rx_call *call, afs_int32 aid)
740 afs_int32 cid = ANONYMOUSID;
742 code = Delete(call, aid, &cid);
743 osi_auditU(call, PTS_DelEvent, code, AUD_ID, aid, AUD_END);
744 ViceLog(5, ("PTS_Delete: code %d cid %d aid %d\n", code, cid, aid));
749 Delete(struct rx_call *call, afs_int32 aid, afs_int32 *cid)
751 register afs_int32 code;
752 struct ubik_trans *tt;
753 struct prentry tentry;
760 if (code != PRSUCCESS)
762 if (aid == SYSADMINID || aid == ANYUSERID || aid == AUTHUSERID
763 || aid == ANONYMOUSID)
765 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
768 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
770 ABORT_WITH(tt, code);
771 code = read_DbHeader(tt);
773 ABORT_WITH(tt, code);
775 code = WhoIsThis(call, tt, cid);
777 ABORT_WITH(tt, PRPERM);
779 /* Read in entry to be deleted */
780 loc = FindByID(tt, aid);
782 ABORT_WITH(tt, PRNOENT);
783 code = pr_ReadEntry(tt, 0, loc, &tentry);
785 ABORT_WITH(tt, PRDBFAIL);
787 /* Do some access checking */
788 if (tentry.owner != *cid && !IsAMemberOf(tt, *cid, SYSADMINID)
789 && !IsAMemberOf(tt, *cid, tentry.owner) && !pr_noAuth)
790 ABORT_WITH(tt, PRPERM);
792 /* Delete each continuation block as a separate transaction so that no one
793 * transaction become to large to complete. */
795 while (nptr != (afs_int32) NULL) {
796 struct contentry centry;
799 code = pr_ReadCoEntry(tt, 0, nptr, ¢ry);
801 ABORT_WITH(tt, PRDBFAIL);
802 for (i = 0; i < COSIZE; i++) {
803 if (centry.entries[i] == PRBADID)
805 if (centry.entries[i] == 0)
807 #if defined(SUPERGROUPS)
808 if (aid < 0 && centry.entries[i] < 0) /* Supergroup */
809 code = RemoveFromSGEntry(tt, aid, centry.entries[i]);
812 code = RemoveFromEntry(tt, aid, centry.entries[i]);
814 ABORT_WITH(tt, code);
815 tentry.count--; /* maintain count */
816 #ifndef AFS_PTHREAD_ENV
821 tentry.next = centry.next; /* thread out this block */
822 code = FreeBlock(tt, nptr); /* free continuation block */
824 ABORT_WITH(tt, code);
825 code = pr_WriteEntry(tt, 0, loc, &tentry); /* update main entry */
827 ABORT_WITH(tt, code);
829 /* end this trans and start a new one */
830 code = ubik_EndTrans(tt);
833 #ifndef AFS_PTHREAD_ENV
834 IOMGR_Poll(); /* just to keep the connection alive */
836 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
839 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
841 ABORT_WITH(tt, code);
843 /* re-read entry to get consistent uptodate info */
844 loc = FindByID(tt, aid);
846 ABORT_WITH(tt, PRNOENT);
847 code = pr_ReadEntry(tt, 0, loc, &tentry);
849 ABORT_WITH(tt, PRDBFAIL);
854 #if defined(SUPERGROUPS)
855 /* Delete each continuation block as a separate transaction
856 * so that no one transaction become too large to complete. */
858 struct prentryg *tentryg = (struct prentryg *)&tentry;
859 nptr = tentryg->nextsg;
860 while (nptr != NULL) {
861 struct contentry centry;
864 code = pr_ReadCoEntry(tt, 0, nptr, ¢ry);
866 ABORT_WITH(tt, PRDBFAIL);
867 for (i = 0; i < COSIZE; i++) {
868 if (centry.entries[i] == PRBADID)
870 if (centry.entries[i] == 0)
872 code = RemoveFromEntry(tt, aid, centry.entries[i]);
874 ABORT_WITH(tt, code);
875 tentryg->countsg--; /* maintain count */
876 #ifndef AFS_PTHREAD_ENV
881 tentryg->nextsg = centry.next; /* thread out this block */
882 code = FreeBlock(tt, nptr); /* free continuation block */
884 ABORT_WITH(tt, code);
885 code = pr_WriteEntry(tt, 0, loc, &tentry); /* update main entry */
887 ABORT_WITH(tt, code);
889 /* end this trans and start a new one */
890 code = ubik_EndTrans(tt);
893 #ifndef AFS_PTHREAD_ENV
894 IOMGR_Poll(); /* just to keep the connection alive */
897 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
900 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
902 ABORT_WITH(tt, code);
904 /* re-read entry to get consistent uptodate info */
905 loc = FindByID(tt, aid);
907 ABORT_WITH(tt, PRNOENT);
908 code = pr_ReadEntry(tt, 0, loc, &tentry);
910 ABORT_WITH(tt, PRDBFAIL);
912 nptr = tentryg->nextsg;
916 #endif /* SUPERGROUPS */
918 /* Then move the owned chain, except possibly ourself to the orphan list.
919 * Because this list can be very long and so exceed the size of a ubik
920 * transaction, we start a new transaction every 50 entries. */
923 while (nptr != (afs_int32) NULL) {
924 struct prentry nentry;
926 code = pr_ReadEntry(tt, 0, nptr, &nentry);
928 ABORT_WITH(tt, PRDBFAIL);
929 nptr = tentry.owned = nentry.nextOwned; /* thread out */
931 if (nentry.id != tentry.id) { /* don't add us to orphan chain! */
932 code = AddToOrphan(tt, nentry.id);
934 ABORT_WITH(tt, code);
936 #ifndef AFS_PTHREAD_ENV
937 if ((count & 3) == 0)
943 code = pr_WriteEntry(tt, 0, loc, &tentry); /* update main entry */
945 ABORT_WITH(tt, code);
947 /* end this trans and start a new one */
948 code = ubik_EndTrans(tt);
951 #ifndef AFS_PTHREAD_ENV
952 IOMGR_Poll(); /* just to keep the connection alive */
954 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
957 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
959 ABORT_WITH(tt, code);
961 /* re-read entry to get consistent uptodate info */
962 loc = FindByID(tt, aid);
964 ABORT_WITH(tt, PRNOENT);
965 code = pr_ReadEntry(tt, 0, loc, &tentry);
967 ABORT_WITH(tt, PRDBFAIL);
972 /* now do what's left of the deletion stuff */
973 code = DeleteEntry(tt, &tentry, loc);
974 if (code != PRSUCCESS)
975 ABORT_WITH(tt, code);
977 code = ubik_EndTrans(tt);
984 SPR_UpdateEntry(struct rx_call *call, afs_int32 aid, char *name,
985 struct PrUpdateEntry *uentry)
988 afs_int32 cid = ANONYMOUSID;
990 code = UpdateEntry(call, aid, name, uentry, &cid);
991 osi_auditU(call, PTS_UpdEntEvent, code, AUD_ID, aid, AUD_STR, name, AUD_END);
992 ViceLog(5, ("PTS_UpdateEntry: code %d cid %d aid %d name %s\n", code, cid, aid, name));
997 UpdateEntry(struct rx_call *call, afs_int32 aid, char *name,
998 struct PrUpdateEntry *uentry, afs_int32 *cid)
1000 register afs_int32 code;
1001 struct ubik_trans *tt;
1002 struct prentry tentry;
1009 if (code != PRSUCCESS)
1013 if (aid == SYSADMINID || aid == ANYUSERID || aid == AUTHUSERID
1014 || aid == ANONYMOUSID)
1017 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1020 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1022 ABORT_WITH(tt, code);
1023 code = read_DbHeader(tt);
1025 ABORT_WITH(tt, code);
1027 code = WhoIsThis(call, tt, cid);
1029 ABORT_WITH(tt, PRPERM);
1030 code = IsAMemberOf(tt, *cid, SYSADMINID);
1031 if (!code && !pr_noAuth)
1032 ABORT_WITH(tt, PRPERM);
1034 /* Read in entry to be deleted */
1036 loc = FindByID(tt, aid);
1038 loc = FindByName(tt, name, &tentry);
1041 ABORT_WITH(tt, PRNOENT);
1042 code = pr_ReadEntry(tt, 0, loc, &tentry);
1044 ABORT_WITH(tt, PRDBFAIL);
1046 if (uentry->Mask & PRUPDATE_NAMEHASH) {
1048 code = RemoveFromNameHash(tt, tentry.name, &tloc);
1049 if (code != PRSUCCESS)
1050 ABORT_WITH(tt, PRDBFAIL);
1051 code = AddToNameHash(tt, tentry.name, loc);
1053 ABORT_WITH(tt, code);
1056 if (uentry->Mask & PRUPDATE_IDHASH) {
1060 code = RemoveFromIDHash(tt, id, &tloc);
1061 if (code != PRSUCCESS)
1062 ABORT_WITH(tt, PRDBFAIL);
1063 code = AddToIDHash(tt, id, loc);
1065 ABORT_WITH(tt, code);
1068 code = ubik_EndTrans(tt);
1075 SPR_RemoveFromGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid)
1078 afs_int32 cid = ANONYMOUSID;
1080 code = removeFromGroup(call, aid, gid, &cid);
1081 osi_auditU(call, PTS_RmFmGrpEvent, code, AUD_ID, gid, AUD_ID, aid,
1083 ViceLog(5, ("PTS_RemoveFromGroup: code %d cid %d gid %d aid %d\n", code, cid, gid, aid));
1088 removeFromGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid,
1091 register afs_int32 code;
1092 struct ubik_trans *tt;
1095 struct prentry uentry;
1096 struct prentry gentry;
1099 if (code != PRSUCCESS)
1101 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1104 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1106 ABORT_WITH(tt, code);
1107 code = read_DbHeader(tt);
1109 ABORT_WITH(tt, code);
1111 code = WhoIsThis(call, tt, cid);
1113 ABORT_WITH(tt, PRPERM);
1114 tempu = FindByID(tt, aid);
1116 ABORT_WITH(tt, PRNOENT);
1117 tempg = FindByID(tt, gid);
1119 ABORT_WITH(tt, PRNOENT);
1120 memset(&uentry, 0, sizeof(uentry));
1121 memset(&gentry, 0, sizeof(gentry));
1122 code = pr_ReadEntry(tt, 0, tempu, &uentry);
1124 ABORT_WITH(tt, code);
1125 code = pr_ReadEntry(tt, 0, tempg, &gentry);
1127 ABORT_WITH(tt, code);
1128 if (!(gentry.flags & PRGRP))
1129 ABORT_WITH(tt, PRNOTGROUP);
1130 #if !defined(SUPERGROUPS)
1131 if (uentry.flags & PRGRP)
1132 ABORT_WITH(tt, PRNOTUSER);
1134 if (!AccessOK(tt, *cid, &gentry, PRP_REMOVE_MEM, 0))
1135 ABORT_WITH(tt, PRPERM);
1136 code = RemoveFromEntry(tt, aid, gid);
1137 if (code != PRSUCCESS)
1138 ABORT_WITH(tt, code);
1139 #if defined(SUPERGROUPS)
1140 if (!(uentry.flags & PRGRP))
1142 code = RemoveFromEntry(tt, gid, aid);
1143 #if defined(SUPERGROUPS)
1145 code = RemoveFromSGEntry(tt, gid, aid);
1147 if (code != PRSUCCESS)
1148 ABORT_WITH(tt, code);
1150 code = ubik_EndTrans(tt);
1158 SPR_GetCPS(struct rx_call *call, afs_int32 aid, prlist *alist, afs_int32 *over)
1161 afs_int32 cid = ANONYMOUSID;
1163 code = getCPS(call, aid, alist, over, &cid);
1164 osi_auditU(call, PTS_GetCPSEvent, code, AUD_ID, aid, AUD_END);
1165 ViceLog(125, ("PTS_GetCPS: code %d cid %d aid %d\n", code, cid, aid));
1170 getCPS(struct rx_call *call, afs_int32 aid, prlist *alist, afs_int32 *over,
1173 register afs_int32 code;
1174 struct ubik_trans *tt;
1176 struct prentry tentry;
1179 alist->prlist_len = 0;
1180 alist->prlist_val = NULL;
1182 if (code != PRSUCCESS)
1184 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1187 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1189 ABORT_WITH(tt, code);
1190 code = read_DbHeader(tt);
1192 ABORT_WITH(tt, code);
1194 temp = FindByID(tt, aid);
1196 ABORT_WITH(tt, PRNOENT);
1197 code = pr_ReadEntry(tt, 0, temp, &tentry);
1199 ABORT_WITH(tt, code);
1201 /* afs does authenticate now */
1202 code = WhoIsThis(call, tt, cid);
1203 if (code || !AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1204 ABORT_WITH(tt, PRPERM);
1206 code = GetList(tt, &tentry, alist, 1);
1207 if (code != PRSUCCESS)
1208 ABORT_WITH(tt, code);
1210 code = ubik_EndTrans(tt);
1217 inCPS(prlist CPS, afs_int32 id)
1221 for (i = (CPS.prlist_len - 1); i >= 0; i--) {
1222 if (CPS.prlist_val[i] == id)
1227 #endif /* IP_WILDCARDS */
1231 SPR_GetCPS2(struct rx_call *call, afs_int32 aid, afs_int32 ahost,
1232 prlist *alist, afs_int32 *over)
1235 afs_int32 cid = ANONYMOUSID;
1237 code = getCPS2(call, aid, ahost, alist, over, &cid);
1238 osi_auditU(call, PTS_GetCPS2Event, code, AUD_ID, aid, AUD_HOST, ahost,
1240 ViceLog(125, ("PTS_GetCPS2: code %d cid %d aid %d ahost %d\n", code, cid, aid, ahost));
1245 getCPS2(struct rx_call *call, afs_int32 aid, afs_int32 ahost, prlist *alist,
1246 afs_int32 *over, afs_int32 *cid)
1248 register afs_int32 code;
1249 struct ubik_trans *tt;
1251 struct prentry tentry;
1252 struct prentry host_tentry;
1255 struct in_addr iaddr;
1258 iaddr.s_addr = ntohl(ahost);
1259 alist->prlist_len = 0;
1260 alist->prlist_val = NULL;
1262 if (code != PRSUCCESS)
1264 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1267 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1269 ABORT_WITH(tt, code);
1270 code = read_DbHeader(tt);
1272 ABORT_WITH(tt, code);
1274 if (aid != PRBADID) {
1275 temp = FindByID(tt, aid);
1277 ABORT_WITH(tt, PRNOENT);
1278 code = pr_ReadEntry(tt, 0, temp, &tentry);
1280 ABORT_WITH(tt, code);
1282 /* afs does authenticate now */
1283 code = WhoIsThis(call, tt, cid);
1285 || !AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1286 ABORT_WITH(tt, PRPERM);
1288 code = NameToID(tt, inet_ntoa(iaddr), &hostid);
1289 if (code == PRSUCCESS && hostid != 0) {
1290 temp = FindByID(tt, hostid);
1292 code = pr_ReadEntry(tt, 0, temp, &host_tentry);
1293 if (code == PRSUCCESS)
1296 fprintf(stderr, "pr_ReadEntry returned %d\n", code);
1298 fprintf(stderr, "FindByID Failed -- Not found\n");
1301 code = GetList2(tt, &tentry, &host_tentry, alist, 1);
1303 code = GetList(tt, &tentry, alist, 1);
1306 code = addWildCards(tt, alist, ntohl(ahost));
1307 #endif /* IP_WILDCARDS */
1308 if (code != PRSUCCESS)
1309 ABORT_WITH(tt, code);
1311 code = ubik_EndTrans(tt);
1317 SPR_GetHostCPS(struct rx_call *call, afs_int32 ahost, prlist *alist,
1322 code = getHostCPS(call, ahost, alist, over);
1323 osi_auditU(call, PTS_GetHCPSEvent, code, AUD_HOST, ahost, AUD_END);
1324 ViceLog(125, ("PTS_GetHostCPS: code %d ahost %d\n", code, ahost));
1329 getHostCPS(struct rx_call *call, afs_int32 ahost, prlist *alist,
1332 register afs_int32 code, temp;
1333 struct ubik_trans *tt;
1334 struct prentry host_tentry;
1336 struct in_addr iaddr;
1339 iaddr.s_addr = ntohl(ahost);
1340 alist->prlist_len = 0;
1341 alist->prlist_val = NULL;
1343 if (code != PRSUCCESS)
1345 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1348 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1350 ABORT_WITH(tt, code);
1351 code = read_DbHeader(tt);
1353 ABORT_WITH(tt, code);
1355 code = NameToID(tt, inet_ntoa(iaddr), &hostid);
1356 if (code == PRSUCCESS && hostid != 0) {
1357 temp = FindByID(tt, hostid);
1359 code = pr_ReadEntry(tt, 0, temp, &host_tentry);
1360 if (code == PRSUCCESS) {
1361 code = GetList(tt, &host_tentry, alist, 0);
1365 fprintf(stderr, "pr_ReadEntry returned %d\n", code);
1367 fprintf(stderr, "FindByID Failed -- Not found\n");
1370 code = addWildCards(tt, alist, ntohl(ahost));
1371 #endif /* IP_WILDCARDS */
1373 if (code != PRSUCCESS)
1374 ABORT_WITH(tt, code);
1376 code = ubik_EndTrans(tt);
1382 SPR_ListMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid)
1386 code = listMax(call, uid, gid);
1387 osi_auditU(call, PTS_LstMaxEvent, code, AUD_END);
1388 ViceLog(125, ("PTS_ListMax: code %d\n", code));
1393 listMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid)
1395 register afs_int32 code;
1396 struct ubik_trans *tt;
1399 if (code != PRSUCCESS)
1401 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1404 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1406 ABORT_WITH(tt, code);
1407 code = read_DbHeader(tt);
1409 ABORT_WITH(tt, code);
1411 code = GetMax(tt, uid, gid);
1412 if (code != PRSUCCESS)
1413 ABORT_WITH(tt, code);
1415 code = ubik_EndTrans(tt);
1422 SPR_SetMax(struct rx_call *call, afs_int32 aid, afs_int32 gflag)
1425 afs_int32 cid = ANONYMOUSID;
1427 code = setMax(call, aid, gflag, &cid);
1428 osi_auditU(call, PTS_SetMaxEvent, code, AUD_ID, aid, AUD_LONG, gflag,
1430 ViceLog(125, ("PTS_SetMax: code %d cid %d aid %d gflag %d\n", code, cid, aid, gflag));
1435 setMax(struct rx_call *call, afs_int32 aid, afs_int32 gflag, afs_int32 *cid)
1437 register afs_int32 code;
1438 struct ubik_trans *tt;
1441 if (code != PRSUCCESS)
1443 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1446 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1448 ABORT_WITH(tt, code);
1449 code = read_DbHeader(tt);
1451 ABORT_WITH(tt, code);
1453 code = WhoIsThis(call, tt, cid);
1455 ABORT_WITH(tt, PRPERM);
1456 if (!AccessOK(tt, *cid, 0, 0, 0))
1457 ABORT_WITH(tt, PRPERM);
1458 if (((gflag & PRGRP) && (aid > 0)) || (!(gflag & PRGRP) && (aid < 0)))
1459 ABORT_WITH(tt, PRBADARG);
1461 code = SetMax(tt, aid, gflag);
1462 if (code != PRSUCCESS)
1463 ABORT_WITH(tt, code);
1465 code = ubik_EndTrans(tt);
1472 SPR_ListEntry(struct rx_call *call, afs_int32 aid, struct prcheckentry *aentry)
1475 afs_int32 cid = ANONYMOUSID;
1477 code = listEntry(call, aid, aentry, &cid);
1478 osi_auditU(call, PTS_LstEntEvent, code, AUD_ID, aid, AUD_END);
1479 ViceLog(125, ("PTS_ListEntry: code %d cid %d aid %d\n", code, cid, aid));
1484 listEntry(struct rx_call *call, afs_int32 aid, struct prcheckentry *aentry,
1487 register afs_int32 code;
1488 struct ubik_trans *tt;
1490 struct prentry tentry;
1493 if (code != PRSUCCESS)
1495 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1498 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1500 ABORT_WITH(tt, code);
1501 code = read_DbHeader(tt);
1503 ABORT_WITH(tt, code);
1505 code = WhoIsThis(call, tt, cid);
1507 ABORT_WITH(tt, PRPERM);
1508 temp = FindByID(tt, aid);
1510 ABORT_WITH(tt, PRNOENT);
1511 code = pr_ReadEntry(tt, 0, temp, &tentry);
1513 ABORT_WITH(tt, code);
1514 if (!AccessOK(tt, *cid, &tentry, PRP_STATUS_MEM, PRP_STATUS_ANY))
1515 ABORT_WITH(tt, PRPERM);
1517 aentry->flags = tentry.flags >> PRIVATE_SHIFT;
1518 if (aentry->flags == 0) {
1519 if (tentry.flags & PRGRP)
1520 aentry->flags = prp_group_default >> PRIVATE_SHIFT;
1522 aentry->flags = prp_user_default >> PRIVATE_SHIFT;
1524 aentry->owner = tentry.owner;
1525 aentry->id = tentry.id;
1526 strncpy(aentry->name, tentry.name, PR_MAXNAMELEN);
1527 aentry->creator = tentry.creator;
1528 aentry->ngroups = tentry.ngroups;
1529 aentry->nusers = tentry.nusers;
1530 aentry->count = tentry.count;
1531 memset(aentry->reserved, 0, sizeof(aentry->reserved));
1532 code = ubik_EndTrans(tt);
1539 SPR_ListEntries(struct rx_call *call, afs_int32 flag, afs_int32 startindex,
1540 prentries *bulkentries, afs_int32 *nextstartindex)
1543 afs_int32 cid = ANONYMOUSID;
1545 code = listEntries(call, flag, startindex, bulkentries, nextstartindex, &cid);
1546 osi_auditU(call, PTS_LstEntsEvent, code, AUD_LONG, flag, AUD_END);
1547 ViceLog(125, ("PTS_ListEntries: code %d cid %d flag %d\n", code, cid, flag));
1552 listEntries(struct rx_call *call, afs_int32 flag, afs_int32 startindex,
1553 prentries *bulkentries, afs_int32 *nextstartindex, afs_int32 *cid)
1556 struct ubik_trans *tt;
1557 afs_int32 i, eof, pos, maxentries, f;
1558 struct prentry tentry;
1559 afs_int32 pollcount = 0;
1561 *nextstartindex = -1;
1562 bulkentries->prentries_val = 0;
1563 bulkentries->prentries_len = 0;
1566 if (code != PRSUCCESS)
1568 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1571 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1573 ABORT_WITH(tt, code);
1574 code = read_DbHeader(tt);
1576 ABORT_WITH(tt, code);
1578 /* Make sure we are an authenticated caller and that we are on the
1581 code = WhoIsThis(call, tt, cid);
1583 ABORT_WITH(tt, PRPERM);
1584 code = IsAMemberOf(tt, *cid, SYSADMINID);
1585 if (!code && !pr_noAuth)
1586 ABORT_WITH(tt, PRPERM);
1588 eof = ntohl(cheader.eofPtr) - sizeof(cheader);
1589 maxentries = eof / sizeof(struct prentry);
1590 for (i = startindex; i < maxentries; i++) {
1591 pos = i * sizeof(struct prentry) + sizeof(cheader);
1592 code = pr_ReadEntry(tt, 0, pos, &tentry);
1596 if (++pollcount > 50) {
1597 #ifndef AFS_PTHREAD_ENV
1603 f = (tentry.flags & PRTYPE);
1604 if (((flag & PRUSERS) && (f == 0)) || /* User entry */
1605 ((flag & PRGROUPS) && (f & PRGRP))) { /* Group entry */
1606 code = put_prentries(&tentry, bulkentries);
1608 break; /* Filled return array */
1615 *nextstartindex = i;
1619 if (bulkentries->prentries_val)
1620 free(bulkentries->prentries_val);
1621 bulkentries->prentries_val = 0;
1622 bulkentries->prentries_len = 0;
1623 ABORT_WITH(tt, code);
1625 code = ubik_EndTrans(tt);
1632 #define PR_MAXENTRIES 500
1634 put_prentries(struct prentry *tentry, prentries *bulkentries)
1636 struct prlistentries *entry;
1638 if (bulkentries->prentries_val == 0) {
1639 bulkentries->prentries_len = 0;
1640 bulkentries->prentries_val =
1641 (struct prlistentries *)malloc(PR_MAXENTRIES *
1642 sizeof(struct prentry));
1643 if (!bulkentries->prentries_val) {
1648 if (bulkentries->prentries_len >= PR_MAXENTRIES) {
1652 entry = (struct prlistentries *)bulkentries->prentries_val;
1653 entry += bulkentries->prentries_len;
1655 entry->flags = tentry->flags >> PRIVATE_SHIFT;
1656 if (entry->flags == 0) {
1659 flags & PRGRP) ? prp_group_default : prp_user_default) >>
1662 entry->owner = tentry->owner;
1663 entry->id = tentry->id;
1664 entry->creator = tentry->creator;
1665 entry->ngroups = tentry->ngroups;
1666 entry->nusers = tentry->nusers;
1667 entry->count = tentry->count;
1668 strncpy(entry->name, tentry->name, PR_MAXNAMELEN);
1669 memset(entry->reserved, 0, sizeof(entry->reserved));
1670 bulkentries->prentries_len++;
1675 SPR_ChangeEntry(struct rx_call *call, afs_int32 aid, char *name, afs_int32 oid,
1679 afs_int32 cid = ANONYMOUSID;
1681 code = changeEntry(call, aid, name, oid, newid, &cid);
1682 osi_auditU(call, PTS_ChgEntEvent, code, AUD_ID, aid, AUD_STR, name,
1683 AUD_LONG, oid, AUD_LONG, newid, AUD_END);
1684 ViceLog(5, ("PTS_ChangeEntry: code %d cid %d aid %d name %s oid %d newid %d\n", code, cid, aid, name, oid, newid));
1689 changeEntry(struct rx_call *call, afs_int32 aid, char *name, afs_int32 oid,
1690 afs_int32 newid, afs_int32 *cid)
1692 register afs_int32 code;
1693 struct ubik_trans *tt;
1703 if (aid == ANYUSERID || aid == AUTHUSERID || aid == ANONYMOUSID
1704 || aid == SYSADMINID)
1706 if (code != PRSUCCESS)
1708 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1711 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1713 ABORT_WITH(tt, code);
1714 code = read_DbHeader(tt);
1716 ABORT_WITH(tt, code);
1718 code = WhoIsThis(call, tt, cid);
1720 ABORT_WITH(tt, PRPERM);
1721 pos = FindByID(tt, aid);
1723 ABORT_WITH(tt, PRNOENT);
1724 /* protection check in changeentry */
1725 code = ChangeEntry(tt, aid, *cid, name, oid, newid);
1726 if (code != PRSUCCESS)
1727 ABORT_WITH(tt, code);
1729 code = ubik_EndTrans(tt);
1734 SPR_SetFieldsEntry(struct rx_call *call,
1736 afs_int32 mask, /* specify which fields to update */
1737 afs_int32 flags, afs_int32 ngroups, afs_int32 nusers,
1738 afs_int32 spare1, afs_int32 spare2)
1741 afs_int32 cid = ANONYMOUSID;
1744 setFieldsEntry(call, id, mask, flags, ngroups, nusers, spare1,
1746 osi_auditU(call, PTS_SetFldEntEvent, code, AUD_ID, id, AUD_END);
1747 ViceLog(5, ("PTS_SetFieldsEntry: code %d cid %d id %d\n", code, cid, id));
1752 setFieldsEntry(struct rx_call *call,
1754 afs_int32 mask, /* specify which fields to update */
1755 afs_int32 flags, afs_int32 ngroups, afs_int32 nusers,
1756 afs_int32 spare1, afs_int32 spare2, afs_int32 *cid)
1758 register afs_int32 code;
1759 struct ubik_trans *tt;
1761 struct prentry tentry;
1765 return 0; /* no-op */
1769 if (id == ANYUSERID || id == AUTHUSERID || id == ANONYMOUSID)
1771 if (code != PRSUCCESS)
1773 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1776 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1778 ABORT_WITH(tt, code);
1779 code = read_DbHeader(tt);
1781 ABORT_WITH(tt, code);
1783 code = WhoIsThis(call, tt, cid);
1785 ABORT_WITH(tt, PRPERM);
1786 pos = FindByID(tt, id);
1788 ABORT_WITH(tt, PRNOENT);
1789 code = pr_ReadEntry(tt, 0, pos, &tentry);
1791 ABORT_WITH(tt, code);
1792 tflags = tentry.flags;
1794 if (mask & (PR_SF_NGROUPS | PR_SF_NUSERS)) {
1795 if (!AccessOK(tt, *cid, 0, 0, 0))
1796 ABORT_WITH(tt, PRPERM);
1797 if ((tflags & PRQUOTA) == 0) { /* default if only setting one */
1798 tentry.ngroups = tentry.nusers = 20;
1801 if (!AccessOK(tt, *cid, &tentry, 0, 0))
1802 ABORT_WITH(tt, PRPERM);
1805 if (mask & 0xffff) { /* if setting flag bits */
1806 afs_int32 flagsMask = mask & 0xffff;
1807 tflags &= ~(flagsMask << PRIVATE_SHIFT);
1808 tflags |= (flags & flagsMask) << PRIVATE_SHIFT;
1812 if (mask & PR_SF_NGROUPS) { /* setting group limit */
1814 ABORT_WITH(tt, PRBADARG);
1815 tentry.ngroups = ngroups;
1819 if (mask & PR_SF_NUSERS) { /* setting foreign user limit */
1821 ABORT_WITH(tt, PRBADARG);
1822 tentry.nusers = nusers;
1825 tentry.flags = tflags;
1827 code = pr_WriteEntry(tt, 0, pos, &tentry);
1829 ABORT_WITH(tt, code);
1831 code = ubik_EndTrans(tt);
1836 SPR_ListElements(struct rx_call *call, afs_int32 aid, prlist *alist,
1840 afs_int32 cid = ANONYMOUSID;
1842 code = listElements(call, aid, alist, over, &cid);
1843 osi_auditU(call, PTS_LstEleEvent, code, AUD_ID, aid, AUD_END);
1844 ViceLog(125, ("PTS_ListElements: code %d cid %d aid %d\n", code, cid, aid));
1849 listElements(struct rx_call *call, afs_int32 aid, prlist *alist,
1850 afs_int32 *over, afs_int32 *cid)
1852 register afs_int32 code;
1853 struct ubik_trans *tt;
1855 struct prentry tentry;
1858 alist->prlist_len = 0;
1859 alist->prlist_val = NULL;
1862 if (code != PRSUCCESS)
1864 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1867 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1869 ABORT_WITH(tt, code);
1870 code = read_DbHeader(tt);
1872 ABORT_WITH(tt, code);
1874 code = WhoIsThis(call, tt, cid);
1876 ABORT_WITH(tt, PRPERM);
1878 temp = FindByID(tt, aid);
1880 ABORT_WITH(tt, PRNOENT);
1881 code = pr_ReadEntry(tt, 0, temp, &tentry);
1883 ABORT_WITH(tt, code);
1884 if (!AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1885 ABORT_WITH(tt, PRPERM);
1887 code = GetList(tt, &tentry, alist, 0);
1888 if (code != PRSUCCESS)
1889 ABORT_WITH(tt, code);
1891 code = ubik_EndTrans(tt);
1897 SPR_ListSuperGroups(struct rx_call *call, afs_int32 aid, prlist *alist,
1900 #if defined(SUPERGROUPS)
1902 afs_int32 cid = ANONYMOUSID;
1904 code = listSuperGroups(call, aid, alist, over, &cid);
1905 osi_auditU(call, PTS_LstSGrps, code, AUD_ID, aid, AUD_END);
1906 ViceLog(125, ("PTS_ListSuperGroups: code %d cid %d aid %d\n", code, cid, aid));
1909 return RXGEN_OPCODE;
1913 #if defined(SUPERGROUPS)
1915 listSuperGroups(struct rx_call *call, afs_int32 aid, prlist *alist,
1916 afs_int32 *over, afs_int32 *cid)
1918 register afs_int32 code;
1919 struct ubik_trans *tt;
1921 struct prentry tentry;
1923 alist->prlist_len = 0;
1924 alist->prlist_val = (afs_int32 *) 0;
1927 if (code != PRSUCCESS)
1929 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1932 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1934 ABORT_WITH(tt, code);
1935 code = WhoIsThis(call, tt, cid);
1937 ABORT_WITH(tt, PRPERM);
1939 temp = FindByID(tt, aid);
1941 ABORT_WITH(tt, PRNOENT);
1942 code = pr_ReadEntry(tt, 0, temp, &tentry);
1944 ABORT_WITH(tt, code);
1945 if (!AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
1946 ABORT_WITH(tt, PRPERM);
1948 code = GetSGList(tt, &tentry, alist);
1950 if (code == PRTOOMANY)
1952 else if (code != PRSUCCESS)
1953 ABORT_WITH(tt, code);
1955 code = ubik_EndTrans(tt);
1961 #endif /* SUPERGROUPS */
1965 * List the entries owned by this id. If the id is zero,
1966 * return the orphans list. This will return up to PR_MAXGROUPS
1967 * at a time with the lastP available to get the rest. The
1968 * maximum value is enforced in GetOwnedChain().
1971 SPR_ListOwned(struct rx_call *call, afs_int32 aid, prlist *alist,
1975 afs_int32 cid = ANONYMOUSID;
1977 code = listOwned(call, aid, alist, lastP, &cid);
1978 osi_auditU(call, PTS_LstOwnEvent, code, AUD_ID, aid, AUD_END);
1979 ViceLog(125, ("PTS_ListOwned: code %d cid %d aid %d\n", code, cid, aid));
1984 listOwned(struct rx_call *call, afs_int32 aid, prlist *alist, afs_int32 *lastP,
1987 register afs_int32 code;
1988 struct ubik_trans *tt;
1989 struct prentry tentry;
1993 alist->prlist_len = 0;
1994 alist->prlist_val = NULL;
2002 if (code != PRSUCCESS)
2004 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
2007 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
2009 ABORT_WITH(tt, code);
2010 code = read_DbHeader(tt);
2012 ABORT_WITH(tt, code);
2014 code = WhoIsThis(call, tt, cid);
2016 ABORT_WITH(tt, PRPERM);
2019 code = pr_ReadEntry(tt, 0, start, &tentry);
2020 if (!code && (tentry.owner == aid))
2021 head = start; /* pick up where we left off */
2026 afs_int32 loc = FindByID(tt, aid);
2028 ABORT_WITH(tt, PRNOENT);
2029 code = pr_ReadEntry(tt, 0, loc, &tentry);
2031 ABORT_WITH(tt, code);
2033 if (!AccessOK(tt, *cid, &tentry, -1, PRP_OWNED_ANY))
2034 ABORT_WITH(tt, PRPERM);
2035 head = tentry.owned;
2037 if (!AccessOK(tt, *cid, 0, 0, 0))
2038 ABORT_WITH(tt, PRPERM);
2039 head = ntohl(cheader.orphan);
2043 code = GetOwnedChain(tt, &head, alist);
2045 if (code == PRTOOMANY)
2048 ABORT_WITH(tt, code);
2051 code = ubik_EndTrans(tt);
2056 SPR_IsAMemberOf(struct rx_call *call, afs_int32 uid, afs_int32 gid,
2060 afs_int32 cid = ANONYMOUSID;
2062 code = isAMemberOf(call, uid, gid, flag, &cid);
2063 osi_auditU(call, PTS_IsMemOfEvent, code, AUD_LONG, uid, AUD_LONG, gid,
2065 ViceLog(125, ("PTS_IsAMemberOf: code %d cid %d uid %d gid %d\n", code, cid, uid, gid));
2070 isAMemberOf(struct rx_call *call, afs_int32 uid, afs_int32 gid, afs_int32 *flag,
2073 register afs_int32 code;
2074 struct ubik_trans *tt;
2077 if (code != PRSUCCESS)
2079 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
2082 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
2084 ABORT_WITH(tt, code);
2085 code = read_DbHeader(tt);
2087 ABORT_WITH(tt, code);
2090 afs_int32 uloc = FindByID(tt, uid);
2091 afs_int32 gloc = FindByID(tt, gid);
2092 struct prentry uentry, gentry;
2095 ABORT_WITH(tt, PRNOENT);
2096 code = WhoIsThis(call, tt, cid);
2098 ABORT_WITH(tt, PRPERM);
2099 code = pr_ReadEntry(tt, 0, uloc, &uentry);
2101 ABORT_WITH(tt, code);
2102 code = pr_ReadEntry(tt, 0, gloc, &gentry);
2104 ABORT_WITH(tt, code);
2105 #if !defined(SUPERGROUPS)
2106 if ((uentry.flags & PRGRP) || !(gentry.flags & PRGRP))
2107 ABORT_WITH(tt, PRBADARG);
2109 if (!(gentry.flags & PRGRP))
2110 ABORT_WITH(tt, PRBADARG);
2112 if (!AccessOK(tt, *cid, &uentry, 0, PRP_MEMBER_ANY)
2113 && !AccessOK(tt, *cid, &gentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
2114 ABORT_WITH(tt, PRPERM);
2117 *flag = IsAMemberOf(tt, uid, gid);
2118 code = ubik_EndTrans(tt);
2124 addWildCards(struct ubik_trans *tt, prlist *alist, afs_int32 host)
2127 struct prentry tentry;
2129 unsigned wild = htonl(0xffffff00);
2130 struct in_addr iaddr;
2132 int size = 0, i, code;
2135 while ((host = (host & wild))) {
2136 wild = htonl(ntohl(wild) << 8);
2137 iaddr.s_addr = host;
2138 code = NameToID(tt, inet_ntoa(iaddr), &hostid);
2139 if (code == PRSUCCESS && hostid != 0) {
2140 temp = FindByID(tt, hostid);
2142 code = pr_ReadEntry(tt, 0, temp, &tentry);
2143 if (code != PRSUCCESS)
2149 wlist.prlist_len = 0;
2150 wlist.prlist_val = NULL;
2152 code = GetList(tt, &tentry, &wlist, 0);
2155 added += wlist.prlist_len;
2156 for (i = 0; i < wlist.prlist_len; i++) {
2157 if (!inCPS(*alist, wlist.prlist_val[i]))
2158 if ((code = AddToPRList(alist, &size, wlist.prlist_val[i]))) {
2159 free(wlist.prlist_val);
2163 if (wlist.prlist_val)
2164 free(wlist.prlist_val);
2167 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
2170 #endif /* IP_WILDCARDS */
2173 WhoIsThisWithName(struct rx_call *acall, struct ubik_trans *at, afs_int32 *aid,
2176 /* aid is set to the identity of the caller, if known, else ANONYMOUSID */
2177 /* returns -1 and sets aid to ANONYMOUSID on any failure */
2178 register struct rx_connection *tconn;
2179 register afs_int32 code;
2180 char tcell[MAXKTCREALMLEN];
2181 char name[MAXKTCNAMELEN];
2182 char inst[MAXKTCNAMELEN];
2187 tconn = rx_ConnectionOf(acall);
2188 code = rx_SecurityClassOf(tconn);
2191 else if (code == 1) { /* vab class */
2192 goto done; /* no longer supported */
2193 } else if (code == 2) { /* kad class */
2197 if ((code = rxkad_GetServerInfo(acall->conn, NULL, 0 /*was &exp */ ,
2198 name, inst, tcell, NULL)))
2202 strncpy(vname, name, sizeof(vname));
2203 if ((ilen = strlen(inst))) {
2204 if (strlen(vname) + 1 + ilen >= sizeof(vname))
2207 strcat(vname, inst);
2209 if ((clen = strlen(tcell))) {
2210 int foreign = afs_is_foreign_ticket_name(name,inst,tcell,pr_realmName);
2213 if (strlen(vname) + 1 + clen >= sizeof(vname))
2216 strcat(vname, tcell);
2217 lcstring(vname, vname, sizeof(vname));
2218 code = NameToID(at, vname, aid);
2219 strcpy(aname, vname);
2224 if (strcmp(AUTH_SUPERUSER, vname) == 0)
2225 *aid = SYSADMINID; /* special case for the fileserver */
2227 lcstring(vname, vname, sizeof(vname));
2228 code = NameToID(at, vname, aid);
2232 if (code && !pr_noAuth)