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) ();
90 pt_mywrite(struct ubik_dbase *tdb, afs_int32 fno, char *bp, afs_int32 pos, afs_int32 count)
92 afs_uint32 headersize = ntohl(cheader.headerSize);
94 if (fno == 0 && pos + count > headersize) {
109 #define xPT(p,x) ((((struct prentry *)(p))->flags & htonl(PRTYPE)) == htonl(x))
112 fprintf(stderr, "Writing %d bytes of entry @ %#lx(+%d)\n", c,
114 else if (c == ENTRYSIZE)
116 "Writing %d bytes of entry @ %#lx (%d<%s>,%d)\n",
117 c, p, ntohl(((struct prentry *)cp)->flags),
118 xPT(cp,PRUSER) ? "user" : xPT(cp,PRFREE) ? "free" :
119 xPT(cp,PRGRP) ? "group" : xPT(cp,PRCONT) ? "cont" :
120 xPT(cp,PRCELL) ? "cell" : xPT(cp,PRFOREIGN) ? "foreign" :
121 xPT(cp,PRINST) ? "sub/super instance" : "?",
122 ntohl(((struct prentry *)cp)->id));
125 "Writing first %d bytes of entry @ %#lx (%d<%s>,%d)\n",
126 c, p, ntohl(((struct prentry *)cp)->flags),
127 xPT(cp,PRUSER) ? "user" : xPT(cp,PRFREE) ? "free" :
128 xPT(cp,PRGRP) ? "group" : xPT(cp,PRCONT) ? "cont" :
129 xPT(cp,PRCELL) ? "cell" : xPT(cp,PRFOREIGN) ? "foreign" :
130 xPT(cp,PRINST) ? "sub/super instance" : "?",
131 ntohl(((struct prentry *)cp)->id));
133 fprintf(stderr, "Writing %d bytes of entry @ %#lx\n", c, p);
135 if (!o && c >= 8 && xPT(cp,PRGRP)) {
137 if (in_map(sg_found, -ntohl(((struct prentry *)cp)->id)))
138 fprintf(stderr, "Unfound: Removing group %d\n",
139 ntohl(((struct prentry *)cp)->id));
140 if (in_map(sg_flagged, -ntohl(((struct prentry *)cp)->id)))
141 fprintf(stderr, "Unflag: Removing group %d\n",
142 ntohl(((struct prentry *)cp)->id));
146 add_map(NIL_MAP, -ntohl(((struct prentry *)cp)->id)));
149 add_map(NIL_MAP, -ntohl(((struct prentry *)cp)->id)));
157 return (*pt_save_dbase_write) (tdb, fno, bp, pos, count);
161 * this function attaches pt_mywrite. It's called once,
162 * just after ubik_ServerInit.
168 extern struct ubik_dbase *ubik_dbase;
169 if (ubik_dbase->write != pt_mywrite) {
170 pt_save_dbase_write = ubik_dbase->write;
171 ubik_dbase->write = pt_mywrite;
175 #endif /* SUPERGROUPS */
177 /* CorrectUserName - Check to make sure a user name is OK. It must not include
178 * either a colon (or it would look like a group) or an atsign (or it would
179 * look like a foreign user). The length is checked as well to make sure
180 * that the user name, an atsign, and the local cell name will fit in
181 * PR_MAXNAMELEN. This is so this user can fit in another cells database as
182 * a foreign user with our cell name tacked on. This is a predicate, so it
183 * return one if name is OK and zero if name is bogus. */
186 CorrectUserName(char *name)
188 extern int pr_realmNameLen;
190 /* We accept foreign names, so we will deal with '@' later */
191 if (strchr(name, ':') || strchr(name, '\n'))
193 if (strlen(name) >= PR_MAXNAMELEN - pr_realmNameLen - 1)
198 /* CorrectGroupName - Like the above but handles more complicated cases caused
199 * by including the ownership in the name. The interface works by calculating
200 * the correct name based on a given name and owner. This allows easy use by
201 * rename, which then compares the correct name with the requested new name. */
204 CorrectGroupName(struct ubik_trans *ut, char aname[PR_MAXNAMELEN], /* name for group */
205 afs_int32 cid, /* caller id */
206 afs_int32 oid, /* owner of group */
207 char cname[PR_MAXNAMELEN]) /* correct name for group */
211 char *prefix; /* ptr to group owner part */
212 char *suffix; /* ptr to group name part */
213 char name[PR_MAXNAMELEN]; /* correct name for group */
214 struct prentry tentry;
216 if (strlen(aname) >= PR_MAXNAMELEN)
218 admin = pr_noAuth || IsAMemberOf(ut, cid, SYSADMINID);
223 /* Determine the correct prefix for the name. */
224 if (oid == SYSADMINID)
227 afs_int32 loc = FindByID(ut, oid);
229 /* let admin create groups owned by non-existent ids (probably
230 * setting a group to own itself). Check that they look like
231 * groups (with a colon) or otherwise are good user names. */
233 strcpy(cname, aname);
238 code = pr_Read(ut, 0, loc, &tentry, sizeof(tentry));
241 if (ntohl(tentry.flags) & PRGRP) {
242 if ((tentry.count == 0) && !admin)
244 /* terminate prefix at colon if there is one */
245 if ((prefix = strchr(tentry.name, ':')))
248 prefix = tentry.name;
250 /* only sysadmin allow to use 'system:' prefix */
251 if ((strcmp(prefix, "system") == 0) && !admin)
254 strcpy(name, aname); /* in case aname & cname are same */
255 suffix = strchr(name, ':');
257 /* sysadmin can make groups w/o ':', but they must still look like
258 * legal user names. */
263 if (strlen(prefix) + strlen(suffix) >= PR_MAXNAMELEN)
265 strcpy(cname, prefix);
266 strcat(cname, suffix);
269 /* check for legal name with either group rules or user rules */
270 if ((suffix = strchr(cname, ':'))) {
271 /* check for confusing characters */
272 if (strchr(cname, '\n') || /* restrict so recreate can work */
273 strchr(suffix + 1, ':')) /* avoid multiple colons */
276 if (!CorrectUserName(cname))
283 AccessOK(struct ubik_trans *ut, afs_int32 cid, /* caller id */
284 struct prentry *tentry, /* object being accessed */
285 int mem, /* check membership in aid, if group */
286 int any) /* if set return true */
294 if (cid == SYSADMINID)
295 return 1; /* special case fileserver */
296 if (restricted && ((mem == PRP_ADD_MEM) || (mem == PRP_REMOVE_MEM)) && (any == 0))
299 flags = tentry->flags;
303 flags = oid = aid = 0;
305 if (!(flags & PRACCESS)) { /* provide default access */
307 flags |= prp_group_default;
309 flags |= prp_user_default;
315 if ((cid == oid) || IsAMemberOf(ut, cid, oid))
318 if (aid > 0) { /* checking on a user */
321 } else if (aid < 0) { /* checking on group */
322 if ((flags & mem) && IsAMemberOf(ut, cid, aid))
325 /* Allow members of SYSVIEWERID to get membership and status only */
326 if (((mem == PRP_STATUS_MEM) || (mem == PRP_MEMBER_MEM)
327 || (any == PRP_OWNED_ANY)) && (IsAMemberOf(ut, cid, SYSVIEWERID)))
329 if (IsAMemberOf(ut, cid, SYSADMINID))
331 return 0; /* no access */
335 CreateEntry(struct ubik_trans *at, char aname[PR_MAXNAMELEN], afs_int32 *aid, afs_int32 idflag, afs_int32 flag, afs_int32 oid, afs_int32 creator)
337 /* get and init a new entry */
340 struct prentry tentry, tent;
343 memset(&tentry, 0, sizeof(tentry));
345 if ((oid == 0) || (oid == ANONYMOUSID))
349 code = CorrectGroupName(at, aname, creator, oid, tentry.name);
352 if (strcmp(aname, tentry.name) != 0)
354 } else { /* non-group must not have colon */
355 if (!CorrectUserName(aname))
357 strcpy(tentry.name, aname);
360 if (FindByName(at, aname, &tent))
363 newEntry = AllocBlock(at);
366 #ifdef PR_REMEMBER_TIMES
367 tentry.createTime = time(0);
371 tentry.flags = PRGRP;
373 } else if (flag == 0) {
375 tentry.owner = SYSADMINID;
380 atsign = strchr(aname, '@');
382 /* A normal user or group. Pick an id for it */
386 code = AllocID(at, flag, &tentry.id);
387 if (code != PRSUCCESS)
390 } else if (flag & PRGRP) {
391 /* A foreign group. Its format must be AUTHUSER_GROUP@cellname
392 * Then pick an id for the group.
397 badFormat = strcmp(AUTHUSER_GROUP, aname);
405 code = AllocID(at, flag, &tentry.id);
406 if (code != PRSUCCESS)
410 /* A foreign user: <name>@<cell>. The foreign user is added to
411 * its representing group. It is
415 struct prentry centry;
417 /* To create the user <name>@<cell> the group AUTHUSER_GROUP@<cell>
421 (char *)malloc(strlen(AUTHUSER_GROUP) + strlen(atsign) + 1);
422 strcpy(cellGroup, AUTHUSER_GROUP);
423 strcat(cellGroup, atsign);
424 pos = FindByName(at, cellGroup, ¢ry);
428 code = pr_Read(at, 0, pos, ¢ry, sizeof(centry));
432 /* cellid is the id of the group representing the cell */
433 tentry.cellid = ntohl(centry.id);
436 /* Check if id is good */
437 if (!inRange(¢ry, *aid))
441 /* Allocate an ID special for this foreign user. It is based
442 * on the representing group's id and nusers count.
444 tentry.id = allocNextId(at, ¢ry);
449 /* The foreign user will be added to the representing foreign
450 * group. The group can hold up to 30 entries.
452 if (!(ntohl(centry.flags) & PRQUOTA)) {
453 centry.flags = htonl(ntohl(centry.flags) | PRQUOTA);
454 centry.ngroups = htonl(30);
456 n = ntohl(centry.ngroups);
457 if ((n <= 0) && !pr_noAuth)
459 centry.ngroups = htonl(n - 1);
461 /* write updated entry for group */
462 code = pr_Write(at, 0, pos, ¢ry, sizeof(centry));
464 /* Now add the new user entry to the database */
465 tentry.creator = creator;
467 code = pr_WriteEntry(at, 0, newEntry, &tentry);
470 code = AddToIDHash(at, *aid, newEntry);
471 if (code != PRSUCCESS)
473 code = AddToNameHash(at, aname, newEntry);
474 if (code != PRSUCCESS)
476 if (inc_header_word(at, foreigncount, 1))
479 /* Now add the entry to the authuser group for this cell.
480 * We will reread the entries for the user and the group
481 * instead of modifying them before writing them in the
482 * previous steps. Although not very efficient, much simpler
484 pos = FindByID(at, tentry.cellid);
487 code = pr_ReadEntry(at, 0, pos, ¢ry);
490 code = AddToEntry(at, ¢ry, pos, *aid);
493 /* and now the user entry */
494 pos = FindByID(at, *aid);
497 code = pr_ReadEntry(at, 0, pos, &tentry);
500 code = AddToEntry(at, &tentry, pos, tentry.cellid);
507 /* Remember the largest group id or largest user id */
509 /* group ids are negative */
510 if (tentry.id < (afs_int32) ntohl(cheader.maxGroup)) {
511 code = set_header_word(at, maxGroup, htonl(tentry.id));
516 if (tentry.id > (afs_int32) ntohl(cheader.maxID)) {
517 code = set_header_word(at, maxID, htonl(tentry.id));
523 /* Charge the creator for this group */
525 afs_int32 loc = FindByID(at, creator);
526 struct prentry centry;
529 if (loc) { /* this should only fail during initialization */
530 code = pr_Read(at, 0, loc, ¢ry, sizeof(centry));
534 /* If quota is uninitialized, do it */
535 if (!(ntohl(centry.flags) & PRQUOTA)) {
536 centry.flags = htonl(ntohl(centry.flags) | PRQUOTA);
537 centry.ngroups = centry.nusers = htonl(20);
540 /* Admins don't get charged for creating a group.
541 * If in noAuth mode, you get changed for it but you
542 * are still allowed to create as many groups as you want.
544 admin = ((creator == SYSADMINID)
545 || IsAMemberOf(at, creator, SYSADMINID));
547 if (ntohl(centry.ngroups) <= 0) {
551 centry.ngroups = htonl(ntohl(centry.ngroups) - 1);
555 code = pr_Write(at, 0, loc, ¢ry, sizeof(centry));
560 /* Initialize the quota for the user. Groups don't have their
563 tentry.flags |= PRQUOTA;
564 tentry.ngroups = tentry.nusers = 20;
567 tentry.creator = creator;
569 code = pr_WriteEntry(at, 0, newEntry, &tentry);
572 code = AddToIDHash(at, *aid, newEntry);
573 if (code != PRSUCCESS)
575 code = AddToNameHash(at, aname, newEntry);
576 if (code != PRSUCCESS)
578 if (tentry.flags & PRGRP) {
579 code = AddToOwnerChain(at, tentry.id, oid);
583 if (tentry.flags & PRGRP) {
584 if (inc_header_word(at, groupcount, 1))
586 } else if (tentry.flags & PRINST) {
587 if (inc_header_word(at, instcount, 1))
590 if (inc_header_word(at, usercount, 1))
597 /* RemoveFromEntry - remove aid from bid's entries list, freeing a continuation
598 * entry if appropriate */
601 RemoveFromEntry(struct ubik_trans *at, afs_int32 aid, afs_int32 bid)
604 struct prentry tentry;
605 struct contentry centry;
606 struct contentry hentry;
613 return PRINCONSISTENT;
614 memset(&hentry, 0, sizeof(hentry));
615 temp = FindByID(at, bid);
618 code = pr_ReadEntry(at, 0, temp, &tentry);
621 #ifdef PR_REMEMBER_TIMES
622 tentry.removeTime = time(0);
624 for (i = 0; i < PRSIZE; i++) {
625 if (tentry.entries[i] == aid) {
626 tentry.entries[i] = PRBADID;
628 code = pr_WriteEntry(at, 0, temp, &tentry);
633 if (tentry.entries[i] == 0) /* found end of list */
639 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
642 if ((centry.id != bid) || !(centry.flags & PRCONT))
644 for (i = 0; i < COSIZE; i++) {
645 if (centry.entries[i] == aid) {
646 centry.entries[i] = PRBADID;
647 for (j = 0; j < COSIZE; j++)
648 if (centry.entries[j] != PRBADID
649 && centry.entries[j] != 0)
651 if (j == COSIZE) { /* can free this block */
653 tentry.next = centry.next;
655 hentry.next = centry.next;
656 code = pr_WriteCoEntry(at, 0, hloc, &hentry);
660 code = FreeBlock(at, nptr);
663 } else { /* can't free it yet */
664 code = pr_WriteCoEntry(at, 0, nptr, ¢ry);
669 code = pr_WriteEntry(at, 0, temp, &tentry);
674 if (centry.entries[i] == 0)
676 } /* for all coentry slots */
679 memcpy(&hentry, ¢ry, sizeof(centry));
680 } /* while there are coentries */
684 #if defined(SUPERGROUPS)
685 /* ChangeIDEntry - remove aid from bid's entries list, freeing a continuation
686 * entry if appropriate */
689 ChangeIDEntry(register struct ubik_trans *at, register afs_int32 aid, afs_int32 newid, register afs_int32 bid)
691 register afs_int32 code;
692 struct prentry tentry;
693 struct contentry centry;
699 return PRINCONSISTENT;
700 temp = FindByID(at, bid);
704 code = pr_ReadEntry(at, 0, temp, &tentry);
707 for (i = 0; i < PRSIZE; i++) {
708 if (tentry.entries[i] == aid) {
709 tentry.entries[i] = newid;
710 code = pr_WriteEntry(at, 0, temp, &tentry);
715 if (tentry.entries[i] == 0) { /* found end of list */
722 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
725 if ((centry.id != bid) || !(centry.flags & PRCONT)) {
727 "ChangeIDEntry: bad database bid=%d centry.id=%d .flags=%d\n",
728 bid, centry.id, centry.flags);
731 for (i = 0; i < COSIZE; i++) {
732 if (centry.entries[i] == aid) {
733 centry.entries[i] = newid;
734 for (j = 0; j < COSIZE; j++)
735 if (centry.entries[j] != PRBADID
736 && centry.entries[j] != 0)
738 code = pr_WriteCoEntry(at, 0, nptr, ¢ry);
743 if (centry.entries[i] == 0) {
746 } /* for all coentry slots */
748 } /* while there are coentries */
752 /* #ifdef SUPERGROUPS */
753 /* RemoveFromSGEntry - remove aid from bid's supergroups list, freeing a
754 * continuation entry if appropriate */
757 RemoveFromSGEntry(register struct ubik_trans *at, register afs_int32 aid, register afs_int32 bid)
759 register afs_int32 code;
760 struct prentry tentry;
761 struct prentryg *tentryg;
762 struct contentry centry;
763 struct contentry hentry;
770 return PRINCONSISTENT;
771 memset(&hentry, 0, sizeof(hentry));
772 temp = FindByID(at, bid);
776 code = pr_ReadEntry(at, 0, temp, &tentry);
779 #ifdef PR_REMEMBER_TIMES
780 tentry.removeTime = time(NULL);
782 tentryg = (struct prentryg *)&tentry;
783 for (i = 0; i < SGSIZE; i++) {
784 if (tentryg->supergroup[i] == aid) {
785 tentryg->supergroup[i] = PRBADID;
787 code = pr_WriteEntry(at, 0, temp, &tentry);
792 if (tentryg->supergroup[i] == 0) { /* found end of list */
797 nptr = tentryg->nextsg;
799 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
802 if ((centry.id != bid) || !(centry.flags & PRCONT)) {
804 "ChangeIDEntry: bad database bid=%d centry.id=%d .flags=%d\n",
805 bid, centry.id, centry.flags);
808 for (i = 0; i < COSIZE; i++) {
809 if (centry.entries[i] == aid) {
810 centry.entries[i] = PRBADID;
811 for (j = 0; j < COSIZE; j++)
812 if (centry.entries[j] != PRBADID
813 && centry.entries[j] != 0)
815 if (j == COSIZE) { /* can free this block */
817 tentryg->nextsg = centry.next;
819 hentry.next = centry.next;
820 code = pr_WriteCoEntry(at, 0, hloc, &hentry);
824 code = FreeBlock(at, nptr);
827 } else { /* can't free it yet */
828 code = pr_WriteCoEntry(at, 0, nptr, ¢ry);
833 code = pr_WriteEntry(at, 0, temp, &tentry);
838 if (centry.entries[i] == 0) {
841 } /* for all coentry slots */
844 memcpy((char *)¢ry, (char *)&hentry, sizeof(centry));
845 } /* while there are coentries */
849 #endif /* SUPERGROUPS */
851 /* DeleteEntry - delete the entry in tentry at loc, removing it from all
852 * groups, putting groups owned by it on orphan chain, and freeing the space */
855 DeleteEntry(struct ubik_trans *at, struct prentry *tentry, afs_int32 loc)
858 struct contentry centry;
862 if (strchr(tentry->name, '@')) {
863 if (tentry->flags & PRGRP) {
864 /* If there are still foreign user accounts from that cell
865 * don't delete the group */
871 afs_int32 loc = FindByID(at, tentry->cellid);
872 struct prentry centry;
874 code = pr_Read(at, 0, loc, ¢ry, sizeof(centry));
877 if (ntohl(centry.flags) & PRQUOTA) {
878 centry.ngroups = htonl(ntohl(centry.ngroups) + 1);
880 code = pr_Write(at, 0, loc, ¢ry, sizeof(centry));
886 /* First remove the entire membership list */
887 for (i = 0; i < PRSIZE; i++) {
888 if (tentry->entries[i] == PRBADID)
890 if (tentry->entries[i] == 0)
892 #if defined(SUPERGROUPS)
893 if ((tentry->flags & PRGRP) && tentry->entries[i] < 0) /* Supergroup */
894 code = RemoveFromSGEntry(at, tentry->id, tentry->entries[i]);
897 code = RemoveFromEntry(at, tentry->id, tentry->entries[i]);
901 #if defined(SUPERGROUPS)
903 struct prentryg *tentryg = (struct prentryg *)tentry;
905 /* Then remove the entire supergroup list */
906 for (i = 0; i < SGSIZE; i++) {
907 if (tentryg->supergroup[i] == PRBADID)
909 if (tentryg->supergroup[i] == 0)
911 code = RemoveFromEntry(at, tentry->id, tentryg->supergroup[i]);
916 #endif /* SUPERGROUPS */
918 while (nptr != (afs_int32) NULL) {
919 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
922 for (i = 0; i < COSIZE; i++) {
923 if (centry.entries[i] == PRBADID)
925 if (centry.entries[i] == 0)
927 code = RemoveFromEntry(at, tentry->id, centry.entries[i]);
931 code = FreeBlock(at, nptr); /* free continuation block */
937 /* Remove us from other's owned chain. Note that this will zero our owned
938 * field (on disk) so this step must follow the above step in case we are
939 * on our own owned list. */
940 if (tentry->flags & PRGRP) {
942 code = RemoveFromOwnerChain(at, tentry->id, tentry->owner);
946 code = RemoveFromOrphan(at, tentry->id);
952 code = RemoveFromIDHash(at, tentry->id, &loc);
953 if (code != PRSUCCESS)
955 code = RemoveFromNameHash(at, tentry->name, &loc);
956 if (code != PRSUCCESS)
959 if (tentry->flags & PRGRP) {
960 afs_int32 loc = FindByID(at, tentry->creator);
961 struct prentry centry;
965 code = pr_Read(at, 0, loc, ¢ry, sizeof(centry));
968 admin = ((tentry->creator == SYSADMINID)
969 || IsAMemberOf(at, tentry->creator, SYSADMINID));
970 if (ntohl(centry.flags) & PRQUOTA) {
971 if (!(admin && (ntohl(centry.ngroups) >= 20))) {
972 centry.ngroups = htonl(ntohl(centry.ngroups) + 1);
975 code = pr_Write(at, 0, loc, ¢ry, sizeof(centry));
981 if (tentry->flags & PRGRP) {
982 if (inc_header_word(at, groupcount, -1))
984 } else if (tentry->flags & PRINST) {
985 if (inc_header_word(at, instcount, -1))
988 if (strchr(tentry->name, '@')) {
989 if (inc_header_word(at, foreigncount, -1))
992 if (inc_header_word(at, usercount, -1))
996 code = FreeBlock(at, loc);
1000 /* AddToEntry - add aid to entry's entries list, alloc'ing a continuation block
1003 * Note the entry is written out by this routine. */
1006 AddToEntry(struct ubik_trans *tt, struct prentry *entry, afs_int32 loc, afs_int32 aid)
1010 struct contentry nentry;
1011 struct contentry aentry;
1013 afs_int32 last; /* addr of last cont. block */
1014 afs_int32 first = 0;
1016 afs_int32 slot = -1;
1018 if (entry->id == aid)
1019 return PRINCONSISTENT;
1020 #ifdef PR_REMEMBER_TIMES
1021 entry->addTime = time(0);
1023 for (i = 0; i < PRSIZE; i++) {
1024 if (entry->entries[i] == aid)
1026 if (entry->entries[i] == PRBADID) { /* remember this spot */
1029 } else if (entry->entries[i] == 0) { /* end of the line */
1039 while (nptr != (afs_int32) NULL) {
1040 code = pr_ReadCoEntry(tt, 0, nptr, &nentry);
1044 if (!(nentry.flags & PRCONT))
1046 for (i = 0; i < COSIZE; i++) {
1047 if (nentry.entries[i] == aid)
1049 if (nentry.entries[i] == PRBADID) {
1054 } else if (nentry.entries[i] == 0) {
1064 if (slot != -1) { /* we found a place */
1066 if (first) { /* place is in first block */
1067 entry->entries[slot] = aid;
1068 code = pr_WriteEntry(tt, 0, loc, entry);
1073 code = pr_WriteEntry(tt, 0, loc, entry);
1076 code = pr_ReadCoEntry(tt, 0, cloc, &aentry);
1079 aentry.entries[slot] = aid;
1080 code = pr_WriteCoEntry(tt, 0, cloc, &aentry);
1085 /* have to allocate a continuation block if we got here */
1086 nptr = AllocBlock(tt);
1088 /* then we should tack new block after last block in cont. chain */
1090 code = pr_WriteCoEntry(tt, 0, last, &nentry);
1096 memset(&aentry, 0, sizeof(aentry));
1097 aentry.flags |= PRCONT;
1098 aentry.id = entry->id;
1100 aentry.entries[0] = aid;
1101 code = pr_WriteCoEntry(tt, 0, nptr, &aentry);
1104 /* don't forget to update count, here! */
1106 code = pr_WriteEntry(tt, 0, loc, entry);
1111 #if defined(SUPERGROUPS)
1113 /* AddToSGEntry - add aid to entry's supergroup list, alloc'ing a
1114 * continuation block if needed.
1116 * Note the entry is written out by this routine. */
1119 AddToSGEntry(struct ubik_trans *tt, struct prentry *entry, afs_int32 loc, afs_int32 aid)
1121 register afs_int32 code;
1123 struct contentry nentry;
1124 struct contentry aentry;
1125 struct prentryg *entryg;
1127 afs_int32 last; /* addr of last cont. block */
1128 afs_int32 first = 0;
1130 afs_int32 slot = -1;
1132 if (entry->id == aid)
1133 return PRINCONSISTENT;
1134 #ifdef PR_REMEMBER_TIMES
1135 entry->addTime = time(NULL);
1137 entryg = (struct prentryg *)entry;
1138 for (i = 0; i < SGSIZE; i++) {
1139 if (entryg->supergroup[i] == aid)
1141 if (entryg->supergroup[i] == PRBADID) { /* remember this spot */
1144 } else if (entryg->supergroup[i] == 0) { /* end of the line */
1153 nptr = entryg->nextsg;
1155 code = pr_ReadCoEntry(tt, 0, nptr, &nentry);
1159 if (!(nentry.flags & PRCONT))
1161 for (i = 0; i < COSIZE; i++) {
1162 if (nentry.entries[i] == aid)
1164 if (nentry.entries[i] == PRBADID) {
1169 } else if (nentry.entries[i] == 0) {
1179 if (slot != -1) { /* we found a place */
1181 if (first) { /* place is in first block */
1182 entryg->supergroup[slot] = aid;
1183 code = pr_WriteEntry(tt, 0, loc, entry);
1188 code = pr_WriteEntry(tt, 0, loc, entry);
1191 code = pr_ReadCoEntry(tt, 0, cloc, &aentry);
1194 aentry.entries[slot] = aid;
1195 code = pr_WriteCoEntry(tt, 0, cloc, &aentry);
1200 /* have to allocate a continuation block if we got here */
1201 nptr = AllocBlock(tt);
1203 /* then we should tack new block after last block in cont. chain */
1205 code = pr_WriteCoEntry(tt, 0, last, &nentry);
1209 entryg->nextsg = nptr;
1211 memset(&aentry, 0, sizeof(aentry));
1212 aentry.flags |= PRCONT;
1213 aentry.id = entry->id;
1215 aentry.entries[0] = aid;
1216 code = pr_WriteCoEntry(tt, 0, nptr, &aentry);
1219 /* don't forget to update count, here! */
1221 code = pr_WriteEntry(tt, 0, loc, entry);
1225 #endif /* SUPERGROUPS */
1228 AddToPRList(prlist *alist, int *sizeP, afs_int32 id)
1233 if (alist->prlist_len >= *sizeP) {
1234 count = alist->prlist_len + 100;
1235 if (alist->prlist_val) {
1237 (char *)realloc(alist->prlist_val, count * sizeof(afs_int32));
1239 tmp = (char *)malloc(count * sizeof(afs_int32));
1243 alist->prlist_val = (afs_int32 *) tmp;
1246 alist->prlist_val[alist->prlist_len++] = id;
1251 GetList(struct ubik_trans *at, struct prentry *tentry, prlist *alist, afs_int32 add)
1255 struct contentry centry;
1261 alist->prlist_val = 0;
1262 alist->prlist_len = 0;
1264 for (i = 0; i < PRSIZE; i++) {
1265 if (tentry->entries[i] == PRBADID)
1267 if (tentry->entries[i] == 0)
1269 code = AddToPRList(alist, &size, tentry->entries[i]);
1272 #if defined(SUPERGROUPS)
1275 code = GetListSG2(at, tentry->entries[i], alist, &size, depthsg);
1281 for (nptr = tentry->next; nptr != 0; nptr = centry.next) {
1282 /* look through cont entries */
1283 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1286 for (i = 0; i < COSIZE; i++) {
1287 if (centry.entries[i] == PRBADID)
1289 if (centry.entries[i] == 0)
1291 code = AddToPRList(alist, &size, centry.entries[i]);
1294 #if defined(SUPERGROUPS)
1297 code = GetListSG2(at, centry.entries[i], alist, &size, depthsg);
1303 #ifndef AFS_PTHREAD_ENV
1310 if (add) { /* this is for a CPS, so tack on appropriate stuff */
1311 if (tentry->id != ANONYMOUSID && tentry->id != ANYUSERID) {
1312 if ((code = AddToPRList(alist, &size, ANYUSERID))
1313 || (code = AddAuthGroup(tentry, alist, &size))
1314 || (code = AddToPRList(alist, &size, tentry->id)))
1317 if ((code = AddToPRList(alist, &size, ANYUSERID))
1318 || (code = AddToPRList(alist, &size, tentry->id)))
1322 #ifndef AFS_PTHREAD_ENV
1323 if (alist->prlist_len > 100)
1326 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
1332 GetList2(struct ubik_trans *at, struct prentry *tentry, struct prentry *tentry2, prlist *alist, afs_int32 add)
1336 struct contentry centry;
1342 alist->prlist_val = 0;
1343 alist->prlist_len = 0;
1344 for (i = 0; i < PRSIZE; i++) {
1345 if (tentry->entries[i] == PRBADID)
1347 if (tentry->entries[i] == 0)
1349 code = AddToPRList(alist, &size, tentry->entries[i]);
1352 #if defined(SUPERGROUPS)
1355 code = GetListSG2(at, tentry->entries[i], alist, &size, depthsg);
1361 nptr = tentry->next;
1362 while (nptr != (afs_uint32) NULL) {
1363 /* look through cont entries */
1364 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1367 for (i = 0; i < COSIZE; i++) {
1368 if (centry.entries[i] == PRBADID)
1370 if (centry.entries[i] == 0)
1372 code = AddToPRList(alist, &size, centry.entries[i]);
1375 #if defined(SUPERGROUPS)
1378 code = GetListSG2(at, centry.entries[i], alist, &size, depthsg);
1385 #ifndef AFS_PTHREAD_ENV
1392 for (i = 0; i < PRSIZE; i++) {
1393 if (tentry2->entries[i] == PRBADID)
1395 if (tentry2->entries[i] == 0)
1397 code = AddToPRList(alist, &size, tentry2->entries[i]);
1403 nptr = tentry2->next;
1404 while (nptr != (afs_uint32) NULL) {
1405 /* look through cont entries */
1406 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1409 for (i = 0; i < COSIZE; i++) {
1410 if (centry.entries[i] == PRBADID)
1412 if (centry.entries[i] == 0)
1414 code = AddToPRList(alist, &size, centry.entries[i]);
1420 #ifndef AFS_PTHREAD_ENV
1427 if (add) { /* this is for a CPS, so tack on appropriate stuff */
1428 if (tentry->id != ANONYMOUSID && tentry->id != ANYUSERID) {
1429 if ((code = AddToPRList(alist, &size, ANYUSERID))
1430 || (code = AddToPRList(alist, &size, AUTHUSERID))
1431 || (code = AddToPRList(alist, &size, tentry->id)))
1434 if ((code = AddToPRList(alist, &size, ANYUSERID))
1435 || (code = AddToPRList(alist, &size, tentry->id)))
1439 #ifndef AFS_PTHREAD_ENV
1440 if (alist->prlist_len > 100)
1443 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
1447 #if defined(SUPERGROUPS)
1450 GetListSG2(struct ubik_trans *at, afs_int32 gid, prlist *alist, afs_int32 *sizeP, afs_int32 depth)
1452 register afs_int32 code;
1453 struct prentry tentry;
1454 struct prentryg *tentryg = (struct prentryg *)&tentry;
1456 struct contentry centry;
1462 int predictfound, predictflagged;
1467 if (!in_map(sg_flagged, -gid)) {
1469 fprintf(stderr, "GetListSG2: I have not yet searched for gid=%d\n",
1471 } else if (predictflagged = 1, in_map(sg_found, -gid)) {
1474 "GetListSG2: I have already searched for gid=%d, and predict success.\n",
1479 if (in_map(sg_flagged, -gid) && !in_map(sg_found, -gid)) {
1482 "GetListSG2: I have already searched for gid=%d, and predict failure.\n",
1491 temp = FindByID(at, gid);
1496 code = pr_ReadEntry(at, 0, temp, &tentry);
1500 fprintf(stderr, "GetListSG2: lookup for gid=%d [\n", gid);
1504 for (i = 0; i < SGSIZE; i++) {
1505 if (tentryg->supergroup[i] == PRBADID)
1507 if (tentryg->supergroup[i] == 0)
1511 fprintf(stderr, "via gid=%d, added %d\n", gid,
1512 e.tentryg.supergroup[i]);
1514 code = AddToPRList(alist, sizeP, tentryg->supergroup[i]);
1518 GetListSG2(at, tentryg->supergroup[i], alist, sizeP, depth - 1);
1523 nptr = tentryg->nextsg;
1526 /* look through cont entries */
1527 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1530 for (i = 0; i < COSIZE; i++) {
1531 if (centry.entries[i] == PRBADID)
1533 if (centry.entries[i] == 0)
1536 fprintf(stderr, "via gid=%d, added %d\n", gid,
1537 e.centry.entries[i]);
1539 code = AddToPRList(alist, sizeP, centry.entries[i]);
1542 code = GetListSG2(at, centry.entries[i], alist, sizeP, depth - 1);
1548 #ifndef AFS_PTHREAD_ENV
1555 fprintf(stderr, "] for gid %d, done [flag=%s]\n", gid,
1556 didsomething ? "TRUE" : "FALSE");
1557 if (predictflagged && didsomething != predictfound)
1558 fprintf(stderr, "**** for gid=%d, didsomething=%d predictfound=%d\n",
1559 didsomething, predictfound);
1562 sg_found = add_map(sg_found, -gid);
1564 sg_found = bic_map(sg_found, add_map(NIL_MAP, -gid));
1565 sg_flagged = add_map(sg_flagged, -gid);
1570 GetSGList(struct ubik_trans *at, struct prentry *tentry, prlist *alist)
1572 register afs_int32 code;
1574 struct contentry centry;
1575 struct prentryg *tentryg;
1581 alist->prlist_val = 0;
1582 alist->prlist_len = 0;
1584 tentryg = (struct prentryg *)tentry;
1585 for (i = 0; i < SGSIZE; i++) {
1586 if (tentryg->supergroup[i] == PRBADID)
1588 if (tentryg->supergroup[i] == 0)
1590 code = AddToPRList(alist, &size, tentryg->supergroup[i]);
1595 nptr = tentryg->nextsg;
1597 /* look through cont entries */
1598 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1601 for (i = 0; i < COSIZE; i++) {
1602 if (centry.entries[i] == PRBADID)
1604 if (centry.entries[i] == 0)
1606 code = AddToPRList(alist, &size, centry.entries[i]);
1612 #ifndef AFS_PTHREAD_ENV
1619 #ifndef AFS_PTHREAD_ENV
1620 if (alist->prlist_len > 100)
1623 qsort((char *)alist->prlist_val, (int)alist->prlist_len,
1624 sizeof(afs_int32), IDCmp);
1627 #endif /* SUPERGROUPS */
1630 GetOwnedChain(struct ubik_trans *ut, afs_int32 *next, prlist *alist)
1633 struct prentry tentry;
1638 alist->prlist_val = 0;
1639 alist->prlist_len = 0;
1641 for (; *next; *next = ntohl(tentry.nextOwned)) {
1642 code = pr_Read(ut, 0, *next, &tentry, sizeof(tentry));
1645 code = AddToPRList(alist, &size, ntohl(tentry.id));
1646 if (alist->prlist_len >= PR_MAXGROUPS) {
1652 #ifndef AFS_PTHREAD_ENV
1658 #ifndef AFS_PTHREAD_ENV
1659 if (alist->prlist_len > 100)
1662 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
1667 GetMax(struct ubik_trans *at, afs_int32 *uid, afs_int32 *gid)
1669 *uid = ntohl(cheader.maxID);
1670 *gid = ntohl(cheader.maxGroup);
1675 SetMax(struct ubik_trans *at, afs_int32 id, afs_int32 flag)
1679 cheader.maxGroup = htonl(id);
1681 pr_Write(at, 0, 16, (char *)&cheader.maxGroup,
1682 sizeof(cheader.maxGroup));
1686 cheader.maxID = htonl(id);
1688 pr_Write(at, 0, 20, (char *)&cheader.maxID,
1689 sizeof(cheader.maxID));
1697 read_DbHeader(struct ubik_trans *tt)
1701 if (!ubik_CacheUpdate(tt))
1704 code = pr_Read(tt, 0, 0, (char *)&cheader, sizeof(cheader));
1706 afs_com_err(whoami, code, "Couldn't read header");
1712 afs_int32 initd = 0;
1718 struct ubik_trans *tt;
1721 /* init the database. We'll try reading it, but if we're starting
1722 * from scratch, we'll have to do a write transaction. */
1724 pr_noAuth = afsconf_GetNoAuthFlag(prdir);
1726 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1729 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1731 ubik_AbortTrans(tt);
1736 } else if (!ubik_CacheUpdate(tt)) {
1737 code = ubik_EndTrans(tt);
1741 len = sizeof(cheader);
1742 code = pr_Read(tt, 0, 0, (char *)&cheader, len);
1744 afs_com_err(whoami, code, "couldn't read header");
1745 ubik_AbortTrans(tt);
1748 if ((ntohl(cheader.version) == PRDBVERSION)
1749 && ntohl(cheader.headerSize) == sizeof(cheader)
1750 && ntohl(cheader.eofPtr) != (afs_uint32) NULL
1751 && FindByID(tt, ANONYMOUSID) != 0) {
1752 /* database exists, so we don't have to build it */
1753 code = ubik_EndTrans(tt);
1758 /* else we need to build a database */
1759 code = ubik_EndTrans(tt);
1763 /* Only rebuild database if the db was deleted (the header is zero) and we
1764 * are running noAuth. */
1766 char *bp = (char *)&cheader;
1768 for (i = 0; i < sizeof(cheader); i++)
1771 afs_com_err(whoami, code,
1772 "Can't rebuild database because it is not empty");
1778 afs_com_err(whoami, code,
1779 "Can't rebuild database because not running NoAuth");
1783 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1787 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1789 ubik_AbortTrans(tt);
1793 /* before doing a rebuild, check again that the dbase looks bad, because
1794 * the previous check was only under a ReadAny transaction, and there could
1795 * actually have been a good database out there. Now that we have a
1796 * real write transaction, make sure things are still bad.
1798 if ((ntohl(cheader.version) == PRDBVERSION)
1799 && ntohl(cheader.headerSize) == sizeof(cheader)
1800 && ntohl(cheader.eofPtr) != (afs_uint32) NULL
1801 && FindByID(tt, ANONYMOUSID) != 0) {
1802 /* database exists, so we don't have to build it */
1803 code = ubik_EndTrans(tt);
1809 /* Initialize the database header */
1810 if ((code = set_header_word(tt, version, htonl(PRDBVERSION)))
1811 || (code = set_header_word(tt, headerSize, htonl(sizeof(cheader))))
1812 || (code = set_header_word(tt, eofPtr, cheader.headerSize))) {
1813 afs_com_err(whoami, code, "couldn't write header words");
1814 ubik_AbortTrans(tt);
1817 #define InitialGroup(id,name) do { \
1818 afs_int32 temp = (id); \
1819 afs_int32 flag = (id) < 0 ? PRGRP : 0; \
1820 code = CreateEntry \
1821 (tt, (name), &temp, /*idflag*/1, flag, SYSADMINID, SYSADMINID); \
1823 afs_com_err (whoami, code, "couldn't create %s with id %di.", \
1825 ubik_AbortTrans(tt); \
1830 InitialGroup(SYSADMINID, "system:administrators");
1831 InitialGroup(SYSBACKUPID, "system:backup");
1832 InitialGroup(ANYUSERID, "system:anyuser");
1833 InitialGroup(AUTHUSERID, "system:authuser");
1834 InitialGroup(SYSVIEWERID, "system:ptsviewers");
1835 InitialGroup(ANONYMOUSID, "anonymous");
1837 /* Well, we don't really want the max id set to anonymousid, so we'll set
1839 code = set_header_word(tt, maxID, 0); /* correct in any byte order */
1841 afs_com_err(whoami, code, "couldn't reset max id");
1842 ubik_AbortTrans(tt);
1846 code = ubik_EndTrans(tt);
1853 ChangeEntry(struct ubik_trans *at, afs_int32 aid, afs_int32 cid, char *name, afs_int32 oid, afs_int32 newid)
1856 afs_int32 i, nptr, pos;
1857 #if defined(SUPERGROUPS)
1860 struct contentry centry;
1861 struct prentry tentry, tent;
1864 char holder[PR_MAXNAMELEN];
1865 char temp[PR_MAXNAMELEN];
1866 char oldname[PR_MAXNAMELEN];
1869 memset(holder, 0, PR_MAXNAMELEN);
1870 memset(temp, 0, PR_MAXNAMELEN);
1871 loc = FindByID(at, aid);
1874 code = pr_ReadEntry(at, 0, loc, &tentry);
1877 if (restricted && !IsAMemberOf(at, cid, SYSADMINID))
1879 if (tentry.owner != cid && !IsAMemberOf(at, cid, SYSADMINID)
1880 && !IsAMemberOf(at, cid, tentry.owner) && !pr_noAuth)
1882 #ifdef PR_REMEMBER_TIMES
1883 tentry.changeTime = time(0);
1886 /* we're actually trying to change the id */
1887 if (newid && (newid != aid)) {
1888 if (!IsAMemberOf(at, cid, SYSADMINID) && !pr_noAuth)
1891 pos = FindByID(at, newid);
1893 return PRIDEXIST; /* new id already in use! */
1894 if ((aid < 0 && newid > 0) || (aid > 0 && newid < 0))
1897 /* Should check that foreign users id to change to is good: inRange() */
1899 /* if new id is not in use, rehash things */
1900 code = RemoveFromIDHash(at, aid, &loc);
1901 if (code != PRSUCCESS)
1904 code = pr_WriteEntry(at, 0, loc, &tentry);
1907 code = AddToIDHash(at, tentry.id, loc);
1911 /* get current data */
1912 code = pr_ReadEntry(at, 0, loc, &tentry);
1916 #if defined(SUPERGROUPS)
1917 if (tentry.id > (afs_int32) ntohl(cheader.maxID))
1918 code = set_header_word(at, maxID, htonl(tentry.id));
1922 /* need to fix up: membership
1927 for (i = 0; i < PRSIZE; i++) {
1928 if (tentry.entries[i] == PRBADID)
1930 if (tentry.entries[i] == 0)
1932 if ((tentry.flags & PRGRP) && tentry.entries[i] < 0) { /* Supergroup */
1933 return 5; /* not yet, in short. */
1935 code = ChangeIDEntry(at, aid, newid, tentry.entries[i]);
1940 for (pos = ntohl(tentry.owned); pos; pos = nextpos) {
1941 code = pr_ReadEntry(at, 0, pos, &tent);
1945 nextpos = tent.nextOwned;
1946 code = pr_WriteEntry(at, 0, pos, &tent);
1952 #define centry (*(struct contentry*)&tent)
1953 code = pr_ReadCoEntry(at, 0, pos, ¢ry);
1954 if ((centry.id != aid)
1955 || !(centry.flags & PRCONT)) {
1957 "ChangeEntry: bad database aid=%d centry.id=%d .flags=%d\n",
1958 aid, centry.id, centry.flags);
1962 for (i = 0; i < COSIZE; i++) {
1963 if (centry.entries[i] == PRBADID)
1965 if (centry.entries[i] == 0)
1967 if ((centry.flags & PRGRP) && centry.entries[i] < 0) { /* Supergroup */
1968 return 5; /* not yet, in short. */
1970 code = ChangeIDEntry(at, aid, newid, centry.entries[i]);
1975 code = pr_WriteCoEntry(at, 0, pos, ¢ry);
1982 #else /* SUPERGROUPS */
1985 /* Also change the references from the membership list */
1986 for (i = 0; i < PRSIZE; i++) {
1987 if (tentry.entries[i] == PRBADID)
1989 if (tentry.entries[i] == 0)
1991 pos = FindByID(at, tentry.entries[i]);
1994 code = RemoveFromEntry(at, aid, tentry.entries[i]);
1997 code = pr_ReadEntry(at, 0, pos, &tent);
2000 code = AddToEntry(at, &tent, pos, newid);
2004 /* Look through cont entries too. This needs to be broken into
2005 * seperate transaction so that no one transaction becomes too
2006 * large to complete.
2008 for (nptr = tentry.next; nptr; nptr = centry.next) {
2009 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
2012 for (i = 0; i < COSIZE; i++) {
2013 if (centry.entries[i] == PRBADID)
2015 if (centry.entries[i] == 0)
2017 pos = FindByID(at, centry.entries[i]);
2020 code = RemoveFromEntry(at, aid, centry.entries[i]);
2023 code = pr_ReadEntry(at, 0, pos, &tent);
2026 code = AddToEntry(at, &tent, pos, newid);
2031 #endif /* SUPERGROUPS */
2034 atsign = strchr(tentry.name, '@'); /* check for foreign entry */
2036 /* Change the owner */
2037 if (oid && (oid != tentry.owner)) {
2038 /* only groups can have their owner's changed */
2039 if (!(tentry.flags & PRGRP))
2043 oldowner = tentry.owner;
2045 /* The entry must be written through first so Remove and Add routines
2046 * can operate on disk data */
2047 code = pr_WriteEntry(at, 0, loc, &tentry);
2051 /* switch owner chains */
2052 if (oldowner) /* if it has an owner */
2053 code = RemoveFromOwnerChain(at, tentry.id, oldowner);
2054 else /* must be an orphan */
2055 code = RemoveFromOrphan(at, tentry.id);
2058 code = AddToOwnerChain(at, tentry.id, tentry.owner);
2062 /* fix up the name */
2063 if (strlen(name) == 0)
2065 /* get current data */
2066 code = pr_ReadEntry(at, 0, loc, &tentry);
2071 /* Change the name, if name is a ptr to tentry.name then this name change
2072 * is due to a chown, otherwise caller has specified a new name */
2073 if ((name == tentry.name) || (*name && (strcmp(tentry.name, name) != 0))) {
2074 strncpy(oldname, tentry.name, PR_MAXNAMELEN);
2075 if (tentry.flags & PRGRP) {
2076 /* don't let foreign cell groups change name */
2079 code = CorrectGroupName(at, name, cid, tentry.owner, tentry.name);
2083 if (name == tentry.name) { /* owner fixup */
2084 if (strcmp(oldname, tentry.name) == 0)
2086 } else { /* new name, caller must be correct */
2087 if (strcmp(name, tentry.name) != 0)
2091 /* Allow a foreign name change only if the cellname part is
2096 newatsign = strchr(name, '@');
2097 if (newatsign != atsign) { /* if they are the same no problem */
2098 /*if the pointers are not equal the strings better be */
2099 if ((atsign == NULL) || (newatsign == NULL)
2100 || strcmp(atsign, newatsign))
2103 if (!CorrectUserName(name))
2107 pos = FindByName(at, name, &tent);
2110 code = RemoveFromNameHash(at, oldname, &loc);
2111 if (code != PRSUCCESS)
2113 strncpy(tentry.name, name, PR_MAXNAMELEN);
2114 code = pr_WriteEntry(at, 0, loc, &tentry);
2117 code = AddToNameHash(at, tentry.name, loc);
2118 if (code != PRSUCCESS)
2127 allocNextId(struct ubik_trans * at, struct prentry * cellEntry)
2129 /* Id's for foreign cell entries are constructed as follows:
2130 * The 16 low order bits are the group id of the cell and the
2131 * top 16 bits identify the particular users in that cell */
2134 afs_int32 cellid = ((ntohl(cellEntry->id)) & 0x0000ffff);
2136 id = (ntohl(cellEntry->nusers) + 1);
2137 while (FindByID(at, ((id << 16) | cellid))) {
2143 cellEntry->nusers = htonl(id);
2144 /* use the field nusers to keep
2145 * the next available id in that
2146 * foreign cell's group. Note :
2147 * It would seem more appropriate
2148 * to use ngroup for that and nusers
2149 * to enforce the quota, however pts
2150 * does not have an option to change
2151 * foreign users quota yet */
2153 id = (id << 16) | cellid;
2158 inRange(struct prentry *cellEntry, afs_int32 aid)
2160 afs_uint32 id, cellid, groupid;
2164 * The only thing that we want to make sure here is that
2165 * the id is in the legal range of this group. If it is
2166 * a duplicate we don't care since it will get caught
2167 * in a different check.
2170 cellid = aid & 0x0000ffff;
2171 groupid = (ntohl(cellEntry->id)) & 0x0000ffff;
2172 if (cellid != groupid)
2173 return 0; /* not in range */
2176 * if we got here we're ok but we need to update the nusers
2177 * field in order to get the id correct the next time that
2178 * we try to allocate it automatically
2182 if (id > ntohl(cellEntry->nusers))
2183 cellEntry->nusers = htonl(id);
2189 AddAuthGroup(struct prentry *tentry, prlist *alist, afs_int32 *size)
2191 if (!(strchr(tentry->name, '@')))
2192 return (AddToPRList(alist, size, AUTHUSERID));