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 * (5) Add functions to process supergroups:
12 * ChangeIDEntry(), RemoveFromSGEntry(),
13 * AddToSGEntry(), GetListSG2().
14 * (6) Add code to existing functions to process
16 * 2/1/98 jjm Add mdw's changes for bit mapping for supergroups
18 * 09/26/02 kwc Move depthsg definition here from ptserver.c since
19 * pt_util needs it defined also, and this file is
20 * common between the two programs.
23 #include <afsconfig.h>
24 #include <afs/param.h>
28 #include <sys/types.h>
33 #include <netinet/in.h>
39 #include <afs/com_err.h>
40 #include <afs/cellconfig.h>
43 #include "ptprototypes.h"
46 /* Foreign cells are represented by the group system:authuser@cell*/
47 #define AUTHUSER_GROUP "system:authuser"
49 extern int restricted;
50 extern struct ubik_dbase *dbase;
51 extern struct afsconf_dir *prdir;
54 static int inRange(struct prentry *cellEntry, afs_int32 aid);
55 static afs_int32 allocNextId(struct ubik_trans *, struct prentry *);
56 static int AddAuthGroup(struct prentry *tentry, prlist *alist, afs_int32 *size);
58 static char *whoami = "ptserver";
60 int prp_user_default = PRP_USER_DEFAULT;
61 int prp_group_default = PRP_GROUP_DEFAULT;
63 #if defined(SUPERGROUPS)
67 afs_int32 depthsg = 5; /* Maximum iterations used during IsAMemberOF */
68 afs_int32 GetListSG2(struct ubik_trans *at, afs_int32 gid, prlist * alist,
69 afs_int32 * sizeP, afs_int32 depth);
71 struct map *sg_flagged;
74 #define NIL_MAP ((struct map *) 0)
76 /* pt_mywrite hooks into the logic that writes ubik records to disk
77 * at a very low level. It invalidates mappings in sg_flagged/sg_found.
78 * By hoooking in at this level, we ensure that a ubik file reload
79 * invalidates our incore cache.
81 * We assert records, cheaders and everything else are 0 mod 64.
82 * So, we can always see the first 64 bytes of any record written.
83 * The stuff we're interested in (flags, id) are in the first 8 bytes.
84 * so we can always tell if we're writing a group record.
87 int (*pt_save_dbase_write)(struct ubik_dbase *, afs_int32, void *, afs_int32,
91 pt_mywrite(struct ubik_dbase *tdb, afs_int32 fno, void *bp, afs_int32 pos, afs_int32 count)
93 afs_uint32 headersize = ntohl(cheader.headerSize);
95 if (fno == 0 && pos + count > headersize) {
110 #define xPT(p,x) ((((struct prentry *)(p))->flags & htonl(PRTYPE)) == htonl(x))
113 fprintf(stderr, "Writing %d bytes of entry @ %#lx(+%d)\n", c,
115 else if (c == ENTRYSIZE)
117 "Writing %d bytes of entry @ %#lx (%d<%s>,%d)\n",
118 c, p, ntohl(((struct prentry *)cp)->flags),
119 xPT(cp,PRUSER) ? "user" : xPT(cp,PRFREE) ? "free" :
120 xPT(cp,PRGRP) ? "group" : xPT(cp,PRCONT) ? "cont" :
121 xPT(cp,PRCELL) ? "cell" : xPT(cp,PRFOREIGN) ? "foreign" :
122 xPT(cp,PRINST) ? "sub/super instance" : "?",
123 ntohl(((struct prentry *)cp)->id));
126 "Writing first %d bytes of entry @ %#lx (%d<%s>,%d)\n",
127 c, p, ntohl(((struct prentry *)cp)->flags),
128 xPT(cp,PRUSER) ? "user" : xPT(cp,PRFREE) ? "free" :
129 xPT(cp,PRGRP) ? "group" : xPT(cp,PRCONT) ? "cont" :
130 xPT(cp,PRCELL) ? "cell" : xPT(cp,PRFOREIGN) ? "foreign" :
131 xPT(cp,PRINST) ? "sub/super instance" : "?",
132 ntohl(((struct prentry *)cp)->id));
134 fprintf(stderr, "Writing %d bytes of entry @ %#lx\n", c, p);
136 if (!o && c >= 8 && xPT(cp,PRGRP)) {
138 if (in_map(sg_found, -ntohl(((struct prentry *)cp)->id)))
139 fprintf(stderr, "Unfound: Removing group %d\n",
140 ntohl(((struct prentry *)cp)->id));
141 if (in_map(sg_flagged, -ntohl(((struct prentry *)cp)->id)))
142 fprintf(stderr, "Unflag: Removing group %d\n",
143 ntohl(((struct prentry *)cp)->id));
147 add_map(NIL_MAP, -ntohl(((struct prentry *)cp)->id)));
150 add_map(NIL_MAP, -ntohl(((struct prentry *)cp)->id)));
158 return (*pt_save_dbase_write) (tdb, fno, bp, pos, count);
162 * this function attaches pt_mywrite. It's called once,
163 * just after ubik_ServerInit.
169 extern struct ubik_dbase *ubik_dbase;
170 if (ubik_dbase->write != pt_mywrite) {
171 pt_save_dbase_write = ubik_dbase->write;
172 ubik_dbase->write = pt_mywrite;
176 #endif /* SUPERGROUPS */
178 /* CorrectUserName - Check to make sure a user name is OK. It must not include
179 * either a colon (or it would look like a group) or an atsign (or it would
180 * look like a foreign user). The length is checked as well to make sure
181 * that the user name, an atsign, and the local cell name will fit in
182 * PR_MAXNAMELEN. This is so this user can fit in another cells database as
183 * a foreign user with our cell name tacked on. This is a predicate, so it
184 * return one if name is OK and zero if name is bogus. */
187 CorrectUserName(char *name)
189 extern int pr_realmNameLen;
191 /* We accept foreign names, so we will deal with '@' later */
192 if (strchr(name, ':') || strchr(name, '\n'))
194 if (strchr(name, '@')) {
195 /* foreign user; we don't need to worry about pr_realmNameLen, since
196 * our local realm name will never be appended to this */
197 if (strlen(name) >= PR_MAXNAMELEN) {
201 if (strlen(name) >= PR_MAXNAMELEN - pr_realmNameLen - 1)
207 /* CorrectGroupName - Like the above but handles more complicated cases caused
208 * by including the ownership in the name. The interface works by calculating
209 * the correct name based on a given name and owner. This allows easy use by
210 * rename, which then compares the correct name with the requested new name. */
213 CorrectGroupName(struct ubik_trans *ut, char aname[PR_MAXNAMELEN], /* name for group */
214 afs_int32 cid, /* caller id */
215 afs_int32 oid, /* owner of group */
216 char cname[PR_MAXNAMELEN]) /* correct name for group */
220 char *prefix; /* ptr to group owner part */
221 char *suffix; /* ptr to group name part */
222 char name[PR_MAXNAMELEN]; /* correct name for group */
223 struct prentry tentry;
225 if (strlen(aname) >= PR_MAXNAMELEN)
227 admin = pr_noAuth || IsAMemberOf(ut, cid, SYSADMINID);
232 /* Determine the correct prefix for the name. */
233 if (oid == SYSADMINID)
236 afs_int32 loc = FindByID(ut, oid);
238 /* let admin create groups owned by non-existent ids (probably
239 * setting a group to own itself). Check that they look like
240 * groups (with a colon) or otherwise are good user names. */
242 strcpy(cname, aname);
247 code = pr_Read(ut, 0, loc, &tentry, sizeof(tentry));
250 if (ntohl(tentry.flags) & PRGRP) {
251 if ((tentry.count == 0) && !admin)
253 /* terminate prefix at colon if there is one */
254 if ((prefix = strchr(tentry.name, ':')))
257 prefix = tentry.name;
259 /* only sysadmin allow to use 'system:' prefix */
260 if ((strcmp(prefix, "system") == 0) && !admin)
263 strcpy(name, aname); /* in case aname & cname are same */
264 suffix = strchr(name, ':');
266 /* sysadmin can make groups w/o ':', but they must still look like
267 * legal user names. */
272 if (strlen(prefix) + strlen(suffix) >= PR_MAXNAMELEN)
274 strcpy(cname, prefix);
275 strcat(cname, suffix);
278 /* check for legal name with either group rules or user rules */
279 if ((suffix = strchr(cname, ':'))) {
280 /* check for confusing characters */
281 if (strchr(cname, '\n') || /* restrict so recreate can work */
282 strchr(suffix + 1, ':')) /* avoid multiple colons */
285 if (!CorrectUserName(cname))
292 AccessOK(struct ubik_trans *ut, afs_int32 cid, /* caller id */
293 struct prentry *tentry, /* object being accessed */
294 int mem, /* check membership in aid, if group */
295 int any) /* if set return true */
303 if (cid == SYSADMINID)
304 return 1; /* special case fileserver */
305 if (restricted && ((mem == PRP_ADD_MEM) || (mem == PRP_REMOVE_MEM)) && (any == 0))
308 flags = tentry->flags;
312 flags = oid = aid = 0;
314 if (!(flags & PRACCESS)) { /* provide default access */
316 flags |= prp_group_default;
318 flags |= prp_user_default;
324 if ((cid == oid) || IsAMemberOf(ut, cid, oid))
327 if (aid > 0) { /* checking on a user */
330 } else if (aid < 0) { /* checking on group */
331 if ((flags & mem) && IsAMemberOf(ut, cid, aid))
334 /* Allow members of SYSVIEWERID to get membership and status only */
335 if (((mem == PRP_STATUS_MEM) || (mem == PRP_MEMBER_MEM)
336 || (any == PRP_OWNED_ANY)) && (IsAMemberOf(ut, cid, SYSVIEWERID)))
338 if (IsAMemberOf(ut, cid, SYSADMINID))
340 return 0; /* no access */
344 CreateEntry(struct ubik_trans *at, char aname[PR_MAXNAMELEN], afs_int32 *aid, afs_int32 idflag, afs_int32 flag, afs_int32 oid, afs_int32 creator)
346 /* get and init a new entry */
349 struct prentry tentry, tent;
352 memset(&tentry, 0, sizeof(tentry));
354 if ((oid == 0) || (oid == ANONYMOUSID))
358 code = CorrectGroupName(at, aname, creator, oid, tentry.name);
361 if (strcmp(aname, tentry.name) != 0)
363 } else { /* non-group must not have colon */
364 if (!CorrectUserName(aname))
366 strcpy(tentry.name, aname);
369 if (FindByName(at, aname, &tent))
372 newEntry = AllocBlock(at);
375 #ifdef PR_REMEMBER_TIMES
376 tentry.createTime = time(0);
380 tentry.flags = PRGRP;
382 } else if (flag == 0) {
384 tentry.owner = SYSADMINID;
389 atsign = strchr(aname, '@');
391 /* A normal user or group. Pick an id for it */
395 code = AllocID(at, flag, &tentry.id);
396 if (code != PRSUCCESS)
399 } else if (flag & PRGRP) {
400 /* A foreign group. Its format must be AUTHUSER_GROUP@cellname
401 * Then pick an id for the group.
406 badFormat = strcmp(AUTHUSER_GROUP, aname);
414 code = AllocID(at, flag, &tentry.id);
415 if (code != PRSUCCESS)
419 /* A foreign user: <name>@<cell>. The foreign user is added to
420 * its representing group. It is
424 struct prentry centry;
426 /* To create the user <name>@<cell> the group AUTHUSER_GROUP@<cell>
430 (char *)malloc(strlen(AUTHUSER_GROUP) + strlen(atsign) + 1);
431 strcpy(cellGroup, AUTHUSER_GROUP);
432 strcat(cellGroup, atsign);
433 pos = FindByName(at, cellGroup, ¢ry);
437 code = pr_Read(at, 0, pos, ¢ry, sizeof(centry));
441 /* cellid is the id of the group representing the cell */
442 tentry.cellid = ntohl(centry.id);
445 /* Check if id is good */
446 if (!inRange(¢ry, *aid))
450 /* Allocate an ID special for this foreign user. It is based
451 * on the representing group's id and nusers count.
453 tentry.id = allocNextId(at, ¢ry);
458 /* The foreign user will be added to the representing foreign
459 * group. The group can hold up to 30 entries.
461 if (!(ntohl(centry.flags) & PRQUOTA)) {
462 centry.flags = htonl(ntohl(centry.flags) | PRQUOTA);
463 centry.ngroups = htonl(30);
465 n = ntohl(centry.ngroups);
466 if ((n <= 0) && !pr_noAuth)
468 centry.ngroups = htonl(n - 1);
470 /* write updated entry for group */
471 code = pr_Write(at, 0, pos, ¢ry, sizeof(centry));
473 /* Now add the new user entry to the database */
474 tentry.creator = creator;
476 code = pr_WriteEntry(at, 0, newEntry, &tentry);
479 code = AddToIDHash(at, *aid, newEntry);
480 if (code != PRSUCCESS)
482 code = AddToNameHash(at, aname, newEntry);
483 if (code != PRSUCCESS)
485 if (inc_header_word(at, foreigncount, 1))
488 /* Now add the entry to the authuser group for this cell.
489 * We will reread the entries for the user and the group
490 * instead of modifying them before writing them in the
491 * previous steps. Although not very efficient, much simpler
493 pos = FindByID(at, tentry.cellid);
496 code = pr_ReadEntry(at, 0, pos, ¢ry);
499 code = AddToEntry(at, ¢ry, pos, *aid);
502 /* and now the user entry */
503 pos = FindByID(at, *aid);
506 code = pr_ReadEntry(at, 0, pos, &tentry);
509 code = AddToEntry(at, &tentry, pos, tentry.cellid);
516 /* Remember the largest group id or largest user id */
518 /* group ids are negative */
519 if (tentry.id < (afs_int32) ntohl(cheader.maxGroup)) {
520 code = set_header_word(at, maxGroup, htonl(tentry.id));
525 if (tentry.id > (afs_int32) ntohl(cheader.maxID)) {
526 code = set_header_word(at, maxID, htonl(tentry.id));
532 /* Charge the creator for this group */
534 afs_int32 loc = FindByID(at, creator);
535 struct prentry centry;
538 if (loc) { /* this should only fail during initialization */
539 code = pr_Read(at, 0, loc, ¢ry, sizeof(centry));
543 /* If quota is uninitialized, do it */
544 if (!(ntohl(centry.flags) & PRQUOTA)) {
545 centry.flags = htonl(ntohl(centry.flags) | PRQUOTA);
546 centry.ngroups = centry.nusers = htonl(20);
549 /* Admins don't get charged for creating a group.
550 * If in noAuth mode, you get changed for it but you
551 * are still allowed to create as many groups as you want.
553 admin = ((creator == SYSADMINID)
554 || IsAMemberOf(at, creator, SYSADMINID));
556 if (ntohl(centry.ngroups) <= 0) {
560 centry.ngroups = htonl(ntohl(centry.ngroups) - 1);
564 code = pr_Write(at, 0, loc, ¢ry, sizeof(centry));
569 /* Initialize the quota for the user. Groups don't have their
572 tentry.flags |= PRQUOTA;
573 tentry.ngroups = tentry.nusers = 20;
576 tentry.creator = creator;
578 code = pr_WriteEntry(at, 0, newEntry, &tentry);
581 code = AddToIDHash(at, *aid, newEntry);
582 if (code != PRSUCCESS)
584 code = AddToNameHash(at, aname, newEntry);
585 if (code != PRSUCCESS)
587 if (tentry.flags & PRGRP) {
588 code = AddToOwnerChain(at, tentry.id, oid);
592 if (tentry.flags & PRGRP) {
593 if (inc_header_word(at, groupcount, 1))
595 } else if (tentry.flags & PRINST) {
596 if (inc_header_word(at, instcount, 1))
599 if (inc_header_word(at, usercount, 1))
606 /* RemoveFromEntry - remove aid from bid's entries list, freeing a continuation
607 * entry if appropriate */
610 RemoveFromEntry(struct ubik_trans *at, afs_int32 aid, afs_int32 bid)
613 struct prentry tentry;
614 struct contentry centry;
615 struct contentry hentry;
622 return PRINCONSISTENT;
623 memset(&hentry, 0, sizeof(hentry));
624 temp = FindByID(at, bid);
627 code = pr_ReadEntry(at, 0, temp, &tentry);
630 #ifdef PR_REMEMBER_TIMES
631 tentry.removeTime = time(0);
633 for (i = 0; i < PRSIZE; i++) {
634 if (tentry.entries[i] == aid) {
635 tentry.entries[i] = PRBADID;
637 code = pr_WriteEntry(at, 0, temp, &tentry);
642 if (tentry.entries[i] == 0) /* found end of list */
648 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
651 if ((centry.id != bid) || !(centry.flags & PRCONT))
653 for (i = 0; i < COSIZE; i++) {
654 if (centry.entries[i] == aid) {
655 centry.entries[i] = PRBADID;
656 for (j = 0; j < COSIZE; j++)
657 if (centry.entries[j] != PRBADID
658 && centry.entries[j] != 0)
660 if (j == COSIZE) { /* can free this block */
662 tentry.next = centry.next;
664 hentry.next = centry.next;
665 code = pr_WriteCoEntry(at, 0, hloc, &hentry);
669 code = FreeBlock(at, nptr);
672 } else { /* can't free it yet */
673 code = pr_WriteCoEntry(at, 0, nptr, ¢ry);
678 code = pr_WriteEntry(at, 0, temp, &tentry);
683 if (centry.entries[i] == 0)
685 } /* for all coentry slots */
688 memcpy(&hentry, ¢ry, sizeof(centry));
689 } /* while there are coentries */
693 #if defined(SUPERGROUPS)
694 /* ChangeIDEntry - remove aid from bid's entries list, freeing a continuation
695 * entry if appropriate */
698 ChangeIDEntry(register struct ubik_trans *at, register afs_int32 aid, afs_int32 newid, register afs_int32 bid)
700 register afs_int32 code;
701 struct prentry tentry;
702 struct contentry centry;
708 return PRINCONSISTENT;
709 temp = FindByID(at, bid);
713 code = pr_ReadEntry(at, 0, temp, &tentry);
716 for (i = 0; i < PRSIZE; i++) {
717 if (tentry.entries[i] == aid) {
718 tentry.entries[i] = newid;
719 code = pr_WriteEntry(at, 0, temp, &tentry);
724 if (tentry.entries[i] == 0) { /* found end of list */
731 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
734 if ((centry.id != bid) || !(centry.flags & PRCONT)) {
736 "ChangeIDEntry: bad database bid=%d centry.id=%d .flags=%d\n",
737 bid, centry.id, centry.flags);
740 for (i = 0; i < COSIZE; i++) {
741 if (centry.entries[i] == aid) {
742 centry.entries[i] = newid;
743 for (j = 0; j < COSIZE; j++)
744 if (centry.entries[j] != PRBADID
745 && centry.entries[j] != 0)
747 code = pr_WriteCoEntry(at, 0, nptr, ¢ry);
752 if (centry.entries[i] == 0) {
755 } /* for all coentry slots */
757 } /* while there are coentries */
761 /* #ifdef SUPERGROUPS */
762 /* RemoveFromSGEntry - remove aid from bid's supergroups list, freeing a
763 * continuation entry if appropriate */
766 RemoveFromSGEntry(register struct ubik_trans *at, register afs_int32 aid, register afs_int32 bid)
768 register afs_int32 code;
769 struct prentry tentry;
770 struct prentryg *tentryg;
771 struct contentry centry;
772 struct contentry hentry;
779 return PRINCONSISTENT;
780 memset(&hentry, 0, sizeof(hentry));
781 temp = FindByID(at, bid);
785 code = pr_ReadEntry(at, 0, temp, &tentry);
788 #ifdef PR_REMEMBER_TIMES
789 tentry.removeTime = time(NULL);
791 tentryg = (struct prentryg *)&tentry;
792 for (i = 0; i < SGSIZE; i++) {
793 if (tentryg->supergroup[i] == aid) {
794 tentryg->supergroup[i] = PRBADID;
796 code = pr_WriteEntry(at, 0, temp, &tentry);
801 if (tentryg->supergroup[i] == 0) { /* found end of list */
806 nptr = tentryg->nextsg;
808 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
811 if ((centry.id != bid) || !(centry.flags & PRCONT)) {
813 "ChangeIDEntry: bad database bid=%d centry.id=%d .flags=%d\n",
814 bid, centry.id, centry.flags);
817 for (i = 0; i < COSIZE; i++) {
818 if (centry.entries[i] == aid) {
819 centry.entries[i] = PRBADID;
820 for (j = 0; j < COSIZE; j++)
821 if (centry.entries[j] != PRBADID
822 && centry.entries[j] != 0)
824 if (j == COSIZE) { /* can free this block */
826 tentryg->nextsg = centry.next;
828 hentry.next = centry.next;
829 code = pr_WriteCoEntry(at, 0, hloc, &hentry);
833 code = FreeBlock(at, nptr);
836 } else { /* can't free it yet */
837 code = pr_WriteCoEntry(at, 0, nptr, ¢ry);
842 code = pr_WriteEntry(at, 0, temp, &tentry);
847 if (centry.entries[i] == 0) {
850 } /* for all coentry slots */
853 memcpy((char *)¢ry, (char *)&hentry, sizeof(centry));
854 } /* while there are coentries */
858 #endif /* SUPERGROUPS */
860 /* DeleteEntry - delete the entry in tentry at loc, removing it from all
861 * groups, putting groups owned by it on orphan chain, and freeing the space */
864 DeleteEntry(struct ubik_trans *at, struct prentry *tentry, afs_int32 loc)
867 struct contentry centry;
871 if (strchr(tentry->name, '@')) {
872 if (tentry->flags & PRGRP) {
873 /* If there are still foreign user accounts from that cell
874 * don't delete the group */
880 afs_int32 loc = FindByID(at, tentry->cellid);
881 struct prentry centry;
883 code = pr_Read(at, 0, loc, ¢ry, sizeof(centry));
886 if (ntohl(centry.flags) & PRQUOTA) {
887 centry.ngroups = htonl(ntohl(centry.ngroups) + 1);
889 code = pr_Write(at, 0, loc, ¢ry, sizeof(centry));
895 /* First remove the entire membership list */
896 for (i = 0; i < PRSIZE; i++) {
897 if (tentry->entries[i] == PRBADID)
899 if (tentry->entries[i] == 0)
901 #if defined(SUPERGROUPS)
902 if ((tentry->flags & PRGRP) && tentry->entries[i] < 0) /* Supergroup */
903 code = RemoveFromSGEntry(at, tentry->id, tentry->entries[i]);
906 code = RemoveFromEntry(at, tentry->id, tentry->entries[i]);
910 #if defined(SUPERGROUPS)
912 struct prentryg *tentryg = (struct prentryg *)tentry;
914 /* Then remove the entire supergroup list */
915 for (i = 0; i < SGSIZE; i++) {
916 if (tentryg->supergroup[i] == PRBADID)
918 if (tentryg->supergroup[i] == 0)
920 code = RemoveFromEntry(at, tentry->id, tentryg->supergroup[i]);
925 #endif /* SUPERGROUPS */
928 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
931 for (i = 0; i < COSIZE; i++) {
932 if (centry.entries[i] == PRBADID)
934 if (centry.entries[i] == 0)
936 code = RemoveFromEntry(at, tentry->id, centry.entries[i]);
940 code = FreeBlock(at, nptr); /* free continuation block */
946 /* Remove us from other's owned chain. Note that this will zero our owned
947 * field (on disk) so this step must follow the above step in case we are
948 * on our own owned list. */
949 if (tentry->flags & PRGRP) {
951 code = RemoveFromOwnerChain(at, tentry->id, tentry->owner);
955 code = RemoveFromOrphan(at, tentry->id);
961 code = RemoveFromIDHash(at, tentry->id, &loc);
962 if (code != PRSUCCESS)
964 code = RemoveFromNameHash(at, tentry->name, &loc);
965 if (code != PRSUCCESS)
968 if (tentry->flags & PRGRP) {
969 afs_int32 loc = FindByID(at, tentry->creator);
970 struct prentry centry;
974 code = pr_Read(at, 0, loc, ¢ry, sizeof(centry));
977 admin = ((tentry->creator == SYSADMINID)
978 || IsAMemberOf(at, tentry->creator, SYSADMINID));
979 if (ntohl(centry.flags) & PRQUOTA) {
980 if (!(admin && (ntohl(centry.ngroups) >= 20))) {
981 centry.ngroups = htonl(ntohl(centry.ngroups) + 1);
984 code = pr_Write(at, 0, loc, ¢ry, sizeof(centry));
990 if (tentry->flags & PRGRP) {
991 if (inc_header_word(at, groupcount, -1))
993 } else if (tentry->flags & PRINST) {
994 if (inc_header_word(at, instcount, -1))
997 if (strchr(tentry->name, '@')) {
998 if (inc_header_word(at, foreigncount, -1))
1001 if (inc_header_word(at, usercount, -1))
1005 code = FreeBlock(at, loc);
1009 /* AddToEntry - add aid to entry's entries list, alloc'ing a continuation block
1012 * Note the entry is written out by this routine. */
1015 AddToEntry(struct ubik_trans *tt, struct prentry *entry, afs_int32 loc, afs_int32 aid)
1019 struct contentry nentry;
1020 struct contentry aentry;
1022 afs_int32 last; /* addr of last cont. block */
1023 afs_int32 first = 0;
1025 afs_int32 slot = -1;
1027 if (entry->id == aid)
1028 return PRINCONSISTENT;
1029 #ifdef PR_REMEMBER_TIMES
1030 entry->addTime = time(0);
1032 for (i = 0; i < PRSIZE; i++) {
1033 if (entry->entries[i] == aid)
1035 if (entry->entries[i] == PRBADID) { /* remember this spot */
1038 } else if (entry->entries[i] == 0) { /* end of the line */
1049 code = pr_ReadCoEntry(tt, 0, nptr, &nentry);
1053 if (!(nentry.flags & PRCONT))
1055 for (i = 0; i < COSIZE; i++) {
1056 if (nentry.entries[i] == aid)
1058 if (nentry.entries[i] == PRBADID) {
1063 } else if (nentry.entries[i] == 0) {
1073 if (slot != -1) { /* we found a place */
1075 if (first) { /* place is in first block */
1076 entry->entries[slot] = aid;
1077 code = pr_WriteEntry(tt, 0, loc, entry);
1082 code = pr_WriteEntry(tt, 0, loc, entry);
1085 code = pr_ReadCoEntry(tt, 0, cloc, &aentry);
1088 aentry.entries[slot] = aid;
1089 code = pr_WriteCoEntry(tt, 0, cloc, &aentry);
1094 /* have to allocate a continuation block if we got here */
1095 nptr = AllocBlock(tt);
1097 /* then we should tack new block after last block in cont. chain */
1099 code = pr_WriteCoEntry(tt, 0, last, &nentry);
1105 memset(&aentry, 0, sizeof(aentry));
1106 aentry.flags |= PRCONT;
1107 aentry.id = entry->id;
1109 aentry.entries[0] = aid;
1110 code = pr_WriteCoEntry(tt, 0, nptr, &aentry);
1113 /* don't forget to update count, here! */
1115 code = pr_WriteEntry(tt, 0, loc, entry);
1120 #if defined(SUPERGROUPS)
1122 /* AddToSGEntry - add aid to entry's supergroup list, alloc'ing a
1123 * continuation block if needed.
1125 * Note the entry is written out by this routine. */
1128 AddToSGEntry(struct ubik_trans *tt, struct prentry *entry, afs_int32 loc, afs_int32 aid)
1130 register afs_int32 code;
1132 struct contentry nentry;
1133 struct contentry aentry;
1134 struct prentryg *entryg;
1136 afs_int32 last; /* addr of last cont. block */
1137 afs_int32 first = 0;
1139 afs_int32 slot = -1;
1141 if (entry->id == aid)
1142 return PRINCONSISTENT;
1143 #ifdef PR_REMEMBER_TIMES
1144 entry->addTime = time(NULL);
1146 entryg = (struct prentryg *)entry;
1147 for (i = 0; i < SGSIZE; i++) {
1148 if (entryg->supergroup[i] == aid)
1150 if (entryg->supergroup[i] == PRBADID) { /* remember this spot */
1153 } else if (entryg->supergroup[i] == 0) { /* end of the line */
1162 nptr = entryg->nextsg;
1164 code = pr_ReadCoEntry(tt, 0, nptr, &nentry);
1168 if (!(nentry.flags & PRCONT))
1170 for (i = 0; i < COSIZE; i++) {
1171 if (nentry.entries[i] == aid)
1173 if (nentry.entries[i] == PRBADID) {
1178 } else if (nentry.entries[i] == 0) {
1188 if (slot != -1) { /* we found a place */
1190 if (first) { /* place is in first block */
1191 entryg->supergroup[slot] = aid;
1192 code = pr_WriteEntry(tt, 0, loc, entry);
1197 code = pr_WriteEntry(tt, 0, loc, entry);
1200 code = pr_ReadCoEntry(tt, 0, cloc, &aentry);
1203 aentry.entries[slot] = aid;
1204 code = pr_WriteCoEntry(tt, 0, cloc, &aentry);
1209 /* have to allocate a continuation block if we got here */
1210 nptr = AllocBlock(tt);
1212 /* then we should tack new block after last block in cont. chain */
1214 code = pr_WriteCoEntry(tt, 0, last, &nentry);
1218 entryg->nextsg = nptr;
1220 memset(&aentry, 0, sizeof(aentry));
1221 aentry.flags |= PRCONT;
1222 aentry.id = entry->id;
1224 aentry.entries[0] = aid;
1225 code = pr_WriteCoEntry(tt, 0, nptr, &aentry);
1228 /* don't forget to update count, here! */
1230 code = pr_WriteEntry(tt, 0, loc, entry);
1234 #endif /* SUPERGROUPS */
1237 AddToPRList(prlist *alist, int *sizeP, afs_int32 id)
1242 if (alist->prlist_len >= *sizeP) {
1243 count = alist->prlist_len + 100;
1244 if (alist->prlist_val) {
1246 (char *)realloc(alist->prlist_val, count * sizeof(afs_int32));
1248 tmp = (char *)malloc(count * sizeof(afs_int32));
1252 alist->prlist_val = (afs_int32 *) tmp;
1255 alist->prlist_val[alist->prlist_len++] = id;
1260 GetList(struct ubik_trans *at, struct prentry *tentry, prlist *alist, afs_int32 add)
1264 struct contentry centry;
1270 alist->prlist_val = 0;
1271 alist->prlist_len = 0;
1273 for (i = 0; i < PRSIZE; i++) {
1274 if (tentry->entries[i] == PRBADID)
1276 if (tentry->entries[i] == 0)
1278 code = AddToPRList(alist, &size, tentry->entries[i]);
1281 #if defined(SUPERGROUPS)
1284 code = GetListSG2(at, tentry->entries[i], alist, &size, depthsg);
1290 for (nptr = tentry->next; nptr != 0; nptr = centry.next) {
1291 /* look through cont entries */
1292 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1295 for (i = 0; i < COSIZE; i++) {
1296 if (centry.entries[i] == PRBADID)
1298 if (centry.entries[i] == 0)
1300 code = AddToPRList(alist, &size, centry.entries[i]);
1303 #if defined(SUPERGROUPS)
1306 code = GetListSG2(at, centry.entries[i], alist, &size, depthsg);
1312 #ifndef AFS_PTHREAD_ENV
1319 if (add) { /* this is for a CPS, so tack on appropriate stuff */
1320 if (tentry->id != ANONYMOUSID && tentry->id != ANYUSERID) {
1321 if ((code = AddToPRList(alist, &size, ANYUSERID))
1322 || (code = AddAuthGroup(tentry, alist, &size))
1323 || (code = AddToPRList(alist, &size, tentry->id)))
1326 if ((code = AddToPRList(alist, &size, ANYUSERID))
1327 || (code = AddToPRList(alist, &size, tentry->id)))
1331 #ifndef AFS_PTHREAD_ENV
1332 if (alist->prlist_len > 100)
1335 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
1341 GetList2(struct ubik_trans *at, struct prentry *tentry, struct prentry *tentry2, prlist *alist, afs_int32 add)
1345 struct contentry centry;
1351 alist->prlist_val = 0;
1352 alist->prlist_len = 0;
1353 for (i = 0; i < PRSIZE; i++) {
1354 if (tentry->entries[i] == PRBADID)
1356 if (tentry->entries[i] == 0)
1358 code = AddToPRList(alist, &size, tentry->entries[i]);
1361 #if defined(SUPERGROUPS)
1364 code = GetListSG2(at, tentry->entries[i], alist, &size, depthsg);
1370 nptr = tentry->next;
1372 /* look through cont entries */
1373 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1376 for (i = 0; i < COSIZE; i++) {
1377 if (centry.entries[i] == PRBADID)
1379 if (centry.entries[i] == 0)
1381 code = AddToPRList(alist, &size, centry.entries[i]);
1384 #if defined(SUPERGROUPS)
1387 code = GetListSG2(at, centry.entries[i], alist, &size, depthsg);
1394 #ifndef AFS_PTHREAD_ENV
1401 for (i = 0; i < PRSIZE; i++) {
1402 if (tentry2->entries[i] == PRBADID)
1404 if (tentry2->entries[i] == 0)
1406 code = AddToPRList(alist, &size, tentry2->entries[i]);
1412 nptr = tentry2->next;
1414 /* look through cont entries */
1415 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1418 for (i = 0; i < COSIZE; i++) {
1419 if (centry.entries[i] == PRBADID)
1421 if (centry.entries[i] == 0)
1423 code = AddToPRList(alist, &size, centry.entries[i]);
1429 #ifndef AFS_PTHREAD_ENV
1436 if (add) { /* this is for a CPS, so tack on appropriate stuff */
1437 if (tentry->id != ANONYMOUSID && tentry->id != ANYUSERID) {
1438 if ((code = AddToPRList(alist, &size, ANYUSERID))
1439 || (code = AddToPRList(alist, &size, AUTHUSERID))
1440 || (code = AddToPRList(alist, &size, tentry->id)))
1443 if ((code = AddToPRList(alist, &size, ANYUSERID))
1444 || (code = AddToPRList(alist, &size, tentry->id)))
1448 #ifndef AFS_PTHREAD_ENV
1449 if (alist->prlist_len > 100)
1452 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
1456 #if defined(SUPERGROUPS)
1459 GetListSG2(struct ubik_trans *at, afs_int32 gid, prlist *alist, afs_int32 *sizeP, afs_int32 depth)
1461 register afs_int32 code;
1462 struct prentry tentry;
1463 struct prentryg *tentryg = (struct prentryg *)&tentry;
1465 struct contentry centry;
1471 int predictfound, predictflagged;
1476 if (!in_map(sg_flagged, -gid)) {
1478 fprintf(stderr, "GetListSG2: I have not yet searched for gid=%d\n",
1480 } else if (predictflagged = 1, in_map(sg_found, -gid)) {
1483 "GetListSG2: I have already searched for gid=%d, and predict success.\n",
1488 if (in_map(sg_flagged, -gid) && !in_map(sg_found, -gid)) {
1491 "GetListSG2: I have already searched for gid=%d, and predict failure.\n",
1500 temp = FindByID(at, gid);
1505 code = pr_ReadEntry(at, 0, temp, &tentry);
1509 fprintf(stderr, "GetListSG2: lookup for gid=%d [\n", gid);
1513 for (i = 0; i < SGSIZE; i++) {
1514 if (tentryg->supergroup[i] == PRBADID)
1516 if (tentryg->supergroup[i] == 0)
1520 fprintf(stderr, "via gid=%d, added %d\n", gid,
1521 e.tentryg.supergroup[i]);
1523 code = AddToPRList(alist, sizeP, tentryg->supergroup[i]);
1527 GetListSG2(at, tentryg->supergroup[i], alist, sizeP, depth - 1);
1532 nptr = tentryg->nextsg;
1535 /* look through cont entries */
1536 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1539 for (i = 0; i < COSIZE; i++) {
1540 if (centry.entries[i] == PRBADID)
1542 if (centry.entries[i] == 0)
1545 fprintf(stderr, "via gid=%d, added %d\n", gid,
1546 e.centry.entries[i]);
1548 code = AddToPRList(alist, sizeP, centry.entries[i]);
1551 code = GetListSG2(at, centry.entries[i], alist, sizeP, depth - 1);
1557 #ifndef AFS_PTHREAD_ENV
1564 fprintf(stderr, "] for gid %d, done [flag=%s]\n", gid,
1565 didsomething ? "TRUE" : "FALSE");
1566 if (predictflagged && didsomething != predictfound)
1567 fprintf(stderr, "**** for gid=%d, didsomething=%d predictfound=%d\n",
1568 didsomething, predictfound);
1571 sg_found = add_map(sg_found, -gid);
1573 sg_found = bic_map(sg_found, add_map(NIL_MAP, -gid));
1574 sg_flagged = add_map(sg_flagged, -gid);
1579 GetSGList(struct ubik_trans *at, struct prentry *tentry, prlist *alist)
1581 register afs_int32 code;
1583 struct contentry centry;
1584 struct prentryg *tentryg;
1590 alist->prlist_val = 0;
1591 alist->prlist_len = 0;
1593 tentryg = (struct prentryg *)tentry;
1594 for (i = 0; i < SGSIZE; i++) {
1595 if (tentryg->supergroup[i] == PRBADID)
1597 if (tentryg->supergroup[i] == 0)
1599 code = AddToPRList(alist, &size, tentryg->supergroup[i]);
1604 nptr = tentryg->nextsg;
1606 /* look through cont entries */
1607 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1610 for (i = 0; i < COSIZE; i++) {
1611 if (centry.entries[i] == PRBADID)
1613 if (centry.entries[i] == 0)
1615 code = AddToPRList(alist, &size, centry.entries[i]);
1621 #ifndef AFS_PTHREAD_ENV
1628 #ifndef AFS_PTHREAD_ENV
1629 if (alist->prlist_len > 100)
1632 qsort((char *)alist->prlist_val, (int)alist->prlist_len,
1633 sizeof(afs_int32), IDCmp);
1636 #endif /* SUPERGROUPS */
1639 GetOwnedChain(struct ubik_trans *ut, afs_int32 *next, prlist *alist)
1642 struct prentry tentry;
1647 alist->prlist_val = 0;
1648 alist->prlist_len = 0;
1650 for (; *next; *next = ntohl(tentry.nextOwned)) {
1651 code = pr_Read(ut, 0, *next, &tentry, sizeof(tentry));
1654 code = AddToPRList(alist, &size, ntohl(tentry.id));
1655 if (alist->prlist_len >= PR_MAXGROUPS) {
1661 #ifndef AFS_PTHREAD_ENV
1667 #ifndef AFS_PTHREAD_ENV
1668 if (alist->prlist_len > 100)
1671 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
1676 GetMax(struct ubik_trans *at, afs_int32 *uid, afs_int32 *gid)
1678 *uid = ntohl(cheader.maxID);
1679 *gid = ntohl(cheader.maxGroup);
1684 SetMax(struct ubik_trans *at, afs_int32 id, afs_int32 flag)
1688 cheader.maxGroup = htonl(id);
1690 pr_Write(at, 0, 16, (char *)&cheader.maxGroup,
1691 sizeof(cheader.maxGroup));
1695 cheader.maxID = htonl(id);
1697 pr_Write(at, 0, 20, (char *)&cheader.maxID,
1698 sizeof(cheader.maxID));
1706 UpdateCache(struct ubik_trans *tt, void *rock)
1710 code = pr_Read(tt, 0, 0, (char *)&cheader, sizeof(cheader));
1712 afs_com_err(whoami, code, "Couldn't read header");
1718 read_DbHeader(struct ubik_trans *tt)
1720 return ubik_CheckCache(tt, UpdateCache, NULL);
1726 * reads in db cache from ubik.
1728 * @param[in] ut ubik transaction
1729 * @param[out] rock opaque pointer to an int*, which on success will be set
1730 * to 1 if we need to build the database, or 0 if we do not
1732 * @return operation status
1736 Initdb_check(struct ubik_trans *tt, void *rock)
1738 int *build_rock = rock;
1742 len = sizeof(cheader);
1743 code = pr_Read(tt, 0, 0, (char *)&cheader, len);
1745 afs_com_err(whoami, code, "couldn't read header");
1748 if ((ntohl(cheader.version) == PRDBVERSION)
1749 && ntohl(cheader.headerSize) == sizeof(cheader)
1750 && ntohl(cheader.eofPtr) != 0
1751 && FindByID(tt, ANONYMOUSID) != 0) {
1752 /* database exists, so we don't have to build it */
1757 /* else we need to build a database */
1765 struct ubik_trans *tt;
1769 /* init the database. We'll try reading it, but if we're starting
1770 * from scratch, we'll have to do a write transaction. */
1772 pr_noAuth = afsconf_GetNoAuthFlag(prdir);
1774 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1777 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1779 ubik_AbortTrans(tt);
1783 code = ubik_CheckCache(tt, Initdb_check, &build);
1785 ubik_AbortTrans(tt);
1790 /* Only rebuild database if the db was deleted (the header is zero) and we
1791 * are running noAuth. */
1792 char *bp = (char *)&cheader;
1794 for (i = 0; i < sizeof(cheader); i++) {
1797 afs_com_err(whoami, code,
1798 "Can't rebuild database because it is not empty");
1804 afs_com_err(whoami, code,
1805 "Can't rebuild database because not running NoAuth");
1812 code = ubik_EndTrans(tt);
1814 if (code || !build) {
1815 /* either we encountered an error, or we don't need to build the db */
1819 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1823 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1825 ubik_AbortTrans(tt);
1829 /* before doing a rebuild, check again that the dbase looks bad, because
1830 * the previous check was only under a ReadAny transaction, and there could
1831 * actually have been a good database out there. Now that we have a
1832 * real write transaction, make sure things are still bad.
1834 code = pr_Read(tt, 0, 0, (char *)&cheader, sizeof(cheader));
1836 afs_com_err(whoami, code, "couldn't read header");
1837 ubik_AbortTrans(tt);
1840 if ((ntohl(cheader.version) == PRDBVERSION)
1841 && ntohl(cheader.headerSize) == sizeof(cheader)
1842 && ntohl(cheader.eofPtr) != 0
1843 && FindByID(tt, ANONYMOUSID) != 0) {
1844 /* database exists, so we don't have to build it */
1845 code = ubik_EndTrans(tt);
1851 /* Initialize the database header */
1852 if ((code = set_header_word(tt, version, htonl(PRDBVERSION)))
1853 || (code = set_header_word(tt, headerSize, htonl(sizeof(cheader))))
1854 || (code = set_header_word(tt, eofPtr, cheader.headerSize))) {
1855 afs_com_err(whoami, code, "couldn't write header words");
1856 ubik_AbortTrans(tt);
1859 #define InitialGroup(id,name) do { \
1860 afs_int32 temp = (id); \
1861 afs_int32 flag = (id) < 0 ? PRGRP : 0; \
1862 code = CreateEntry \
1863 (tt, (name), &temp, /*idflag*/1, flag, SYSADMINID, SYSADMINID); \
1865 afs_com_err (whoami, code, "couldn't create %s with id %di.", \
1867 ubik_AbortTrans(tt); \
1872 InitialGroup(SYSADMINID, "system:administrators");
1873 InitialGroup(SYSBACKUPID, "system:backup");
1874 InitialGroup(ANYUSERID, "system:anyuser");
1875 InitialGroup(AUTHUSERID, "system:authuser");
1876 InitialGroup(SYSVIEWERID, "system:ptsviewers");
1877 InitialGroup(ANONYMOUSID, "anonymous");
1879 /* Well, we don't really want the max id set to anonymousid, so we'll set
1881 code = set_header_word(tt, maxID, 0); /* correct in any byte order */
1883 afs_com_err(whoami, code, "couldn't reset max id");
1884 ubik_AbortTrans(tt);
1888 code = ubik_EndTrans(tt);
1895 ChangeEntry(struct ubik_trans *at, afs_int32 aid, afs_int32 cid, char *name, afs_int32 oid, afs_int32 newid)
1899 #if defined(SUPERGROUPS)
1903 struct contentry centry;
1905 struct prentry tentry, tent;
1908 char holder[PR_MAXNAMELEN];
1909 char temp[PR_MAXNAMELEN];
1910 char oldname[PR_MAXNAMELEN];
1913 memset(holder, 0, PR_MAXNAMELEN);
1914 memset(temp, 0, PR_MAXNAMELEN);
1915 loc = FindByID(at, aid);
1918 code = pr_ReadEntry(at, 0, loc, &tentry);
1921 if (restricted && !IsAMemberOf(at, cid, SYSADMINID))
1923 if (tentry.owner != cid && !IsAMemberOf(at, cid, SYSADMINID)
1924 && !IsAMemberOf(at, cid, tentry.owner) && !pr_noAuth)
1926 #ifdef PR_REMEMBER_TIMES
1927 tentry.changeTime = time(0);
1930 /* we're actually trying to change the id */
1931 if (newid && (newid != aid)) {
1932 if (!IsAMemberOf(at, cid, SYSADMINID) && !pr_noAuth)
1935 pos = FindByID(at, newid);
1937 return PRIDEXIST; /* new id already in use! */
1938 if ((aid < 0 && newid > 0) || (aid > 0 && newid < 0))
1941 /* Should check that foreign users id to change to is good: inRange() */
1943 /* if new id is not in use, rehash things */
1944 code = RemoveFromIDHash(at, aid, &loc);
1945 if (code != PRSUCCESS)
1948 code = pr_WriteEntry(at, 0, loc, &tentry);
1951 code = AddToIDHash(at, tentry.id, loc);
1955 /* get current data */
1956 code = pr_ReadEntry(at, 0, loc, &tentry);
1960 #if defined(SUPERGROUPS)
1961 if (tentry.id > (afs_int32) ntohl(cheader.maxID))
1962 code = set_header_word(at, maxID, htonl(tentry.id));
1966 /* need to fix up: membership
1971 for (i = 0; i < PRSIZE; i++) {
1972 if (tentry.entries[i] == PRBADID)
1974 if (tentry.entries[i] == 0)
1976 if ((tentry.flags & PRGRP) && tentry.entries[i] < 0) { /* Supergroup */
1977 return 5; /* not yet, in short. */
1979 code = ChangeIDEntry(at, aid, newid, tentry.entries[i]);
1984 for (pos = ntohl(tentry.owned); pos; pos = nextpos) {
1985 code = pr_ReadEntry(at, 0, pos, &tent);
1989 nextpos = tent.nextOwned;
1990 code = pr_WriteEntry(at, 0, pos, &tent);
1996 #define centry (*(struct contentry*)&tent)
1997 code = pr_ReadCoEntry(at, 0, pos, ¢ry);
1998 if ((centry.id != aid)
1999 || !(centry.flags & PRCONT)) {
2001 "ChangeEntry: bad database aid=%d centry.id=%d .flags=%d\n",
2002 aid, centry.id, centry.flags);
2006 for (i = 0; i < COSIZE; i++) {
2007 if (centry.entries[i] == PRBADID)
2009 if (centry.entries[i] == 0)
2011 if ((centry.flags & PRGRP) && centry.entries[i] < 0) { /* Supergroup */
2012 return 5; /* not yet, in short. */
2014 code = ChangeIDEntry(at, aid, newid, centry.entries[i]);
2019 code = pr_WriteCoEntry(at, 0, pos, ¢ry);
2026 #else /* SUPERGROUPS */
2029 /* Also change the references from the membership list */
2030 for (i = 0; i < PRSIZE; i++) {
2031 if (tentry.entries[i] == PRBADID)
2033 if (tentry.entries[i] == 0)
2035 pos = FindByID(at, tentry.entries[i]);
2038 code = RemoveFromEntry(at, aid, tentry.entries[i]);
2041 code = pr_ReadEntry(at, 0, pos, &tent);
2044 code = AddToEntry(at, &tent, pos, newid);
2048 /* Look through cont entries too. This needs to be broken into
2049 * seperate transaction so that no one transaction becomes too
2050 * large to complete.
2052 for (nptr = tentry.next; nptr; nptr = centry.next) {
2053 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
2056 for (i = 0; i < COSIZE; i++) {
2057 if (centry.entries[i] == PRBADID)
2059 if (centry.entries[i] == 0)
2061 pos = FindByID(at, centry.entries[i]);
2064 code = RemoveFromEntry(at, aid, centry.entries[i]);
2067 code = pr_ReadEntry(at, 0, pos, &tent);
2070 code = AddToEntry(at, &tent, pos, newid);
2075 #endif /* SUPERGROUPS */
2078 atsign = strchr(tentry.name, '@'); /* check for foreign entry */
2080 /* Change the owner */
2081 if (oid && (oid != tentry.owner)) {
2082 /* only groups can have their owner's changed */
2083 if (!(tentry.flags & PRGRP))
2087 oldowner = tentry.owner;
2089 /* The entry must be written through first so Remove and Add routines
2090 * can operate on disk data */
2091 code = pr_WriteEntry(at, 0, loc, &tentry);
2095 /* switch owner chains */
2096 if (oldowner) /* if it has an owner */
2097 code = RemoveFromOwnerChain(at, tentry.id, oldowner);
2098 else /* must be an orphan */
2099 code = RemoveFromOrphan(at, tentry.id);
2102 code = AddToOwnerChain(at, tentry.id, tentry.owner);
2106 /* fix up the name */
2107 if (strlen(name) == 0)
2109 /* get current data */
2110 code = pr_ReadEntry(at, 0, loc, &tentry);
2115 /* Change the name, if name is a ptr to tentry.name then this name change
2116 * is due to a chown, otherwise caller has specified a new name */
2117 if ((name == tentry.name) || (*name && (strcmp(tentry.name, name) != 0))) {
2118 strncpy(oldname, tentry.name, PR_MAXNAMELEN);
2119 if (tentry.flags & PRGRP) {
2120 /* don't let foreign cell groups change name */
2123 code = CorrectGroupName(at, name, cid, tentry.owner, tentry.name);
2127 if (name == tentry.name) { /* owner fixup */
2128 if (strcmp(oldname, tentry.name) == 0)
2130 } else { /* new name, caller must be correct */
2131 if (strcmp(name, tentry.name) != 0)
2135 /* Allow a foreign name change only if the cellname part is
2140 newatsign = strchr(name, '@');
2141 if (newatsign != atsign) { /* if they are the same no problem */
2142 /*if the pointers are not equal the strings better be */
2143 if ((atsign == NULL) || (newatsign == NULL)
2144 || strcmp(atsign, newatsign))
2147 if (!CorrectUserName(name))
2151 pos = FindByName(at, name, &tent);
2154 code = RemoveFromNameHash(at, oldname, &loc);
2155 if (code != PRSUCCESS)
2157 strncpy(tentry.name, name, PR_MAXNAMELEN);
2158 code = pr_WriteEntry(at, 0, loc, &tentry);
2161 code = AddToNameHash(at, tentry.name, loc);
2162 if (code != PRSUCCESS)
2171 allocNextId(struct ubik_trans * at, struct prentry * cellEntry)
2173 /* Id's for foreign cell entries are constructed as follows:
2174 * The 16 low order bits are the group id of the cell and the
2175 * top 16 bits identify the particular users in that cell */
2178 afs_int32 cellid = ((ntohl(cellEntry->id)) & 0x0000ffff);
2180 id = (ntohl(cellEntry->nusers) + 1);
2181 while (FindByID(at, ((id << 16) | cellid))) {
2187 cellEntry->nusers = htonl(id);
2188 /* use the field nusers to keep
2189 * the next available id in that
2190 * foreign cell's group. Note :
2191 * It would seem more appropriate
2192 * to use ngroup for that and nusers
2193 * to enforce the quota, however pts
2194 * does not have an option to change
2195 * foreign users quota yet */
2197 id = (id << 16) | cellid;
2202 inRange(struct prentry *cellEntry, afs_int32 aid)
2204 afs_uint32 id, cellid, groupid;
2208 * The only thing that we want to make sure here is that
2209 * the id is in the legal range of this group. If it is
2210 * a duplicate we don't care since it will get caught
2211 * in a different check.
2214 cellid = aid & 0x0000ffff;
2215 groupid = (ntohl(cellEntry->id)) & 0x0000ffff;
2216 if (cellid != groupid)
2217 return 0; /* not in range */
2220 * if we got here we're ok but we need to update the nusers
2221 * field in order to get the id correct the next time that
2222 * we try to allocate it automatically
2226 if (id > ntohl(cellEntry->nusers))
2227 cellEntry->nusers = htonl(id);
2233 AddAuthGroup(struct prentry *tentry, prlist *alist, afs_int32 *size)
2235 if (!(strchr(tentry->name, '@')))
2236 return (AddToPRList(alist, size, AUTHUSERID));