Coda File System

Re: understanding permissions and changing user id's

From: Jan Harkes <jaharkes_at_cs.cmu.edu>
Date: Fri, 25 May 2001 12:35:07 -0400
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