On 5/19/23 12:24, Todd C. Miller wrote:
> If /etc/usermgmt.conf has a line like:
>
> group =uid
>
> where a new user's group ID in the passwd file is the same as their
> user ID, remove that group when the user is removed. The group is
> only removed if it matches the login name, has a gid that matches
> the user's uid, and has no other members.
>
> This makes our userdel(8) behave more like the version on other
> systems.
>
> Opinions? This is something that has always bothered me and can
> result in uid/gid mismatches if you remove a user, then re-add them
> without removing the login group first.
>
> Thoughts or strong opinions?
Will this not potentially break people's setups? I like this change though.
This would also make the post pkg_delete output simpler by just asking
the admin to delete the user, instead of both user and group.
>
> - todd
>
> Index: usr.sbin/user/user.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/user/user.c,v
> retrieving revision 1.131
> diff -u -p -u -r1.131 user.c
> --- usr.sbin/user/user.c 18 May 2023 18:29:28 -0000 1.131
> +++ usr.sbin/user/user.c 19 May 2023 16:16:02 -0000
> @@ -193,7 +193,7 @@ static int is_local(char *, const char *
> static int modify_gid(char *, char *);
> static int moduser(char *, char *, user_t *);
> static int removehomedir(const char *, uid_t, const char *);
> -static int rm_user_from_groups(char *);
> +static int rm_user_from_groups(char *, int);
> static int save_range(user_t *, char *);
> static int scantime(time_t *, char *);
> static int setdefaults(user_t *);
> @@ -1308,9 +1308,9 @@ adduser(char *login_name, user_t *up)
> return 1;
> }
>
> -/* remove a user from the groups file */
> +/* remove a user from the groups file, optionally removing the login group */
> static int
> -rm_user_from_groups(char *login_name)
> +rm_user_from_groups(char *login_name, int rm_login_group)
> {
> struct stat st;
> size_t login_len;
> @@ -1366,6 +1366,15 @@ rm_user_from_groups(char *login_name)
> warnx("Malformed entry `%s'. Skipping", buf);
> continue;
> }
> + if (rm_login_group && strncmp(buf, login_name, login_len) == 0
> + && buf[login_len] == ':') {
> + /* remove login group if empty or user is only member */
> + if (*cp == '\n')
> + continue;
> + if (strncmp(cp, login_name, login_len) == 0 &&
> + cp [login_len] == '\n')
> + continue;
> + }
> while ((cp = strstr(cp, login_name)) != NULL) {
> if ((cp[-1] == ':' || cp[-1] == ',') &&
> (cp[login_len] == ',' || cp[login_len] == '\n')) {
> @@ -1745,7 +1754,7 @@ moduser(char *login_name, char *newlogin
> up->u_groupv[i]);
> }
> }
> - if (!rm_user_from_groups(newlogin)) {
> + if (!rm_user_from_groups(newlogin, 0)) {
> close(ptmpfd);
> pw_abort();
> errx(EXIT_FAILURE,
> @@ -2101,8 +2110,10 @@ int
> userdel(int argc, char **argv)
> {
> struct passwd *pwp;
> + struct group *grp;
> user_t u;
> int defaultfield;
> + int rm_login_group;
> int rmhome;
> int bigD;
> int c;
> @@ -2164,7 +2175,15 @@ userdel(int argc, char **argv)
> openlog("userdel", LOG_PID, LOG_USER);
> return moduser(*argv, *argv, &u) ? EXIT_SUCCESS : EXIT_FAILURE;
> }
> - if (!rm_user_from_groups(*argv)) {
> + rm_login_group = 0;
> + if (strcmp(u.u_primgrp, "=uid") == 0 && pwp->pw_uid == pwp->pw_gid) {
> + /* remove primary group if it matches the username */
> + grp = getgrgid(pwp->pw_gid);
> + if (grp != NULL && strcmp(grp->gr_name, *argv) == 0) {
> + rm_login_group = 1;
> + }
> + }
> + if (!rm_user_from_groups(*argv, rm_login_group)) {
> return 0;
> }
> openlog("userdel", LOG_PID, LOG_USER);
>