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?

 - 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);

Reply via email to