(Illustration by Gaich Muramatsu)
On Fri, May 25, 2001 at 07:46:24AM -0400, Jan Harkes wrote: > > Also, I'm trying to change the user id for the administrative user in > > pdbtool, but not all references to that id are changed. I want to free > > up that id so I can match my current system user ids for consistency > > across the system. If I change the id and do a 'list', the > > System:Administrators owner id still shows the old value and now I can't > > do anything as the coda admin until I change it back. Same with any > > groups that are owned by the user whose id I'm trying to change. Is > > this a bug in pdbtool? > > I guess the pdbtools isn't exhaustive enough in hunting down all id's > that need to be renumbered. It will work when the changing userid is > only a member of a group, so yes, this is a bug. I'll look into it. I found several bugs in the implementation of 'pdbtool ci' that result in inconsistencies in the pdb databases. - Group owner id wasn't updated. - Traversal of the groups_or_members array was broken. As a result users who's uid changed and that were a member of a group, are not listed as group members in the group information. - Member of information was updated in such a way that a group would be listed as a member of a user (shouldn't be possible). I just committed a version into CVS that fixes these bugs and also has added the functionality to 'pdbtool cm' to fix inconsistencies that occur as a result of these bugs (same patch follows here). Jan Index: pdb.c =================================================================== RCS file: /afs/cs/project/coda-src/cvs/coda/coda-src/al/pdb.c,v retrieving revision 1.9 retrieving revision 1.10 diff -u -u -r1.9 -r1.10 --- pdb.c 1999/09/14 19:00:40 1.9 +++ pdb.c 2001/05/25 16:29:57 1.10 @@ -425,6 +425,99 @@ } +void PDB_bugfixes(void) +{ + PDB_HANDLE h; + /* fixups for old bugs */ + int32_t id, id2; + pdb_array_off off, off2; + int rc; + PDB_profile p, r; + + h = PDB_db_open(O_RDWR); + + while ( (rc = PDB_db_nextkey(h, &id)) ) { + if ( rc == -1 ) continue; + PDB_readProfile(h, id, &p); + + if (PDB_ISGROUP(p.id)) { + /* BUG: forgot to update owner_id when changing a user's uid */ + PDB_lookupByName(p.owner_name, &id); + if (p.owner_id != id) { + fprintf(stderr, "Group %d owner name %s didn't match owner id %d, FIXED\n", p.id, p.owner_name, p.owner_id); + p.owner_id = id; + PDB_writeProfile(h, &p); + } + + /* BUG: we added userid's to a group's member_of list */ +again: + id = pdb_array_head(&p.member_of, &off); + while(id != 0) { + if (PDB_ISUSER(id)) { + fprintf(stderr, "Group %d was listed as a member of userid %d, FIXED\n", p.id, id); + pdb_array_del(&p.member_of, id); + PDB_updateCps(h, &p); + PDB_writeProfile(h, &p); + goto again; + } + id = pdb_array_next(&p.member_of, &off); + } + + /* BUG: we forgot to change userid's in a group's groups_or_members + * list (fix part 1, removes non-existing or non-member + * userids) */ +again2: + id = pdb_array_head(&p.groups_or_members, &off); + while(id != 0) { + if (PDB_ISUSER(id)) { + PDB_readProfile(h, id, &r); + id2 = pdb_array_head(&r.member_of, &off2); + while (id2 != 0) { + if (id2 == p.id) break; + id2 = pdb_array_next(&r.member_of, &off2); + } + if (id2 == 0) { + pdb_array_del(&p.groups_or_members, id); + PDB_updateCps(h, &p); + PDB_writeProfile(h, &p); + fprintf(stderr, "Group %d had nonexisting member %d, FIXED\n", p.id, id); + PDB_freeProfile(&r); + goto again2; + } + PDB_freeProfile(&r); + } + id = pdb_array_next(&p.groups_or_members, &off); + } + } + else /* PDB_ISUSER(p.id) */ + { + /* BUG: we forgot to change userid's in a group's groups_or_members + * list (fix part 2, adds missing members to groups)*/ + id = pdb_array_head(&p.member_of, &off); + while (id != 0) { + if (PDB_ISGROUP(id)) { + PDB_readProfile(h, id, &r); + id2 = pdb_array_head(&r.groups_or_members, &off2); + while (id2 != 0) { + if (id2 == p.id) break; + id2 = pdb_array_next(&r.groups_or_members, &off2); + } + if (id2 == 0) { + fprintf(stderr, "Group %d was missing member %d, FIXED\n", id, p.id); + pdb_array_add(&r.groups_or_members, p.id); + PDB_updateCps(h, &r); + PDB_writeProfile(h, &r); + } + PDB_freeProfile(&r); + } + id = pdb_array_next(&p.member_of, &off); + } + } + PDB_freeProfile(&p); + } + PDB_db_close(h); +} + void PDB_changeId(int32_t oldId, int32_t newId) { PDB_HANDLE h; @@ -466,35 +559,44 @@ else PDB_db_update_maxids(h, newId, 0, PDB_MAXID_SET); - /* update groups is member of */ + /* update groups we are a member of */ nextid = pdb_array_head(&(r.member_of), &off); while(nextid != 0){ PDB_readProfile(h, nextid, &p); CODA_ASSERT(p.id != 0); pdb_array_del(&(p.groups_or_members), oldId); pdb_array_add(&(p.groups_or_members), newId); + /* Don't need CPS updates */ PDB_writeProfile(h, &p); PDB_freeProfile(&p); - nextid = pdb_array_next(&(r.groups_or_members), &off); + nextid = pdb_array_next(&(r.member_of), &off); } - /* update members */ + /* update members or ownership */ nextid = pdb_array_head(&(r.groups_or_members), &off); - while(nextid != 0){ - PDB_readProfile(h, nextid, &p); - CODA_ASSERT(p.id != 0); + while(nextid != 0) { + PDB_readProfile(h, nextid, &p); + CODA_ASSERT(p.id != 0); + + if (PDB_ISGROUP(oldId)) { pdb_array_del(&(p.member_of), oldId); pdb_array_add(&(p.member_of), newId); - if(PDB_ISGROUP(oldId)){ - if(PDB_ISGROUP(p.id)) - PDB_updateCps(h, &p); - else - PDB_updateCpsSelf(h, &p); + } else { + if (PDB_ISGROUP(p.id)) { + if(p.owner_id == oldId) + p.owner_id = newId; } - PDB_writeProfile(h, &p); - PDB_freeProfile(&p); - nextid = pdb_array_next(&(r.groups_or_members), &off); + } + + if(PDB_ISGROUP(p.id)) + PDB_updateCps(h, &p); + else + PDB_updateCpsSelf(h, &p); + + PDB_writeProfile(h, &p); + PDB_freeProfile(&p); + nextid = pdb_array_next(&(r.groups_or_members), &off); } PDB_db_close(h); Index: pdb.h =================================================================== RCS file: /afs/cs/project/coda-src/cvs/coda/coda-src/al/pdb.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -u -r1.2 -r1.3 --- pdb.h 1999/05/07 04:04:19 1.2 +++ pdb.h 2001/05/25 16:29:57 1.3 @@ -70,6 +70,9 @@ int PDB_nameInUse(char *name); void PDB_changeId(int32_t oldid, int32_t newid); +/* fix known problems in PDB profiles created by older versions of pdbtool */ +void PDB_bugfixes(void); + /* internal packing functions */ void pdb_pack(PDB_profile *r, void **data, size_t *size); void pdb_unpack(PDB_profile *r, void *data, size_t size); Index: pdbtool.c =================================================================== RCS file: /afs/cs/project/coda-src/cvs/coda/coda-src/al/pdbtool.c,v retrieving revision 1.13 retrieving revision 1.14 diff -u -u -r1.13 -r1.14 --- pdbtool.c 2001/01/19 12:58:02 1.13 +++ pdbtool.c 2001/05/25 16:29:57 1.14 @@ -362,12 +362,17 @@ } /* COMPACT DATABASES */ -void tool_compact(int argc,char *argv[]){ +void tool_compact(int argc,char *argv[]) +{ PDB_HANDLE h; + if(check_args_num(argc,1)){ printf("Usage: cm\n"); return; } + /* fix database consistency bugs */ + PDB_bugfixes(); + h = PDB_db_open(O_RDWR); PDB_db_compact(h); PDB_db_close(h); @@ -757,7 +762,7 @@ printf("cu <newusername> <userid>\tclone a user\n"); printf("ag <groupid/name> <id/name>\tadd a group or user to a group\n"); printf("rg <groupid/name> <id/name>\tremove a group or user from a group\n"); - printf("d <id/name>\t\t\t\tdelete a user or a group\n"); + printf("d <id/name>\t\t\tdelete a user or a group\n"); printf("cm\t\t\t\tcompact the database (RARE)\n"); printf("ci <name> <newid>\t\tchange the Id of a user or group\n"); printf("cn <id> <newname>\t\tchange the Name of a user or group\n");Received on 2001-05-25 12:35:15