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>
30 #include <sys/types.h>
35 #include <netinet/in.h>
41 #include <afs/com_err.h>
42 #include <afs/cellconfig.h>
47 /* Foreign cells are represented by the group system:authuser@cell*/
48 #define AUTHUSER_GROUP "system:authuser"
50 extern int restricted;
51 extern struct ubik_dbase *dbase;
52 extern struct afsconf_dir *prdir;
56 extern afs_int32 AddToEntry();
57 static char *whoami = "ptserver";
59 int prp_user_default = PRP_USER_DEFAULT;
60 int prp_group_default = PRP_GROUP_DEFAULT;
62 #if defined(SUPERGROUPS)
66 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);
70 afs_int32 allocNextId(struct ubik_trans *, struct prentry *);
72 struct map *sg_flagged;
75 #define NIL_MAP ((struct map *) 0)
77 /* pt_mywrite hooks into the logic that writes ubik records to disk
78 * at a very low level. It invalidates mappings in sg_flagged/sg_found.
79 * By hoooking in at this level, we ensure that a ubik file reload
80 * invalidates our incore cache.
82 * We assert records, cheaders and everything else are 0 mod 64.
83 * So, we can always see the first 64 bytes of any record written.
84 * The stuff we're interested in (flags, id) are in the first 8 bytes.
85 * so we can always tell if we're writing a group record.
88 int (*pt_save_dbase_write) ();
91 pt_mywrite(struct ubik_dbase *tdb, afs_int32 fno, char *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 (strlen(name) >= PR_MAXNAMELEN - pr_realmNameLen - 1)
199 /* CorrectGroupName - Like the above but handles more complicated cases caused
200 * by including the ownership in the name. The interface works by calculating
201 * the correct name based on a given name and owner. This allows easy use by
202 * rename, which then compares the correct name with the requested new name. */
205 CorrectGroupName(struct ubik_trans *ut, char aname[PR_MAXNAMELEN], /* name for group */
206 afs_int32 cid, /* caller id */
207 afs_int32 oid, /* owner of group */
208 char cname[PR_MAXNAMELEN]) /* correct name for group */
212 char *prefix; /* ptr to group owner part */
213 char *suffix; /* ptr to group name part */
214 char name[PR_MAXNAMELEN]; /* correct name for group */
215 struct prentry tentry;
217 if (strlen(aname) >= PR_MAXNAMELEN)
219 admin = pr_noAuth || IsAMemberOf(ut, cid, SYSADMINID);
224 /* Determine the correct prefix for the name. */
225 if (oid == SYSADMINID)
228 afs_int32 loc = FindByID(ut, oid);
230 /* let admin create groups owned by non-existent ids (probably
231 * setting a group to own itself). Check that they look like
232 * groups (with a colon) or otherwise are good user names. */
234 strcpy(cname, aname);
239 code = pr_Read(ut, 0, loc, &tentry, sizeof(tentry));
242 if (ntohl(tentry.flags) & PRGRP) {
243 if ((tentry.count == 0) && !admin)
245 /* terminate prefix at colon if there is one */
246 if ((prefix = strchr(tentry.name, ':')))
249 prefix = tentry.name;
251 /* only sysadmin allow to use 'system:' prefix */
252 if ((strcmp(prefix, "system") == 0) && !admin)
255 strcpy(name, aname); /* in case aname & cname are same */
256 suffix = strchr(name, ':');
258 /* sysadmin can make groups w/o ':', but they must still look like
259 * legal user names. */
264 if (strlen(prefix) + strlen(suffix) >= PR_MAXNAMELEN)
266 strcpy(cname, prefix);
267 strcat(cname, suffix);
270 /* check for legal name with either group rules or user rules */
271 if ((suffix = strchr(cname, ':'))) {
272 /* check for confusing characters */
273 if (strchr(cname, '\n') || /* restrict so recreate can work */
274 strchr(suffix + 1, ':')) /* avoid multiple colons */
277 if (!CorrectUserName(cname))
284 AccessOK(struct ubik_trans *ut, afs_int32 cid, /* caller id */
285 struct prentry *tentry, /* object being accessed */
286 int mem, /* check membership in aid, if group */
287 int any) /* if set return true */
295 if (cid == SYSADMINID)
296 return 1; /* special case fileserver */
297 if (restricted && ((mem == PRP_ADD_MEM) || (mem == any == 0)))
300 flags = tentry->flags;
304 flags = oid = aid = 0;
306 if (!(flags & PRACCESS)) { /* provide default access */
308 flags |= prp_group_default;
310 flags |= prp_user_default;
316 if ((cid == oid) || IsAMemberOf(ut, cid, oid))
319 if (aid > 0) { /* checking on a user */
322 } else if (aid < 0) { /* checking on group */
323 if ((flags & mem) && IsAMemberOf(ut, cid, aid))
326 /* Allow members of SYSVIEWERID to get membership and status only */
327 if (((mem == PRP_STATUS_MEM) || (mem == PRP_MEMBER_MEM)
328 || (any == PRP_OWNED_ANY)) && (IsAMemberOf(ut, cid, SYSVIEWERID)))
330 if (IsAMemberOf(ut, cid, SYSADMINID))
332 return 0; /* no access */
336 CreateEntry(struct ubik_trans *at, char aname[PR_MAXNAMELEN], afs_int32 *aid, afs_int32 idflag, afs_int32 flag, afs_int32 oid, afs_int32 creator)
338 /* get and init a new entry */
341 struct prentry tentry, tent;
344 memset(&tentry, 0, sizeof(tentry));
346 if ((oid == 0) || (oid == ANONYMOUSID))
350 code = CorrectGroupName(at, aname, creator, oid, tentry.name);
353 if (strcmp(aname, tentry.name) != 0)
355 } else { /* non-group must not have colon */
356 if (!CorrectUserName(aname))
358 strcpy(tentry.name, aname);
361 if (FindByName(at, aname, &tent))
364 newEntry = AllocBlock(at);
367 #ifdef PR_REMEMBER_TIMES
368 tentry.createTime = time(0);
372 tentry.flags = PRGRP;
374 } else if (flag == 0) {
376 tentry.owner = SYSADMINID;
381 atsign = strchr(aname, '@');
383 /* A normal user or group. Pick an id for it */
387 code = AllocID(at, flag, &tentry.id);
388 if (code != PRSUCCESS)
391 } else if (flag & PRGRP) {
392 /* A foreign group. Its format must be AUTHUSER_GROUP@cellname
393 * Then pick an id for the group.
398 badFormat = strcmp(AUTHUSER_GROUP, aname);
406 code = AllocID(at, flag, &tentry.id);
407 if (code != PRSUCCESS)
411 /* A foreign user: <name>@<cell>. The foreign user is added to
412 * its representing group. It is
416 struct prentry centry;
418 /* To create the user <name>@<cell> the group AUTHUSER_GROUP@<cell>
422 (char *)malloc(strlen(AUTHUSER_GROUP) + strlen(atsign) + 1);
423 strcpy(cellGroup, AUTHUSER_GROUP);
424 strcat(cellGroup, atsign);
425 pos = FindByName(at, cellGroup, ¢ry);
429 code = pr_Read(at, 0, pos, ¢ry, sizeof(centry));
433 /* cellid is the id of the group representing the cell */
434 tentry.cellid = ntohl(centry.id);
437 /* Check if id is good */
438 if (!inRange(¢ry, *aid))
442 /* Allocate an ID special for this foreign user. It is based
443 * on the representing group's id and nusers count.
445 tentry.id = allocNextId(at, ¢ry);
450 /* The foreign user will be added to the representing foreign
451 * group. The group can hold up to 30 entries.
453 if (!(ntohl(centry.flags) & PRQUOTA)) {
454 centry.flags = htonl(ntohl(centry.flags) | PRQUOTA);
455 centry.ngroups = htonl(30);
457 n = ntohl(centry.ngroups);
458 if ((n <= 0) && !pr_noAuth)
460 centry.ngroups = htonl(n - 1);
462 /* write updated entry for group */
463 code = pr_Write(at, 0, pos, ¢ry, sizeof(centry));
465 /* Now add the new user entry to the database */
466 tentry.creator = creator;
468 code = pr_WriteEntry(at, 0, newEntry, &tentry);
471 code = AddToIDHash(at, *aid, newEntry);
472 if (code != PRSUCCESS)
474 code = AddToNameHash(at, aname, newEntry);
475 if (code != PRSUCCESS)
477 if (inc_header_word(at, foreigncount, 1))
480 /* Now add the entry to the authuser group for this cell.
481 * We will reread the entries for the user and the group
482 * instead of modifying them before writing them in the
483 * previous steps. Although not very efficient, much simpler
485 pos = FindByID(at, tentry.cellid);
488 code = pr_ReadEntry(at, 0, pos, ¢ry);
491 code = AddToEntry(at, ¢ry, pos, *aid);
494 /* and now the user entry */
495 pos = FindByID(at, *aid);
498 code = pr_ReadEntry(at, 0, pos, &tentry);
501 code = AddToEntry(at, &tentry, pos, tentry.cellid);
508 /* Remember the largest group id or largest user id */
510 /* group ids are negative */
511 if (tentry.id < (afs_int32) ntohl(cheader.maxGroup)) {
512 code = set_header_word(at, maxGroup, htonl(tentry.id));
517 if (tentry.id > (afs_int32) ntohl(cheader.maxID)) {
518 code = set_header_word(at, maxID, htonl(tentry.id));
524 /* Charge the creator for this group */
526 afs_int32 loc = FindByID(at, creator);
527 struct prentry centry;
530 if (loc) { /* this should only fail during initialization */
531 code = pr_Read(at, 0, loc, ¢ry, sizeof(centry));
535 /* If quota is uninitialized, do it */
536 if (!(ntohl(centry.flags) & PRQUOTA)) {
537 centry.flags = htonl(ntohl(centry.flags) | PRQUOTA);
538 centry.ngroups = centry.nusers = htonl(20);
541 /* Admins don't get charged for creating a group.
542 * If in noAuth mode, you get changed for it but you
543 * are still allowed to create as many groups as you want.
545 admin = ((creator == SYSADMINID)
546 || IsAMemberOf(at, creator, SYSADMINID));
548 if (ntohl(centry.ngroups) <= 0) {
552 centry.ngroups = htonl(ntohl(centry.ngroups) - 1);
556 code = pr_Write(at, 0, loc, ¢ry, sizeof(centry));
561 /* Initialize the quota for the user. Groups don't have their
564 tentry.flags |= PRQUOTA;
565 tentry.ngroups = tentry.nusers = 20;
568 tentry.creator = creator;
570 code = pr_WriteEntry(at, 0, newEntry, &tentry);
573 code = AddToIDHash(at, *aid, newEntry);
574 if (code != PRSUCCESS)
576 code = AddToNameHash(at, aname, newEntry);
577 if (code != PRSUCCESS)
579 if (tentry.flags & PRGRP) {
580 code = AddToOwnerChain(at, tentry.id, oid);
584 if (tentry.flags & PRGRP) {
585 if (inc_header_word(at, groupcount, 1))
587 } else if (tentry.flags & PRINST) {
588 if (inc_header_word(at, instcount, 1))
591 if (inc_header_word(at, usercount, 1))
598 /* RemoveFromEntry - remove aid from bid's entries list, freeing a continuation
599 * entry if appropriate */
602 RemoveFromEntry(struct ubik_trans *at, afs_int32 aid, afs_int32 bid)
605 struct prentry tentry;
606 struct contentry centry;
607 struct contentry hentry;
614 return PRINCONSISTENT;
615 memset(&hentry, 0, sizeof(hentry));
616 temp = FindByID(at, bid);
619 code = pr_ReadEntry(at, 0, temp, &tentry);
622 #ifdef PR_REMEMBER_TIMES
623 tentry.removeTime = time(0);
625 for (i = 0; i < PRSIZE; i++) {
626 if (tentry.entries[i] == aid) {
627 tentry.entries[i] = PRBADID;
629 code = pr_WriteEntry(at, 0, temp, &tentry);
634 if (tentry.entries[i] == 0) /* found end of list */
640 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
643 if ((centry.id != bid) || !(centry.flags & PRCONT))
645 for (i = 0; i < COSIZE; i++) {
646 if (centry.entries[i] == aid) {
647 centry.entries[i] = PRBADID;
648 for (j = 0; j < COSIZE; j++)
649 if (centry.entries[j] != PRBADID
650 && centry.entries[j] != 0)
652 if (j == COSIZE) { /* can free this block */
654 tentry.next = centry.next;
656 hentry.next = centry.next;
657 code = pr_WriteCoEntry(at, 0, hloc, &hentry);
661 code = FreeBlock(at, nptr);
664 } else { /* can't free it yet */
665 code = pr_WriteCoEntry(at, 0, nptr, ¢ry);
670 code = pr_WriteEntry(at, 0, temp, &tentry);
675 if (centry.entries[i] == 0)
677 } /* for all coentry slots */
680 memcpy(&hentry, ¢ry, sizeof(centry));
681 } /* while there are coentries */
685 #if defined(SUPERGROUPS)
686 /* ChangeIDEntry - remove aid from bid's entries list, freeing a continuation
687 * entry if appropriate */
690 ChangeIDEntry(register struct ubik_trans *at, register afs_int32 aid, afs_int32 newid, register afs_int32 bid)
692 register afs_int32 code;
693 struct prentry tentry;
694 struct contentry centry;
700 return PRINCONSISTENT;
701 temp = FindByID(at, bid);
705 code = pr_ReadEntry(at, 0, temp, &tentry);
708 for (i = 0; i < PRSIZE; i++) {
709 if (tentry.entries[i] == aid) {
710 tentry.entries[i] = newid;
711 code = pr_WriteEntry(at, 0, temp, &tentry);
716 if (tentry.entries[i] == 0) { /* found end of list */
723 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
726 if ((centry.id != bid) || !(centry.flags & PRCONT)) {
728 "ChangeIDEntry: bad database bid=%d centry.id=%d .flags=%d\n",
729 bid, centry.id, centry.flags);
732 for (i = 0; i < COSIZE; i++) {
733 if (centry.entries[i] == aid) {
734 centry.entries[i] = newid;
735 for (j = 0; j < COSIZE; j++)
736 if (centry.entries[j] != PRBADID
737 && centry.entries[j] != 0)
739 code = pr_WriteCoEntry(at, 0, nptr, ¢ry);
744 if (centry.entries[i] == 0) {
747 } /* for all coentry slots */
749 } /* while there are coentries */
753 /* #ifdef SUPERGROUPS */
754 /* RemoveFromSGEntry - remove aid from bid's supergroups list, freeing a
755 * continuation entry if appropriate */
758 RemoveFromSGEntry(register struct ubik_trans *at, register afs_int32 aid, register afs_int32 bid)
760 register afs_int32 code;
761 struct prentry tentry;
762 struct prentryg *tentryg;
763 struct contentry centry;
764 struct contentry hentry;
771 return PRINCONSISTENT;
772 memset(&hentry, 0, sizeof(hentry));
773 temp = FindByID(at, bid);
777 code = pr_ReadEntry(at, 0, temp, &tentry);
780 #ifdef PR_REMEMBER_TIMES
781 tentry.removeTime = time(NULL);
783 tentryg = (struct prentryg *)&tentry;
784 for (i = 0; i < SGSIZE; i++) {
785 if (tentryg->supergroup[i] == aid) {
786 tentryg->supergroup[i] = PRBADID;
788 code = pr_WriteEntry(at, 0, temp, &tentry);
793 if (tentryg->supergroup[i] == 0) { /* found end of list */
798 nptr = tentryg->nextsg;
800 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
803 if ((centry.id != bid) || !(centry.flags & PRCONT)) {
805 "ChangeIDEntry: bad database bid=%d centry.id=%d .flags=%d\n",
806 bid, centry.id, centry.flags);
809 for (i = 0; i < COSIZE; i++) {
810 if (centry.entries[i] == aid) {
811 centry.entries[i] = PRBADID;
812 for (j = 0; j < COSIZE; j++)
813 if (centry.entries[j] != PRBADID
814 && centry.entries[j] != 0)
816 if (j == COSIZE) { /* can free this block */
818 tentryg->nextsg = centry.next;
820 hentry.next = centry.next;
821 code = pr_WriteCoEntry(at, 0, hloc, &hentry);
825 code = FreeBlock(at, nptr);
828 } else { /* can't free it yet */
829 code = pr_WriteCoEntry(at, 0, nptr, ¢ry);
834 code = pr_WriteEntry(at, 0, temp, &tentry);
839 if (centry.entries[i] == 0) {
842 } /* for all coentry slots */
845 memcpy((char *)¢ry, (char *)&hentry, sizeof(centry));
846 } /* while there are coentries */
850 #endif /* SUPERGROUPS */
852 /* DeleteEntry - delete the entry in tentry at loc, removing it from all
853 * groups, putting groups owned by it on orphan chain, and freeing the space */
856 DeleteEntry(struct ubik_trans *at, struct prentry *tentry, afs_int32 loc)
859 struct contentry centry;
863 if (strchr(tentry->name, '@')) {
864 if (tentry->flags & PRGRP) {
865 /* If there are still foreign user accounts from that cell
866 * don't delete the group */
872 afs_int32 loc = FindByID(at, tentry->cellid);
873 struct prentry centry;
875 code = pr_Read(at, 0, loc, ¢ry, sizeof(centry));
878 if (ntohl(centry.flags) & PRQUOTA) {
879 centry.ngroups = htonl(ntohl(centry.ngroups) + 1);
881 code = pr_Write(at, 0, loc, ¢ry, sizeof(centry));
887 /* First remove the entire membership list */
888 for (i = 0; i < PRSIZE; i++) {
889 if (tentry->entries[i] == PRBADID)
891 if (tentry->entries[i] == 0)
893 #if defined(SUPERGROUPS)
894 if ((tentry->flags & PRGRP) && tentry->entries[i] < 0) /* Supergroup */
895 code = RemoveFromSGEntry(at, tentry->id, tentry->entries[i]);
898 code = RemoveFromEntry(at, tentry->id, tentry->entries[i]);
902 #if defined(SUPERGROUPS)
904 struct prentryg *tentryg = (struct prentryg *)tentry;
906 /* Then remove the entire supergroup list */
907 for (i = 0; i < SGSIZE; i++) {
908 if (tentryg->supergroup[i] == PRBADID)
910 if (tentryg->supergroup[i] == 0)
912 code = RemoveFromEntry(at, tentry->id, tentryg->supergroup[i]);
917 #endif /* SUPERGROUPS */
919 while (nptr != (afs_int32) NULL) {
920 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
923 for (i = 0; i < COSIZE; i++) {
924 if (centry.entries[i] == PRBADID)
926 if (centry.entries[i] == 0)
928 code = RemoveFromEntry(at, tentry->id, centry.entries[i]);
932 code = FreeBlock(at, nptr); /* free continuation block */
938 /* Remove us from other's owned chain. Note that this will zero our owned
939 * field (on disk) so this step must follow the above step in case we are
940 * on our own owned list. */
941 if (tentry->flags & PRGRP) {
943 code = RemoveFromOwnerChain(at, tentry->id, tentry->owner);
947 code = RemoveFromOrphan(at, tentry->id);
953 code = RemoveFromIDHash(at, tentry->id, &loc);
954 if (code != PRSUCCESS)
956 code = RemoveFromNameHash(at, tentry->name, &loc);
957 if (code != PRSUCCESS)
960 if (tentry->flags & PRGRP) {
961 afs_int32 loc = FindByID(at, tentry->creator);
962 struct prentry centry;
966 code = pr_Read(at, 0, loc, ¢ry, sizeof(centry));
969 admin = ((tentry->creator == SYSADMINID)
970 || IsAMemberOf(at, tentry->creator, SYSADMINID));
971 if (ntohl(centry.flags) & PRQUOTA) {
972 if (!(admin && (ntohl(centry.ngroups) >= 20))) {
973 centry.ngroups = htonl(ntohl(centry.ngroups) + 1);
976 code = pr_Write(at, 0, loc, ¢ry, sizeof(centry));
982 if (tentry->flags & PRGRP) {
983 if (inc_header_word(at, groupcount, -1))
985 } else if (tentry->flags & PRINST) {
986 if (inc_header_word(at, instcount, -1))
989 if (strchr(tentry->name, '@')) {
990 if (inc_header_word(at, foreigncount, -1))
993 if (inc_header_word(at, usercount, -1))
997 code = FreeBlock(at, loc);
1001 /* AddToEntry - add aid to entry's entries list, alloc'ing a continuation block
1004 * Note the entry is written out by this routine. */
1007 AddToEntry(struct ubik_trans *tt, struct prentry *entry, afs_int32 loc, afs_int32 aid)
1011 struct contentry nentry;
1012 struct contentry aentry;
1014 afs_int32 last; /* addr of last cont. block */
1015 afs_int32 first = 0;
1017 afs_int32 slot = -1;
1019 if (entry->id == aid)
1020 return PRINCONSISTENT;
1021 #ifdef PR_REMEMBER_TIMES
1022 entry->addTime = time(0);
1024 for (i = 0; i < PRSIZE; i++) {
1025 if (entry->entries[i] == aid)
1027 if (entry->entries[i] == PRBADID) { /* remember this spot */
1030 } else if (entry->entries[i] == 0) { /* end of the line */
1040 while (nptr != (afs_int32) NULL) {
1041 code = pr_ReadCoEntry(tt, 0, nptr, &nentry);
1045 if (!(nentry.flags & PRCONT))
1047 for (i = 0; i < COSIZE; i++) {
1048 if (nentry.entries[i] == aid)
1050 if (nentry.entries[i] == PRBADID) {
1055 } else if (nentry.entries[i] == 0) {
1065 if (slot != -1) { /* we found a place */
1067 if (first) { /* place is in first block */
1068 entry->entries[slot] = aid;
1069 code = pr_WriteEntry(tt, 0, loc, entry);
1074 code = pr_WriteEntry(tt, 0, loc, entry);
1077 code = pr_ReadCoEntry(tt, 0, cloc, &aentry);
1080 aentry.entries[slot] = aid;
1081 code = pr_WriteCoEntry(tt, 0, cloc, &aentry);
1086 /* have to allocate a continuation block if we got here */
1087 nptr = AllocBlock(tt);
1089 /* then we should tack new block after last block in cont. chain */
1091 code = pr_WriteCoEntry(tt, 0, last, &nentry);
1097 memset(&aentry, 0, sizeof(aentry));
1098 aentry.flags |= PRCONT;
1099 aentry.id = entry->id;
1101 aentry.entries[0] = aid;
1102 code = pr_WriteCoEntry(tt, 0, nptr, &aentry);
1105 /* don't forget to update count, here! */
1107 code = pr_WriteEntry(tt, 0, loc, entry);
1112 #if defined(SUPERGROUPS)
1114 /* AddToSGEntry - add aid to entry's supergroup list, alloc'ing a
1115 * continuation block if needed.
1117 * Note the entry is written out by this routine. */
1120 AddToSGEntry(struct ubik_trans *tt, struct prentry *entry, afs_int32 loc, afs_int32 aid)
1122 register afs_int32 code;
1124 struct contentry nentry;
1125 struct contentry aentry;
1126 struct prentryg *entryg;
1128 afs_int32 last; /* addr of last cont. block */
1129 afs_int32 first = 0;
1131 afs_int32 slot = -1;
1133 if (entry->id == aid)
1134 return PRINCONSISTENT;
1135 #ifdef PR_REMEMBER_TIMES
1136 entry->addTime = time(NULL);
1138 entryg = (struct prentryg *)entry;
1139 for (i = 0; i < SGSIZE; i++) {
1140 if (entryg->supergroup[i] == aid)
1142 if (entryg->supergroup[i] == PRBADID) { /* remember this spot */
1145 } else if (entryg->supergroup[i] == 0) { /* end of the line */
1154 nptr = entryg->nextsg;
1156 code = pr_ReadCoEntry(tt, 0, nptr, &nentry);
1160 if (!(nentry.flags & PRCONT))
1162 for (i = 0; i < COSIZE; i++) {
1163 if (nentry.entries[i] == aid)
1165 if (nentry.entries[i] == PRBADID) {
1170 } else if (nentry.entries[i] == 0) {
1180 if (slot != -1) { /* we found a place */
1182 if (first) { /* place is in first block */
1183 entryg->supergroup[slot] = aid;
1184 code = pr_WriteEntry(tt, 0, loc, entry);
1189 code = pr_WriteEntry(tt, 0, loc, entry);
1192 code = pr_ReadCoEntry(tt, 0, cloc, &aentry);
1195 aentry.entries[slot] = aid;
1196 code = pr_WriteCoEntry(tt, 0, cloc, &aentry);
1201 /* have to allocate a continuation block if we got here */
1202 nptr = AllocBlock(tt);
1204 /* then we should tack new block after last block in cont. chain */
1206 code = pr_WriteCoEntry(tt, 0, last, &nentry);
1210 entryg->nextsg = nptr;
1212 memset(&aentry, 0, sizeof(aentry));
1213 aentry.flags |= PRCONT;
1214 aentry.id = entry->id;
1216 aentry.entries[0] = aid;
1217 code = pr_WriteCoEntry(tt, 0, nptr, &aentry);
1220 /* don't forget to update count, here! */
1222 code = pr_WriteEntry(tt, 0, loc, entry);
1226 #endif /* SUPERGROUPS */
1229 AddToPRList(prlist *alist, int *sizeP, afs_int32 id)
1234 if (alist->prlist_len >= *sizeP) {
1235 count = alist->prlist_len + 100;
1236 if (alist->prlist_val) {
1238 (char *)realloc(alist->prlist_val, count * sizeof(afs_int32));
1240 tmp = (char *)malloc(count * sizeof(afs_int32));
1244 alist->prlist_val = (afs_int32 *) tmp;
1247 alist->prlist_val[alist->prlist_len++] = id;
1252 GetList(struct ubik_trans *at, struct prentry *tentry, prlist *alist, afs_int32 add)
1256 struct contentry centry;
1262 alist->prlist_val = 0;
1263 alist->prlist_len = 0;
1265 for (i = 0; i < PRSIZE; i++) {
1266 if (tentry->entries[i] == PRBADID)
1268 if (tentry->entries[i] == 0)
1270 code = AddToPRList(alist, &size, tentry->entries[i]);
1273 #if defined(SUPERGROUPS)
1276 code = GetListSG2(at, tentry->entries[i], alist, &size, depthsg);
1282 for (nptr = tentry->next; nptr != 0; nptr = centry.next) {
1283 /* look through cont entries */
1284 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1287 for (i = 0; i < COSIZE; i++) {
1288 if (centry.entries[i] == PRBADID)
1290 if (centry.entries[i] == 0)
1292 code = AddToPRList(alist, &size, centry.entries[i]);
1295 #if defined(SUPERGROUPS)
1298 code = GetListSG2(at, centry.entries[i], alist, &size, depthsg);
1304 IOMGR_Poll(), count = 0;
1307 if (add) { /* this is for a CPS, so tack on appropriate stuff */
1308 if (tentry->id != ANONYMOUSID && tentry->id != ANYUSERID) {
1309 if ((code = AddToPRList(alist, &size, ANYUSERID))
1310 || (code = AddAuthGroup(tentry, alist, &size))
1311 || (code = AddToPRList(alist, &size, tentry->id)))
1314 if ((code = AddToPRList(alist, &size, ANYUSERID))
1315 || (code = AddToPRList(alist, &size, tentry->id)))
1319 if (alist->prlist_len > 100)
1321 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
1327 GetList2(struct ubik_trans *at, struct prentry *tentry, struct prentry *tentry2, prlist *alist, afs_int32 add)
1331 struct contentry centry;
1337 alist->prlist_val = 0;
1338 alist->prlist_len = 0;
1339 for (i = 0; i < PRSIZE; i++) {
1340 if (tentry->entries[i] == PRBADID)
1342 if (tentry->entries[i] == 0)
1344 code = AddToPRList(alist, &size, tentry->entries[i]);
1347 #if defined(SUPERGROUPS)
1350 code = GetListSG2(at, tentry->entries[i], alist, &size, depthsg);
1356 nptr = tentry->next;
1357 while (nptr != (afs_uint32) NULL) {
1358 /* look through cont entries */
1359 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1362 for (i = 0; i < COSIZE; i++) {
1363 if (centry.entries[i] == PRBADID)
1365 if (centry.entries[i] == 0)
1367 code = AddToPRList(alist, &size, centry.entries[i]);
1370 #if defined(SUPERGROUPS)
1373 code = GetListSG2(at, centry.entries[i], alist, &size, depthsg);
1380 IOMGR_Poll(), count = 0;
1383 for (i = 0; i < PRSIZE; i++) {
1384 if (tentry2->entries[i] == PRBADID)
1386 if (tentry2->entries[i] == 0)
1388 code = AddToPRList(alist, &size, tentry2->entries[i]);
1394 nptr = tentry2->next;
1395 while (nptr != (afs_uint32) NULL) {
1396 /* look through cont entries */
1397 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1400 for (i = 0; i < COSIZE; i++) {
1401 if (centry.entries[i] == PRBADID)
1403 if (centry.entries[i] == 0)
1405 code = AddToPRList(alist, &size, centry.entries[i]);
1411 IOMGR_Poll(), count = 0;
1414 if (add) { /* this is for a CPS, so tack on appropriate stuff */
1415 if (tentry->id != ANONYMOUSID && tentry->id != ANYUSERID) {
1416 if ((code = AddToPRList(alist, &size, ANYUSERID))
1417 || (code = AddToPRList(alist, &size, AUTHUSERID))
1418 || (code = AddToPRList(alist, &size, tentry->id)))
1421 if ((code = AddToPRList(alist, &size, ANYUSERID))
1422 || (code = AddToPRList(alist, &size, tentry->id)))
1426 if (alist->prlist_len > 100)
1428 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
1432 #if defined(SUPERGROUPS)
1435 GetListSG2(struct ubik_trans *at, afs_int32 gid, prlist *alist, afs_int32 *sizeP, afs_int32 depth)
1437 register afs_int32 code;
1438 struct prentry tentry;
1439 struct prentryg *tentryg = (struct prentryg *)&tentry;
1441 struct contentry centry;
1447 int predictfound, predictflagged;
1452 if (!in_map(sg_flagged, -gid)) {
1454 fprintf(stderr, "GetListSG2: I have not yet searched for gid=%d\n",
1456 } else if (predictflagged = 1, in_map(sg_found, -gid)) {
1459 "GetListSG2: I have already searched for gid=%d, and predict success.\n",
1464 if (in_map(sg_flagged, -gid) && !in_map(sg_found, -gid)) {
1467 "GetListSG2: I have already searched for gid=%d, and predict failure.\n",
1476 temp = FindByID(at, gid);
1481 code = pr_ReadEntry(at, 0, temp, &tentry);
1485 fprintf(stderr, "GetListSG2: lookup for gid=%d [\n", gid);
1489 for (i = 0; i < SGSIZE; i++) {
1490 if (tentryg->supergroup[i] == PRBADID)
1492 if (tentryg->supergroup[i] == 0)
1496 fprintf(stderr, "via gid=%d, added %d\n", gid,
1497 e.tentryg.supergroup[i]);
1499 code = AddToPRList(alist, sizeP, tentryg->supergroup[i]);
1503 GetListSG2(at, tentryg->supergroup[i], alist, sizeP, depth - 1);
1508 nptr = tentryg->nextsg;
1511 /* look through cont entries */
1512 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1515 for (i = 0; i < COSIZE; i++) {
1516 if (centry.entries[i] == PRBADID)
1518 if (centry.entries[i] == 0)
1521 fprintf(stderr, "via gid=%d, added %d\n", gid,
1522 e.centry.entries[i]);
1524 code = AddToPRList(alist, sizeP, centry.entries[i]);
1527 code = GetListSG2(at, centry.entries[i], alist, sizeP, depth - 1);
1533 IOMGR_Poll(), count = 0;
1536 fprintf(stderr, "] for gid %d, done [flag=%s]\n", gid,
1537 didsomething ? "TRUE" : "FALSE");
1538 if (predictflagged && didsomething != predictfound)
1539 fprintf(stderr, "**** for gid=%d, didsomething=%d predictfound=%d\n",
1540 didsomething, predictfound);
1543 sg_found = add_map(sg_found, -gid);
1545 sg_found = bic_map(sg_found, add_map(NIL_MAP, -gid));
1546 sg_flagged = add_map(sg_flagged, -gid);
1551 GetSGList(struct ubik_trans *at, struct prentry *tentry, prlist *alist)
1553 register afs_int32 code;
1555 struct contentry centry;
1556 struct prentryg *tentryg;
1562 alist->prlist_val = 0;
1563 alist->prlist_len = 0;
1565 tentryg = (struct prentryg *)tentry;
1566 for (i = 0; i < SGSIZE; i++) {
1567 if (tentryg->supergroup[i] == PRBADID)
1569 if (tentryg->supergroup[i] == 0)
1571 code = AddToPRList(alist, &size, tentryg->supergroup[i]);
1576 nptr = tentryg->nextsg;
1578 /* look through cont entries */
1579 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1582 for (i = 0; i < COSIZE; i++) {
1583 if (centry.entries[i] == PRBADID)
1585 if (centry.entries[i] == 0)
1587 code = AddToPRList(alist, &size, centry.entries[i]);
1593 IOMGR_Poll(), count = 0;
1596 if (alist->prlist_len > 100)
1598 qsort((char *)alist->prlist_val, (int)alist->prlist_len,
1599 sizeof(afs_int32), IDCmp);
1602 #endif /* SUPERGROUPS */
1605 GetOwnedChain(struct ubik_trans *ut, afs_int32 *next, prlist *alist)
1608 struct prentry tentry;
1613 alist->prlist_val = 0;
1614 alist->prlist_len = 0;
1616 for (; *next; *next = ntohl(tentry.nextOwned)) {
1617 code = pr_Read(ut, 0, *next, &tentry, sizeof(tentry));
1620 code = AddToPRList(alist, &size, ntohl(tentry.id));
1621 if (alist->prlist_len >= PR_MAXGROUPS) {
1627 IOMGR_Poll(), count = 0;
1629 if (alist->prlist_len > 100)
1631 qsort(alist->prlist_val, alist->prlist_len, sizeof(afs_int32), IDCmp);
1636 GetMax(struct ubik_trans *at, afs_int32 *uid, afs_int32 *gid)
1638 *uid = ntohl(cheader.maxID);
1639 *gid = ntohl(cheader.maxGroup);
1644 SetMax(struct ubik_trans *at, afs_int32 id, afs_int32 flag)
1648 cheader.maxGroup = htonl(id);
1650 pr_Write(at, 0, 16, (char *)&cheader.maxGroup,
1651 sizeof(cheader.maxGroup));
1655 cheader.maxID = htonl(id);
1657 pr_Write(at, 0, 20, (char *)&cheader.maxID,
1658 sizeof(cheader.maxID));
1666 read_DbHeader(struct ubik_trans *tt)
1670 if (!ubik_CacheUpdate(tt))
1673 code = pr_Read(tt, 0, 0, (char *)&cheader, sizeof(cheader));
1675 afs_com_err(whoami, code, "Couldn't read header");
1681 afs_int32 initd = 0;
1687 struct ubik_trans *tt;
1690 /* init the database. We'll try reading it, but if we're starting
1691 * from scratch, we'll have to do a write transaction. */
1693 pr_noAuth = afsconf_GetNoAuthFlag(prdir);
1695 code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
1698 code = ubik_SetLock(tt, 1, 1, LOCKREAD);
1700 ubik_AbortTrans(tt);
1705 } else if (!ubik_CacheUpdate(tt)) {
1706 code = ubik_EndTrans(tt);
1710 len = sizeof(cheader);
1711 code = pr_Read(tt, 0, 0, (char *)&cheader, len);
1713 afs_com_err(whoami, code, "couldn't read header");
1714 ubik_AbortTrans(tt);
1717 if ((ntohl(cheader.version) == PRDBVERSION)
1718 && ntohl(cheader.headerSize) == sizeof(cheader)
1719 && ntohl(cheader.eofPtr) != (afs_uint32) NULL
1720 && FindByID(tt, ANONYMOUSID) != 0) {
1721 /* database exists, so we don't have to build it */
1722 code = ubik_EndTrans(tt);
1727 /* else we need to build a database */
1728 code = ubik_EndTrans(tt);
1732 /* Only rebuild database if the db was deleted (the header is zero) and we
1733 * are running noAuth. */
1735 char *bp = (char *)&cheader;
1737 for (i = 0; i < sizeof(cheader); i++)
1740 afs_com_err(whoami, code,
1741 "Can't rebuild database because it is not empty");
1747 afs_com_err(whoami, code,
1748 "Can't rebuild database because not running NoAuth");
1752 code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
1756 code = ubik_SetLock(tt, 1, 1, LOCKWRITE);
1758 ubik_AbortTrans(tt);
1762 /* before doing a rebuild, check again that the dbase looks bad, because
1763 * the previous check was only under a ReadAny transaction, and there could
1764 * actually have been a good database out there. Now that we have a
1765 * real write transaction, make sure things are still bad.
1767 if ((ntohl(cheader.version) == PRDBVERSION)
1768 && ntohl(cheader.headerSize) == sizeof(cheader)
1769 && ntohl(cheader.eofPtr) != (afs_uint32) NULL
1770 && FindByID(tt, ANONYMOUSID) != 0) {
1771 /* database exists, so we don't have to build it */
1772 code = ubik_EndTrans(tt);
1778 /* Initialize the database header */
1779 if ((code = set_header_word(tt, version, htonl(PRDBVERSION)))
1780 || (code = set_header_word(tt, headerSize, htonl(sizeof(cheader))))
1781 || (code = set_header_word(tt, eofPtr, cheader.headerSize))) {
1782 afs_com_err(whoami, code, "couldn't write header words");
1783 ubik_AbortTrans(tt);
1786 #define InitialGroup(id,name) do { \
1787 afs_int32 temp = (id); \
1788 afs_int32 flag = (id) < 0 ? PRGRP : 0; \
1789 code = CreateEntry \
1790 (tt, (name), &temp, /*idflag*/1, flag, SYSADMINID, SYSADMINID); \
1792 afs_com_err (whoami, code, "couldn't create %s with id %di.", \
1794 ubik_AbortTrans(tt); \
1799 InitialGroup(SYSADMINID, "system:administrators");
1800 InitialGroup(SYSBACKUPID, "system:backup");
1801 InitialGroup(ANYUSERID, "system:anyuser");
1802 InitialGroup(AUTHUSERID, "system:authuser");
1803 InitialGroup(SYSVIEWERID, "system:ptsviewers");
1804 InitialGroup(ANONYMOUSID, "anonymous");
1806 /* Well, we don't really want the max id set to anonymousid, so we'll set
1808 code = set_header_word(tt, maxID, 0); /* correct in any byte order */
1810 afs_com_err(whoami, code, "couldn't reset max id");
1811 ubik_AbortTrans(tt);
1815 code = ubik_EndTrans(tt);
1822 ChangeEntry(struct ubik_trans *at, afs_int32 aid, afs_int32 cid, char *name, afs_int32 oid, afs_int32 newid)
1825 afs_int32 i, nptr, pos;
1826 #if defined(SUPERGROUPS)
1829 struct contentry centry;
1830 struct prentry tentry, tent;
1833 char holder[PR_MAXNAMELEN];
1834 char temp[PR_MAXNAMELEN];
1835 char oldname[PR_MAXNAMELEN];
1838 memset(holder, 0, PR_MAXNAMELEN);
1839 memset(temp, 0, PR_MAXNAMELEN);
1840 loc = FindByID(at, aid);
1843 code = pr_ReadEntry(at, 0, loc, &tentry);
1846 if (restricted && !IsAMemberOf(at, cid, SYSADMINID))
1848 if (tentry.owner != cid && !IsAMemberOf(at, cid, SYSADMINID)
1849 && !IsAMemberOf(at, cid, tentry.owner) && !pr_noAuth)
1851 #ifdef PR_REMEMBER_TIMES
1852 tentry.changeTime = time(0);
1855 /* we're actually trying to change the id */
1856 if (newid && (newid != aid)) {
1857 if (!IsAMemberOf(at, cid, SYSADMINID) && !pr_noAuth)
1860 pos = FindByID(at, newid);
1862 return PRIDEXIST; /* new id already in use! */
1863 if ((aid < 0 && newid > 0) || (aid > 0 && newid < 0))
1866 /* Should check that foreign users id to change to is good: inRange() */
1868 /* if new id is not in use, rehash things */
1869 code = RemoveFromIDHash(at, aid, &loc);
1870 if (code != PRSUCCESS)
1873 code = pr_WriteEntry(at, 0, loc, &tentry);
1876 code = AddToIDHash(at, tentry.id, loc);
1880 /* get current data */
1881 code = pr_ReadEntry(at, 0, loc, &tentry);
1885 #if defined(SUPERGROUPS)
1886 if (tentry.id > (afs_int32) ntohl(cheader.maxID))
1887 code = set_header_word(at, maxID, htonl(tentry.id));
1891 /* need to fix up: membership
1896 for (i = 0; i < PRSIZE; i++) {
1897 if (tentry.entries[i] == PRBADID)
1899 if (tentry.entries[i] == 0)
1901 if ((tentry.flags & PRGRP) && tentry.entries[i] < 0) { /* Supergroup */
1902 return 5; /* not yet, in short. */
1904 code = ChangeIDEntry(at, aid, newid, tentry.entries[i]);
1909 for (pos = ntohl(tentry.owned); pos; pos = nextpos) {
1910 code = pr_ReadEntry(at, 0, pos, &tent);
1914 nextpos = tent.nextOwned;
1915 code = pr_WriteEntry(at, 0, pos, &tent);
1921 #define centry (*(struct contentry*)&tent)
1922 code = pr_ReadCoEntry(at, 0, pos, ¢ry);
1923 if ((centry.id != aid)
1924 || !(centry.flags & PRCONT)) {
1926 "ChangeEntry: bad database aid=%d centry.id=%d .flags=%d\n",
1927 aid, centry.id, centry.flags);
1931 for (i = 0; i < COSIZE; i++) {
1932 if (centry.entries[i] == PRBADID)
1934 if (centry.entries[i] == 0)
1936 if ((centry.flags & PRGRP) && centry.entries[i] < 0) { /* Supergroup */
1937 return 5; /* not yet, in short. */
1939 code = ChangeIDEntry(at, aid, newid, centry.entries[i]);
1944 code = pr_WriteCoEntry(at, 0, pos, ¢ry);
1951 #else /* SUPERGROUPS */
1954 /* Also change the references from the membership list */
1955 for (i = 0; i < PRSIZE; i++) {
1956 if (tentry.entries[i] == PRBADID)
1958 if (tentry.entries[i] == 0)
1960 pos = FindByID(at, tentry.entries[i]);
1963 code = RemoveFromEntry(at, aid, tentry.entries[i]);
1966 code = pr_ReadEntry(at, 0, pos, &tent);
1969 code = AddToEntry(at, &tent, pos, newid);
1973 /* Look through cont entries too. This needs to be broken into
1974 * seperate transaction so that no one transaction becomes too
1975 * large to complete.
1977 for (nptr = tentry.next; nptr; nptr = centry.next) {
1978 code = pr_ReadCoEntry(at, 0, nptr, ¢ry);
1981 for (i = 0; i < COSIZE; i++) {
1982 if (centry.entries[i] == PRBADID)
1984 if (centry.entries[i] == 0)
1986 pos = FindByID(at, centry.entries[i]);
1989 code = RemoveFromEntry(at, aid, centry.entries[i]);
1992 code = pr_ReadEntry(at, 0, pos, &tent);
1995 code = AddToEntry(at, &tent, pos, newid);
2000 #endif /* SUPERGROUPS */
2003 atsign = strchr(tentry.name, '@'); /* check for foreign entry */
2005 /* Change the owner */
2006 if (oid && (oid != tentry.owner)) {
2007 /* only groups can have their owner's changed */
2008 if (!(tentry.flags & PRGRP))
2012 oldowner = tentry.owner;
2014 /* The entry must be written through first so Remove and Add routines
2015 * can operate on disk data */
2016 code = pr_WriteEntry(at, 0, loc, (char *)&tentry);
2020 /* switch owner chains */
2021 if (oldowner) /* if it has an owner */
2022 code = RemoveFromOwnerChain(at, tentry.id, oldowner);
2023 else /* must be an orphan */
2024 code = RemoveFromOrphan(at, tentry.id);
2027 code = AddToOwnerChain(at, tentry.id, tentry.owner);
2031 /* fix up the name */
2032 if (strlen(name) == 0)
2034 /* get current data */
2035 code = pr_ReadEntry(at, 0, loc, &tentry);
2040 /* Change the name, if name is a ptr to tentry.name then this name change
2041 * is due to a chown, otherwise caller has specified a new name */
2042 if ((name == tentry.name) || (*name && (strcmp(tentry.name, name) != 0))) {
2043 strncpy(oldname, tentry.name, PR_MAXNAMELEN);
2044 if (tentry.flags & PRGRP) {
2045 /* don't let foreign cell groups change name */
2048 code = CorrectGroupName(at, name, cid, tentry.owner, tentry.name);
2052 if (name == tentry.name) { /* owner fixup */
2053 if (strcmp(oldname, tentry.name) == 0)
2055 } else { /* new name, caller must be correct */
2056 if (strcmp(name, tentry.name) != 0)
2060 /* Allow a foreign name change only if the cellname part is
2065 newatsign = strchr(name, '@');
2066 if (newatsign != atsign) { /* if they are the same no problem */
2067 /*if the pointers are not equal the strings better be */
2068 if ((atsign == NULL) || (newatsign == NULL)
2069 || strcmp(atsign, newatsign))
2072 if (!CorrectUserName(name))
2076 pos = FindByName(at, name, &tent);
2079 code = RemoveFromNameHash(at, oldname, &loc);
2080 if (code != PRSUCCESS)
2082 strncpy(tentry.name, name, PR_MAXNAMELEN);
2083 code = pr_WriteEntry(at, 0, loc, (char *)&tentry);
2086 code = AddToNameHash(at, tentry.name, loc);
2087 if (code != PRSUCCESS)
2096 allocNextId(struct ubik_trans * at, struct prentry * cellEntry)
2098 /* Id's for foreign cell entries are constructed as follows:
2099 * The 16 low order bits are the group id of the cell and the
2100 * top 16 bits identify the particular users in that cell */
2103 afs_int32 cellid = ((ntohl(cellEntry->id)) & 0x0000ffff);
2105 id = (ntohl(cellEntry->nusers) + 1);
2106 while (FindByID(at, ((id << 16) | cellid))) {
2112 cellEntry->nusers = htonl(id);
2113 /* use the field nusers to keep
2114 * the next available id in that
2115 * foreign cell's group. Note :
2116 * It would seem more appropriate
2117 * to use ngroup for that and nusers
2118 * to enforce the quota, however pts
2119 * does not have an option to change
2120 * foreign users quota yet */
2122 id = (id << 16) | cellid;
2127 inRange(struct prentry *cellEntry, afs_int32 aid)
2129 afs_uint32 id, cellid, groupid;
2133 * The only thing that we want to make sure here is that
2134 * the id is in the legal range of this group. If it is
2135 * a duplicate we don't care since it will get caught
2136 * in a different check.
2139 cellid = aid & 0x0000ffff;
2140 groupid = (ntohl(cellEntry->id)) & 0x0000ffff;
2141 if (cellid != groupid)
2142 return 0; /* not in range */
2145 * if we got here we're ok but we need to update the nusers
2146 * field in order to get the id correct the next time that
2147 * we try to allocate it automatically
2151 if (id > ntohl(cellEntry->nusers))
2152 cellEntry->nusers = htonl(id);
2158 AddAuthGroup(struct prentry *tentry, prlist *alist, afs_int32 *size)
2160 if (!(strchr(tentry->name, '@')))
2161 return (AddToPRList(alist, size, AUTHUSERID));