[PATCH] proposal to unify passwd and group file handling of loginutils

Tito farmatito at tiscali.it
Tue Apr 14 12:42:09 UTC 2009


Hi Denys,
works fine for me. Thanks.

BTW: i've noticed that we don't enforce --system for addgroup
so by adding a user with adduser we get a group with gid >= 1000
by adding a group with addgroup we get a group with gid > 0.
Maybe this is worth to be fixed, I can try to write a patch this evening.

Ciao,
Tito

On Tuesday 14 April 2009 02:55:33 Denys Vlasenko wrote:
> On Thursday 09 April 2009 15:20, Tito wrote:
> > Hi,
> > this series of patches is a first attempt to unify passwd and group file handling 
> > of loginutils applets. The goal of the patch is to avoid that every applet
> > cooks his own soup while scribbling /etc/passwd, /etc/group, /etc/shadow
> > and /etc/gshadow and to enforce "cooperative locking".
> > The patch is based on the existing version of update_password
> > function as it already has some locking and and backup mechanism.
> > This is a first version of the patch series, tested just for the basic stuff
> > and almost size neutral:
> > 
> > debian:~/Desktop/busybox$ scripts/bloat-o-meter ../busybox.orig/busybox_unstripped busybox_unstripped
> > function                                             old     new   delta
> > bb_update_passwd                                       -    1092   +1092
> > parse_and_run_stream                                  54     154    +100
> > .rodata                                           122570  122640     +70
> > o_addstr                                               -      59     +59
> > expand_variables                                    2141    2191     +50
> > handle_dollar                                        632     667     +35
> > lookup_param                                           -      31     +31
> > set_in_charmap                                         -      30     +30
> > o_addstrauto                                           -      27     +27
> > builtin_trap                                         414     438     +24
> > builtin_help                                          63      74     +11
> > bb_perror_nomsg                                        -       9      +9
> > hush_main                                            961     968      +7
> > check_and_run_traps                                  164     169      +5
> > pseudo_exec_argv                                     147     151      +4
> > passwd_main                                         1023    1027      +4
> > chpasswd_main                                        315     319      +4
> > maybe_set_sighandler                                  47      50      +3
> > hush_exit                                             90      93      +3
> > builtin_wait                                         272     275      +3
> > arith                                               1535    1537      +2
> > static.null_ptr                                        4       -      -4
> > run_list                                            2021    2017      -4
> > fbset_main                                          1713    1709      -4
> > adduser_main                                         646     642      -4
> > addgroup_main                                        338     334      -4
> > deluser_main                                         137     132      -5
> > doCommands                                          2533    2522     -11
> > parse_stream                                        1462    1448     -14
> > o_addstr_with_NUL                                     27       -     -27
> > get_local_var_value                                   31       -     -31
> > o_addblock                                            59       -     -59
> > add_user_to_group                                    231       -    -231
> > del_line_matching                                    460      31    -429
> > update_passwd                                        745       -    -745
> > ------------------------------------------------------------------------------
> > (add/remove: 6/6 grow/shrink: 15/8 up/down: 1573/-1572)         Total: 1 bytes
> > 
> > As this is security related stuff i would like the more experienced list members to take
> > a look at it for bugs and other possible improvements.
> > I would also like to know if there is some interest in this patchset 
> > before investing more time in it.
> 
> Thanks!
> 
> Edited a bit (it was apparently complaining aboit missing /etc/[g]shadow,
> which it should not do), and committed the following patch to svn.
> Can you test current svn?
> --
> vda
> 
> 
> diff -d -urpN busybox.0/include/libbb.h busybox.1/include/libbb.h
> --- busybox.0/include/libbb.h	2009-04-14 01:43:05.000000000 +0200
> +++ busybox.1/include/libbb.h	2009-04-14 01:57:06.000000000 +0200
> @@ -1142,9 +1142,16 @@ extern int obscure(const char *old, cons
>   * (otherwise we risk having same salt generated)
>   */
>  extern int crypt_make_salt(char *p, int cnt, int rnd) FAST_FUNC;
> +
>  /* Returns number of lines changed, or -1 on error */
> -extern int update_passwd(const char *filename, const char *username,
> -			const char *new_pw) FAST_FUNC;
> +#if !(ENABLE_FEATURE_ADDUSER_TO_GROUP || ENABLE_FEATURE_DEL_USER_FROM_GROUP)
> +#define update_passwd(filename, username, data, member) \
> +	update_passwd(filename, username, data)
> +#endif
> +extern int update_passwd(const char *filename,
> +		const char *username,
> +		const char *data,
> +		const char *member) FAST_FUNC;
>  
>  int index_in_str_array(const char *const string_array[], const char *key) FAST_FUNC;
>  int index_in_strings(const char *strings, const char *key) FAST_FUNC;
> diff -d -urpN busybox.0/libbb/Kbuild busybox.1/libbb/Kbuild
> --- busybox.0/libbb/Kbuild	2009-04-14 01:43:00.000000000 +0200
> +++ busybox.1/libbb/Kbuild	2009-04-14 01:44:11.000000000 +0200
> @@ -120,6 +120,9 @@ lib-y += xrealloc_vector.o
>  lib-$(CONFIG_FEATURE_MOUNT_LOOP) += loop.o
>  lib-$(CONFIG_LOSETUP) += loop.o
>  lib-$(CONFIG_FEATURE_MTAB_SUPPORT) += mtab.o
> +lib-$(CONFIG_ADDGROUP) += update_passwd.o
> +lib-$(CONFIG_ADDUSER) += update_passwd.o
> +lib-$(CONFIG_DELUSER) += update_passwd.o
>  lib-$(CONFIG_PASSWD) += pw_encrypt.o update_passwd.o
>  lib-$(CONFIG_CHPASSWD) += pw_encrypt.o update_passwd.o
>  lib-$(CONFIG_CRYPTPW) += pw_encrypt.o
> diff -d -urpN busybox.0/libbb/update_passwd.c busybox.1/libbb/update_passwd.c
> --- busybox.0/libbb/update_passwd.c	2009-04-14 01:43:00.000000000 +0200
> +++ busybox.1/libbb/update_passwd.c	2009-04-14 02:49:45.000000000 +0200
> @@ -8,9 +8,11 @@
>   *
>   * Moved from loginutils/passwd.c by Alexander Shishkin <virtuoso at slind.org>
>   *
> + * Modified to be able to add or delete users, groups and users to/from groups
> + * by Tito Ragusa <farmatito at tiscali.it>
> + *
>   * Licensed under GPLv2, see file LICENSE in this tarball for details.
>   */
> -
>  #include "libbb.h"
>  
>  #if ENABLE_SELINUX
> @@ -35,12 +37,44 @@ static void check_selinux_update_passwd(
>  		freecon(context);
>  }
>  #else
> -#define check_selinux_update_passwd(username) ((void)0)
> +# define check_selinux_update_passwd(username) ((void)0)
>  #endif
>  
> -int FAST_FUNC update_passwd(const char *filename, const char *username,
> -			const char *new_pw)
> +/*
> + 1) add a user: update_passwd(FILE, USER, REMAINING_PWLINE, NULL)
> +    only if CONFIG_ADDUSER=y and applet_name[0] == 'a' like in adduser
> +
> + 2) add a group: update_passwd(FILE, GROUP, REMAINING_GRLINE, NULL)
> +    only if CONFIG_ADDGROUP=y and applet_name[0] == 'a' like in addgroup
> +
> + 3) add a user to a group: update_passwd(FILE, GROUP, NULL, MEMBER)
> +    only if CONFIG_FEATURE_ADDUSER_TO_GROUP=y, applet_name[0] == 'a'
> +    like in addgroup and member != NULL
> +
> + 4) delete a user: update_passwd(FILE, USER, NULL, NULL)
> +
> + 5) delete a group: update_passwd(FILE, GROUP, NULL, NULL)
> +
> + 6) delete a user from a group: update_passwd(FILE, GROUP, NULL, MEMBER)
> +    only if CONFIG_FEATURE_DEL_USER_FROM_GROUP=y and member != NULL
> +
> + 7) change user's passord: update_passwd(FILE, USER, NEW_PASSWD, NULL)
> +    only if CONFIG_PASSWD=y and applet_name[0] == 'p' like in passwd
> +    or if CONFIG_CHPASSWD=y and applet_name[0] == 'c' like in chpasswd
> +
> + This function does not validate the arguments fed to it
> + so the calling program should take care of that.
> +
> + Returns number of lines changed, or -1 on error.
> +*/
> +int FAST_FUNC update_passwd(const char *filename,
> +		const char *name,
> +		const char *new_passwd,
> +		const char *member)
>  {
> +#if !(ENABLE_FEATURE_ADDUSER_TO_GROUP || ENABLE_FEATURE_DEL_USER_FROM_GROUP)
> +#define member NULL
> +#endif
>  	struct stat sb;
>  	struct flock lock;
>  	FILE *old_fp;
> @@ -51,22 +85,25 @@ int FAST_FUNC update_passwd(const char *
>  	int old_fd;
>  	int new_fd;
>  	int i;
> -	int cnt = 0;
> +	int changed_lines;
>  	int ret = -1; /* failure */
>  
>  	filename = xmalloc_follow_symlinks(filename);
>  	if (filename == NULL)
> -		return -1;
> +		return ret;
>  
> -	check_selinux_update_passwd(username);
> +	check_selinux_update_passwd(name);
>  
>  	/* New passwd file, "/etc/passwd+" for now */
>  	fnamesfx = xasprintf("%s+", filename);
>  	sfx_char = &fnamesfx[strlen(fnamesfx)-1];
> -	username = xasprintf("%s:", username);
> -	user_len = strlen(username);
> +	name = xasprintf("%s:", name);
> +	user_len = strlen(name);
>  
> -	old_fp = fopen(filename, "r+");
> +	if (strstr(filename, "shadow"))
> +		old_fp = fopen(filename, "r+");
> +	else
> +		old_fp = fopen_or_warn(filename, "r+");
>  	if (!old_fp)
>  		goto free_mem;
>  	old_fd = fileno(old_fp);
> @@ -82,7 +119,7 @@ int FAST_FUNC update_passwd(const char *
>  		if (errno != EEXIST) break;
>  		usleep(100000); /* 0.1 sec */
>  	} while (--i);
> -	bb_perror_msg("cannot create '%s'", fnamesfx);
> +	bb_perror_msg("can't create '%s'", fnamesfx);
>  	goto close_old_fp;
>  
>   created:
> @@ -90,8 +127,10 @@ int FAST_FUNC update_passwd(const char *
>  		fchmod(new_fd, sb.st_mode & 0777); /* ignore errors */
>  		fchown(new_fd, sb.st_uid, sb.st_gid);
>  	}
> +	errno = 0;
>  	new_fp = fdopen(new_fd, "w");
>  	if (!new_fp) {
> +		bb_perror_nomsg();
>  		close(new_fd);
>  		goto unlink_new;
>  	}
> @@ -102,7 +141,8 @@ int FAST_FUNC update_passwd(const char *
>  	i = (unlink(fnamesfx) && errno != ENOENT);
>  	/* Create backup as a hardlink to current */
>  	if (i || link(filename, fnamesfx))
> -		bb_perror_msg("warning: cannot create backup copy '%s'", fnamesfx);
> +		bb_perror_msg("warning: can't create backup copy '%s'",
> +				fnamesfx);
>  	*sfx_char = '+';
>  
>  	/* Lock the password file before updating */
> @@ -111,38 +151,107 @@ int FAST_FUNC update_passwd(const char *
>  	lock.l_start = 0;
>  	lock.l_len = 0;
>  	if (fcntl(old_fd, F_SETLK, &lock) < 0)
> -		bb_perror_msg("warning: cannot lock '%s'", filename);
> +		bb_perror_msg("warning: can't lock '%s'", filename);
>  	lock.l_type = F_UNLCK;
>  
>  	/* Read current password file, write updated /etc/passwd+ */
> +	changed_lines = 0;
>  	while (1) {
> -		char *line = xmalloc_fgets(old_fp);
> -		if (!line) break; /* EOF/error */
> -		if (strncmp(username, line, user_len) == 0) {
> -			/* we have a match with "username:"... */
> -			const char *cp = line + user_len;
> -			/* now cp -> old passwd, skip it: */
> -			cp = strchrnul(cp, ':');
> -			/* now cp -> ':' after old passwd or -> "" */
> -			fprintf(new_fp, "%s%s%s", username, new_pw, cp);
> -			cnt++;
> +		char *cp, *line;
> +
> +		line = xmalloc_fgetline(old_fp);
> +		if (!line) /* EOF/error */
> +			break;
> +		if (strncmp(name, line, user_len) != 0) {
> +			fprintf(new_fp, "%s\n", line);
> +			goto next;
> +		}
> +
> +		/* We have a match with "name:"... */
> +		cp = line + user_len; /* move past name: */
> +
> +#if ENABLE_FEATURE_ADDUSER_TO_GROUP || ENABLE_FEATURE_DEL_USER_FROM_GROUP
> +		if (member) {
> +			/* It's actually /etc/group+, not /etc/passwd+ */
> +			if (ENABLE_FEATURE_ADDUSER_TO_GROUP
> +			 && applet_name[0] == 'a'
> +			) {
> +				/* Add user to group */
> +				fprintf(new_fp, "%s%s%s\n", line,
> +					last_char_is(line, ':') ? "" : ",",
> +					member);
> +				changed_lines++;
> +			} else if (ENABLE_FEATURE_DEL_USER_FROM_GROUP
> +			/* && applet_name[0] == 'd' */
> +			) {
> +				/* Delete user from group */
> +				char *tmp;
> +				const char *fmt = "%s";
> +
> +				/* find the start of the member list: last ':' */
> +				cp = strrchr(line, ':');
> +				/* cut it */
> +				*cp++ = '\0';
> +				/* write the cut line name:passwd:gid:
> +				 * or name:!:: */
> +				fprintf(new_fp, "%s:", line);
> +				/* parse the tokens of the member list */
> +				tmp = cp;
> +				while ((cp = strsep(&tmp, ",")) != NULL) {
> +					if (strcmp(member, cp) != 0) {
> +						fprintf(new_fp, fmt, cp);
> +						fmt = ",%s";
> +					} else {
> +						/* found member, skip it */
> +						changed_lines++;
> +					}
> +				}
> +				fprintf(new_fp, "\n");
> +			}
>  		} else
> -			fputs(line, new_fp);
> +#endif
> +		if ((ENABLE_PASSWD && applet_name[0] == 'p')
> +		 || (ENABLE_CHPASSWD && applet_name[0] == 'c')
> +		) {
> +			/* Change passwd */
> +			cp = strchrnul(cp, ':'); /* move past old passwd */
> +			/* name: + new_passwd + :rest of line */
> +			fprintf(new_fp, "%s%s%s\n", name, new_passwd, cp);
> +			changed_lines++;
> +		} /* else delete user or group: skip the line */
> + next:
>  		free(line);
>  	}
> +
> +	if (changed_lines == 0) {
> +		if (ENABLE_FEATURE_DEL_USER_FROM_GROUP && member)
> +			bb_error_msg("can't find %s in %s", member, filename);
> +		if ((ENABLE_ADDUSER || ENABLE_ADDGROUP)
> +		 && applet_name[0] == 'a' && !member
> +		) {
> +			/* add user or group */
> +			fprintf(new_fp, "%s%s\n", name, new_passwd);
> +			changed_lines++;
> +		}
> +	}
> +
>  	fcntl(old_fd, F_SETLK, &lock);
>  
>  	/* We do want all of them to execute, thus | instead of || */
> +	errno = 0;
>  	if ((ferror(old_fp) | fflush(new_fp) | fsync(new_fd) | fclose(new_fp))
>  	 || rename(fnamesfx, filename)
>  	) {
>  		/* At least one of those failed */
> +		bb_perror_nomsg();
>  		goto unlink_new;
>  	}
> -	ret = cnt; /* whee, success! */
> +	/* Success: ret >= 0 */
> +	ret = changed_lines;
>  
>   unlink_new:
> -	if (ret < 0) unlink(fnamesfx);
> +	if (ret < 0)
> +		unlink(fnamesfx);
>  
>   close_old_fp:
>  	fclose(old_fp);
> @@ -150,6 +259,6 @@ int FAST_FUNC update_passwd(const char *
>   free_mem:
>  	free(fnamesfx);
>  	free((char *)filename);
> -	free((char *)username);
> +	free((char *)name);
>  	return ret;
>  }
> diff -d -urpN busybox.0/loginutils/addgroup.c busybox.1/loginutils/addgroup.c
> --- busybox.0/loginutils/addgroup.c	2009-04-14 01:43:06.000000000 +0200
> +++ busybox.1/loginutils/addgroup.c	2009-04-14 01:54:34.000000000 +0200
> @@ -9,7 +9,6 @@
>   * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
>   *
>   */
> -
>  #include "libbb.h"
>  
>  static void xgroup_study(struct group *g)
> @@ -45,8 +44,8 @@ static void xgroup_study(struct group *g
>  /* append a new user to the passwd file */
>  static void new_group(char *group, gid_t gid)
>  {
> -	FILE *file;
>  	struct group gr;
> +	char *p;
>  
>  	/* make sure gid and group haven't already been allocated */
>  	gr.gr_gid = gid;
> @@ -54,67 +53,17 @@ static void new_group(char *group, gid_t
>  	xgroup_study(&gr);
>  
>  	/* add entry to group */
> -	file = xfopen(bb_path_group_file, "a");
> -	/* group:passwd:gid:userlist */
> -	fprintf(file, "%s:x:%u:\n", group, (unsigned)gr.gr_gid);
> +	p = xasprintf("x:%u:", gr.gr_gid);
> +	if (update_passwd(bb_path_group_file, group, p, NULL) < 0)
> +		exit(EXIT_FAILURE);
>  	if (ENABLE_FEATURE_CLEAN_UP)
> -		fclose(file);
> +		free(p);
>  #if ENABLE_FEATURE_SHADOWPASSWDS
> -	file = fopen_or_warn(bb_path_gshadow_file, "a");
> -	if (file) {
> -		fprintf(file, "%s:!::\n", group);
> -		if (ENABLE_FEATURE_CLEAN_UP)
> -			fclose(file);
> -	}
> +	/* Ignore errors: if file is missing we suppose admin doesn't want it */
> +	update_passwd(bb_path_gshadow_file, group, "!::", NULL);
>  #endif
>  }
>  
> -#if ENABLE_FEATURE_ADDUSER_TO_GROUP
> -static void add_user_to_group(char **args,
> -		const char *path,
> -		FILE* FAST_FUNC (*fopen_func)(const char *fileName, const char *mode))
> -{
> -	char *line;
> -	int len = strlen(args[1]);
> -	llist_t *plist = NULL;
> -	FILE *group_file;
> -
> -	group_file = fopen_func(path, "r");
> -
> -	if (!group_file) return;
> -
> -	while ((line = xmalloc_fgetline(group_file)) != NULL) {
> -		/* Find the group */
> -		if (!strncmp(line, args[1], len)
> -		 && line[len] == ':'
> -		) {
> -			/* Add the new user */
> -			line = xasprintf("%s%s%s", line,
> -						last_char_is(line, ':') ? "" : ",",
> -						args[0]);
> -		}
> -		llist_add_to_end(&plist, line);
> -	}
> -
> -	if (ENABLE_FEATURE_CLEAN_UP) {
> -		fclose(group_file);
> -		group_file = fopen_func(path, "w");
> -		while ((line = llist_pop(&plist))) {
> -			if (group_file)
> -				fprintf(group_file, "%s\n", line);
> -			free(line);
> -		}
> -		if (group_file)
> -			fclose(group_file);
> -	} else {
> -		group_file = fopen_func(path, "w");
> -		if (group_file)
> -			while ((line = llist_pop(&plist)))
> -				fprintf(group_file, "%s\n", line);
> -	}
> -}
> -#endif
> -
>  /*
>   * addgroup will take a login_name as its first parameter.
>   *
> @@ -166,10 +115,12 @@ int addgroup_main(int argc UNUSED_PARAM,
>  				return EXIT_SUCCESS;
>  			}
>  		}
> -		add_user_to_group(argv, bb_path_group_file, xfopen);
> -#if ENABLE_FEATURE_SHADOWPASSWDS
> -		add_user_to_group(argv, bb_path_gshadow_file, fopen_or_warn);
> -#endif
> +		if (update_passwd(bb_path_group_file, argv[1], NULL, argv[0]) < 0) {
> +			return EXIT_FAILURE;
> +		}
> +# if ENABLE_FEATURE_SHADOWPASSWDS
> +		update_passwd(bb_path_gshadow_file, argv[1], NULL, argv[0]);
> +# endif
>  	} else
>  #endif /* ENABLE_FEATURE_ADDUSER_TO_GROUP */
>  	{
> diff -d -urpN busybox.0/loginutils/adduser.c busybox.1/loginutils/adduser.c
> --- busybox.0/loginutils/adduser.c	2009-04-14 01:43:06.000000000 +0200
> +++ busybox.1/loginutils/adduser.c	2009-04-14 01:55:16.000000000 +0200
> @@ -7,14 +7,12 @@
>   *
>   * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
>   */
> -
>  #include "libbb.h"
>  
>  #define OPT_DONT_SET_PASS  (1 << 4)
>  #define OPT_SYSTEM_ACCOUNT (1 << 5)
>  #define OPT_DONT_MAKE_HOME (1 << 6)
>  
> -
>  /* remix */
>  /* recoded such that the uid may be passed in *p */
>  static void passwd_study(struct passwd *p)
> @@ -88,10 +86,7 @@ int adduser_main(int argc UNUSED_PARAM, 
>  {
>  	struct passwd pw;
>  	const char *usegroup = NULL;
> -	FILE *file;
> -#if ENABLE_FEATURE_SHADOWPASSWDS
> -	int fd;
> -#endif
> +	char *p;
>  
>  #if ENABLE_FEATURE_ADDUSER_LONG_OPTIONS
>  	applet_long_options = adduser_longopts;
> @@ -124,32 +119,19 @@ int adduser_main(int argc UNUSED_PARAM, 
>  	/* make sure everything is kosher and setup uid && maybe gid */
>  	passwd_study(&pw);
>  
> -	/* add to passwd */
> -	file = xfopen(bb_path_passwd_file, "a");
> -	//fseek(file, 0, SEEK_END); /* paranoia, "a" should ensure that anyway */
> -	if (putpwent(&pw, file) != 0) {
> -		bb_perror_nomsg_and_die();
> +	p = xasprintf("x:%u:%u:%s:%s:%s", pw.pw_uid, pw.pw_gid, pw.pw_gecos, pw.pw_dir, pw.pw_shell);
> +	if (update_passwd(bb_path_passwd_file, pw.pw_name, p, NULL) < 0) {
> +		return EXIT_FAILURE;
>  	}
> -	/* do fclose even if !ENABLE_FEATURE_CLEAN_UP.
> -	 * We will exec passwd, files must be flushed & closed before that! */
> -	fclose(file);
> +	if (ENABLE_FEATURE_CLEAN_UP)
> +		free(p);
>  
>  #if ENABLE_FEATURE_SHADOWPASSWDS
> -	/* add to shadow if necessary */
> -	/* fopen(..., "a"); would create shadow file, which is wrong.
> -	 * If shadow file doesn't exist, admin probably does not want it */
> -	fd = open_or_warn(bb_path_shadow_file, O_WRONLY | O_APPEND);
> -	if (fd >= 0) {
> -		char *s = xasprintf("%s:!:%u:0:99999:7:::\n",
> -				pw.pw_name,             /* username */
> -				(unsigned)(time(NULL) / 86400) /* sp->sp_lstchg */
> -				/*0,*/                  /* sp->sp_min */
> -				/*99999,*/              /* sp->sp_max */
> -				/*7*/                   /* sp->sp_warn */
> -		);
> -		xwrite_str(fd, s);
> -		close(fd);
> -	}
> +	p = xasprintf("!:%u:0:99999:7:::",  (unsigned)(time(NULL) / 86400)); /* sp->sp_lstchg */
> +	/* Ignore errors: if file is missing we suppose admin doesn't want it */
> +	update_passwd(bb_path_shadow_file, pw.pw_name, p, NULL);
> +	if (ENABLE_FEATURE_CLEAN_UP)
> +		free(p);
>  #endif
>  
>  	/* add to group */
> diff -d -urpN busybox.0/loginutils/chpasswd.c busybox.1/loginutils/chpasswd.c
> --- busybox.0/loginutils/chpasswd.c	2009-04-14 01:43:06.000000000 +0200
> +++ busybox.1/loginutils/chpasswd.c	2009-04-14 01:55:22.000000000 +0200
> @@ -5,7 +5,6 @@
>   * Written for SLIND (from passwd.c) by Alexander Shishkin <virtuoso at slind.org>
>   * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
>   */
> -
>  #include "libbb.h"
>  
>  #if ENABLE_GETOPT_LONG
> @@ -53,10 +52,10 @@ int chpasswd_main(int argc UNUSED_PARAM,
>  		/* This is rather complex: if user is not found in /etc/shadow,
>  		 * we try to find & change his passwd in /etc/passwd */
>  #if ENABLE_FEATURE_SHADOWPASSWDS
> -		rc = update_passwd(bb_path_shadow_file, name, pass);
> +		rc = update_passwd(bb_path_shadow_file, name, pass, NULL);
>  		if (rc == 0) /* no lines updated, no errors detected */
>  #endif
> -			rc = update_passwd(bb_path_passwd_file, name, pass);
> +			rc = update_passwd(bb_path_passwd_file, name, pass, NULL);
>  		/* LOGMODE_BOTH logs to syslog also */
>  		logmode = LOGMODE_BOTH;
>  		if (rc < 0)
> diff -d -urpN busybox.0/loginutils/deluser.c busybox.1/loginutils/deluser.c
> --- busybox.0/loginutils/deluser.c	2009-04-14 01:43:06.000000000 +0200
> +++ busybox.1/loginutils/deluser.c	2009-04-14 02:44:23.000000000 +0200
> @@ -9,117 +9,48 @@
>   * Licensed under GPL version 2, see file LICENSE in this tarball for details.
>   *
>   */
> -
>  #include "libbb.h"
>  
> -/* Status */
> -#define STATUS_OK            0
> -#define NAME_NOT_FOUND       1
> -#define MEMBER_NOT_FOUND     2
> -
> -static void del_line_matching(char **args,
> -		const char *filename,
> -		FILE* FAST_FUNC (*fopen_func)(const char *fileName, const char *mode))
> +static int del_line_matching(char **args, const char *filename)
>  {
> -	FILE *passwd;
> -	smallint error = NAME_NOT_FOUND;
> -	char *name = (ENABLE_FEATURE_DEL_USER_FROM_GROUP && args[2]) ? args[2] : args[1];
> -	char *line, *del;
> -	char *new = xzalloc(1);
> -
> -	passwd = fopen_func(filename, "r");
> -	if (passwd) {
> -		while ((line = xmalloc_fgets(passwd))) {
> -			int len = strlen(name);
> -
> -			if (strncmp(line, name, len) == 0
> -			 && line[len] == ':'
> -			) {
> -				error = STATUS_OK;
> -				if (ENABLE_FEATURE_DEL_USER_FROM_GROUP) {
> -					struct group *gr;
> -					char *p;
> -					if (args[2]
> -					 /* There were two args on commandline */
> -					 && (gr = getgrnam(name))
> -					 /* The group was not deleted in the meanwhile */
> -					 && (p = strrchr(line, ':'))
> -					 /* We can find a pointer to the last ':' */
> -					) {
> -						error = MEMBER_NOT_FOUND;
> -						/* Move past ':' (worst case to '\0') and cut the line */
> -						p[1] = '\0';
> -						/* Reuse p */
> -						for (p = xzalloc(1); *gr->gr_mem != NULL; gr->gr_mem++) {
> -							/* Add all the other group members */
> -							if (strcmp(args[1], *gr->gr_mem) != 0) {
> -								del = p;
> -								p = xasprintf("%s%s%s", p, p[0] ? "," : "", *gr->gr_mem);
> -								free(del);
> -							} else
> -								error = STATUS_OK;
> -						}
> -						/* Recompose the line */
> -						line = xasprintf("%s%s\n", line, p);
> -						if (ENABLE_FEATURE_CLEAN_UP) free(p);
> -					} else
> -						goto skip;
> -				}
> -			}
> -			del = new;
> -			new = xasprintf("%s%s", new, line);
> -			free(del);
> - skip:
> -			free(line);
> -		}
> -
> -		if (ENABLE_FEATURE_CLEAN_UP) fclose(passwd);
> -
> -		if (error) {
> -			if (ENABLE_FEATURE_DEL_USER_FROM_GROUP && error == MEMBER_NOT_FOUND) {
> -				/* Set the correct values for error message */
> -				filename = name;
> -				name = args[1];
> -			}
> -			bb_error_msg("can't find %s in %s", name, filename);
> -		} else {
> -			passwd = fopen_func(filename, "w");
> -			if (passwd) {
> -				fputs(new, passwd);
> -				if (ENABLE_FEATURE_CLEAN_UP) fclose(passwd);
> -			}
> -		}
> +	if (ENABLE_FEATURE_DEL_USER_FROM_GROUP && args[2]) {
> +		return update_passwd(filename, args[2], NULL, args[1]);
>  	}
> -	free(new);
> +	return update_passwd(filename, args[1], NULL, NULL);
>  }
>  
>  int deluser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
>  int deluser_main(int argc, char **argv)
>  {
> -	if (argc == 2
> -	 || (ENABLE_FEATURE_DEL_USER_FROM_GROUP
> -	    && (applet_name[3] == 'g' && argc == 3))
> +	if (argc != 2
> +	 && (!ENABLE_FEATURE_DEL_USER_FROM_GROUP
> +	    || (applet_name[3] != 'g' || argc != 3))
>  	) {
> -		if (geteuid())
> -			bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
> +		bb_show_usage();
> +	}
>  
> -		if ((ENABLE_FEATURE_DEL_USER_FROM_GROUP && argc != 3)
> -		 || ENABLE_DELUSER
> -		 || (ENABLE_DELGROUP && ENABLE_DESKTOP)
> +	if (geteuid())
> +		bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
> +
> +	if ((ENABLE_FEATURE_DEL_USER_FROM_GROUP && argc != 3)
> +	 || ENABLE_DELUSER
> +	 || (ENABLE_DELGROUP && ENABLE_DESKTOP)
> +	) {
> +		if (ENABLE_DELUSER
> +		 && (!ENABLE_DELGROUP || applet_name[3] == 'u')
>  		) {
> -			if (ENABLE_DELUSER
> -			 && (!ENABLE_DELGROUP || applet_name[3] == 'u')
> -			) {
> -				del_line_matching(argv, bb_path_passwd_file, xfopen);
> -				if (ENABLE_FEATURE_SHADOWPASSWDS)
> -					del_line_matching(argv, bb_path_shadow_file, fopen_or_warn);
> -			} else if (ENABLE_DESKTOP && ENABLE_DELGROUP && getpwnam(argv[1]))
> -				bb_error_msg_and_die("can't remove primary group of user %s", argv[1]);
> -		}
> -		del_line_matching(argv, bb_path_group_file, xfopen);
> -		if (ENABLE_FEATURE_SHADOWPASSWDS)
> -			del_line_matching(argv, bb_path_gshadow_file, fopen_or_warn);
> -		return EXIT_SUCCESS;
> -	} else
> -		bb_show_usage();
> +			if (del_line_matching(argv, bb_path_passwd_file) < 0)
> +				return EXIT_FAILURE;
> +			if (ENABLE_FEATURE_SHADOWPASSWDS) {
> +				del_line_matching(argv, bb_path_shadow_file);
> +			}
> +		} else if (ENABLE_DESKTOP && ENABLE_DELGROUP && getpwnam(argv[1]))
> +			bb_error_msg_and_die("can't remove primary group of user %s", argv[1]);
> +	}
> +	if (del_line_matching(argv, bb_path_group_file) < 0)
> +		return EXIT_FAILURE;
> +	if (ENABLE_FEATURE_SHADOWPASSWDS) {
> +		del_line_matching(argv, bb_path_gshadow_file);
> +	}
> +	return EXIT_SUCCESS;
>  }
> diff -d -urpN busybox.0/loginutils/passwd.c busybox.1/loginutils/passwd.c
> --- busybox.0/loginutils/passwd.c	2009-04-14 01:43:06.000000000 +0200
> +++ busybox.1/loginutils/passwd.c	2009-04-14 01:55:07.000000000 +0200
> @@ -2,7 +2,6 @@
>  /*
>   * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
>   */
> -
>  #include "libbb.h"
>  #include <syslog.h>
>  
> @@ -181,12 +180,12 @@ int passwd_main(int argc UNUSED_PARAM, c
>  
>  #if ENABLE_FEATURE_SHADOWPASSWDS
>  	filename = bb_path_shadow_file;
> -	rc = update_passwd(bb_path_shadow_file, name, newp);
> +	rc = update_passwd(bb_path_shadow_file, name, newp, NULL);
>  	if (rc == 0) /* no lines updated, no errors detected */
>  #endif
>  	{
>  		filename = bb_path_passwd_file;
> -		rc = update_passwd(bb_path_passwd_file, name, newp);
> +		rc = update_passwd(bb_path_passwd_file, name, newp, NULL);
>  	}
>  	/* LOGMODE_BOTH */
>  	if (rc < 0)
> 
> 
> 




More information about the busybox mailing list