(oops i hit send too early)
the attached patch should fix it for you.

fixes a bug in xuserset which makes it go into an infinite loop.
the user entries are read from the pwd database and stored in a local
structure.

Signed-off-by: Abhishek Kulkarni <[EMAIL PROTECTED]>

On Mon, 2008-11-24 at 15:49 -0500, Daniel Gruner wrote:
> The latest version in the repository (734) has a bug in xuserset when used as:
> 
> xuserset add -a -u
> 
> where it goes into an infinite loop repeating this:
> 
> xp_user_add: n0000: Error 5: root:user exists
> xp_user_add: n0001: Error 5: root:user exists
> xp_user_add: n0000: Error 5: root:user exists
> xp_user_add: n0001: Error 5: root:user exists
> 
> This had happened before, and was fixed then...
> 
> This is from the Nov 3 thread:
> 
> arrgh, it works fine on my home machine too..
> but i think i have caught the bug. so getpwent() should loop over the
> passwd database (contents of /etc/passwd) but in xp_user_add, there's
> again a call to getpwnam() which could possibly reset the passwd database
> and getpwent() again returns "root" entry in the next iteration.
> this is not triggered for all libc versions and the one included in
> RHEL5.2 seems to break it open badly. I run most of my tests on
> Ubuntu/Fedora which I have started to believe is a bad choice to test this
> stuff.
> 
> 
> Daniel
Index: utils/xuserset.c
===================================================================
--- utils/xuserset.c	(revision 734)
+++ utils/xuserset.c	(working copy)
@@ -105,6 +105,13 @@
 	int allflag = 0, passwdfile = 0;
 	struct passwd *pw;
 	struct group *gr;
+	struct pwent {
+		char *pw_name;
+		uid_t pw_uid;
+		gid_t pw_gid;
+		char *pw_key;
+		struct pwent *next;
+	} *users, *head;
 
 	while((c = getopt(argc, argv, "aA:dhup")) != -1) {
 		switch(c) {
@@ -197,22 +204,31 @@
 	} else if (!strcmp("add", cmd)) {
 		if (passwdfile) {
 			setpwent();
+			head = NULL;
 			while ((pw = getpwent()) != NULL) {
 				snprintf(ukeypath, sizeof(ukeypath), "%s/.ssh/id_rsa.pub", pw->pw_dir);
-				if (get_user_key(ukeypath, userkey, sizeof(userkey)) < 0) {
-					sp_suerror("get_user_key", errno);
-					continue;
+				if (!access(ukeypath, R_OK)) {
+					users = (struct pwent *)malloc(sizeof(struct pwent));
+					users->pw_name = strdup(pw->pw_name);
+					users->pw_uid = pw->pw_uid;
+					users->pw_gid = pw->pw_gid;					
+					users->pw_key = strdup(ukeypath);
+					users->next = head;
+					head = users;
 				}
-				
-				if ((gr = getgrgid(pw->pw_gid)) == NULL) {
-					sp_suerror("get_user_key", errno);
+			}
+			endpwent();
+
+			for(; users; users = users->next) {
+				if (get_user_key(users->pw_key, userkey, sizeof(userkey)) < 0)
 					continue;
-				}
-				
-				xp_user_add(nds, adminkey, pw->pw_name, pw->pw_uid,
+			
+				if ((gr = getgrgid(users->pw_gid)) == NULL)
+					continue;
+			
+				xp_user_add(nds, adminkey, users->pw_name, users->pw_uid,
 					    gr->gr_name, userkey);
 			}
-			endpwent();
 		} else {
 			if ((argc - optind) < 4)
 				usage(argv[0]);

Reply via email to