[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