b8f1b8
From e481437ab9ebe9a8bf8fbaabe986d42b2f765991 Mon Sep 17 00:00:00 2001
b8f1b8
From: Iker Pedrosa <ipedrosa@redhat.com>
b8f1b8
Date: Tue, 3 Aug 2021 08:57:20 +0200
b8f1b8
Subject: [PATCH] usermod: allow all group types with -G option
b8f1b8
b8f1b8
The only way of removing a group from the supplementary list is to use
b8f1b8
-G option, and list all groups that the user is a member of except for
b8f1b8
the one that wants to be removed. The problem lies when there's a user
b8f1b8
that contains both local and remote groups, and the group to be removed
b8f1b8
is a local one. As we need to include the remote group with -G option
b8f1b8
the command will fail.
b8f1b8
b8f1b8
This reverts commit 140510de9de4771feb3af1d859c09604043a4c9b. This way,
b8f1b8
it would be possible to remove the remote groups from the supplementary
b8f1b8
list.
b8f1b8
b8f1b8
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1967641
b8f1b8
Resolves: https://github.com/shadow-maint/shadow/issues/338
b8f1b8
b8f1b8
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
b8f1b8
---
b8f1b8
 src/usermod.c | 220 ++++++++++++++++++--------------------------------
b8f1b8
 1 file changed, 77 insertions(+), 143 deletions(-)
b8f1b8
b8f1b8
diff --git a/src/usermod.c b/src/usermod.c
b8f1b8
index 03bb9b9d..a0c03afa 100644
b8f1b8
--- a/src/usermod.c
b8f1b8
+++ b/src/usermod.c
b8f1b8
@@ -187,7 +187,6 @@ static bool sub_gid_locked = false;
b8f1b8
 static void date_to_str (/*@unique@*//*@out@*/char *buf, size_t maxsize,
b8f1b8
                          long int date);
b8f1b8
 static int get_groups (char *);
b8f1b8
-static struct group * get_local_group (char * grp_name);
b8f1b8
 static /*@noreturn@*/void usage (int status);
b8f1b8
 static void new_pwent (struct passwd *);
b8f1b8
 static void new_spent (struct spwd *);
b8f1b8
@@ -201,9 +200,7 @@ static void grp_update (void);
b8f1b8
 
b8f1b8
 static void process_flags (int, char **);
b8f1b8
 static void close_files (void);
b8f1b8
-static void close_group_files (void);
b8f1b8
 static void open_files (void);
b8f1b8
-static void open_group_files (void);
b8f1b8
 static void usr_update (void);
b8f1b8
 static void move_home (void);
b8f1b8
 static void update_lastlog (void);
b8f1b8
@@ -260,11 +257,6 @@ static int get_groups (char *list)
b8f1b8
 		return 0;
b8f1b8
 	}
b8f1b8
 
b8f1b8
-	/*
b8f1b8
-	 * Open the group files
b8f1b8
-	 */
b8f1b8
-	open_group_files ();
b8f1b8
-
b8f1b8
 	/*
b8f1b8
 	 * So long as there is some data to be converted, strip off each
b8f1b8
 	 * name and look it up. A mix of numerical and string values for
b8f1b8
@@ -284,7 +276,7 @@ static int get_groups (char *list)
b8f1b8
 		 * Names starting with digits are treated as numerical GID
b8f1b8
 		 * values, otherwise the string is looked up as is.
b8f1b8
 		 */
b8f1b8
-		grp = get_local_group (list);
b8f1b8
+		grp = prefix_getgr_nam_gid (list);
b8f1b8
 
b8f1b8
 		/*
b8f1b8
 		 * There must be a match, either by GID value or by
b8f1b8
@@ -334,8 +326,6 @@ static int get_groups (char *list)
b8f1b8
 		gr_free ((struct group *)grp);
b8f1b8
 	} while (NULL != list);
b8f1b8
 
b8f1b8
-	close_group_files ();
b8f1b8
-
b8f1b8
 	user_groups[ngroups] = (char *) 0;
b8f1b8
 
b8f1b8
 	/*
b8f1b8
@@ -348,44 +338,6 @@ static int get_groups (char *list)
b8f1b8
 	return 0;
b8f1b8
 }
b8f1b8
 
b8f1b8
-/*
b8f1b8
- * get_local_group - checks if a given group name exists locally
b8f1b8
- *
b8f1b8
- *	get_local_group() checks if a given group name exists locally.
b8f1b8
- *	If the name exists the group information is returned, otherwise NULL is
b8f1b8
- *	returned.
b8f1b8
- */
b8f1b8
-static struct group * get_local_group(char * grp_name)
b8f1b8
-{
b8f1b8
-	const struct group *grp;
b8f1b8
-	struct group *result_grp = NULL;
b8f1b8
-	long long int gid;
b8f1b8
-	char *endptr;
b8f1b8
-
b8f1b8
-	gid = strtoll (grp_name, &endptr, 10);
b8f1b8
-	if (   ('\0' != *grp_name)
b8f1b8
-		&& ('\0' == *endptr)
b8f1b8
-		&& (ERANGE != errno)
b8f1b8
-		&& (gid == (gid_t)gid)) {
b8f1b8
-		grp = gr_locate_gid ((gid_t) gid);
b8f1b8
-	}
b8f1b8
-	else {
b8f1b8
-		grp = gr_locate(grp_name);
b8f1b8
-	}
b8f1b8
-
b8f1b8
-	if (grp != NULL) {
b8f1b8
-		result_grp = __gr_dup (grp);
b8f1b8
-		if (NULL == result_grp) {
b8f1b8
-			fprintf (stderr,
b8f1b8
-					_("%s: Out of memory. Cannot find group '%s'.\n"),
b8f1b8
-					Prog, grp_name);
b8f1b8
-			fail_exit (E_GRP_UPDATE);
b8f1b8
-		}
b8f1b8
-	}
b8f1b8
-
b8f1b8
-	return result_grp;
b8f1b8
-}
b8f1b8
-
b8f1b8
 #ifdef ENABLE_SUBIDS
b8f1b8
 struct ulong_range
b8f1b8
 {
b8f1b8
@@ -1523,7 +1475,50 @@ static void close_files (void)
b8f1b8
 	}
b8f1b8
 
b8f1b8
 	if (Gflg || lflg) {
b8f1b8
-		close_group_files ();
b8f1b8
+		if (gr_close () == 0) {
b8f1b8
+			fprintf (stderr,
b8f1b8
+			         _("%s: failure while writing changes to %s\n"),
b8f1b8
+			         Prog, gr_dbname ());
b8f1b8
+			SYSLOG ((LOG_ERR,
b8f1b8
+			         "failure while writing changes to %s",
b8f1b8
+			         gr_dbname ()));
b8f1b8
+			fail_exit (E_GRP_UPDATE);
b8f1b8
+		}
b8f1b8
+#ifdef SHADOWGRP
b8f1b8
+		if (is_shadow_grp) {
b8f1b8
+			if (sgr_close () == 0) {
b8f1b8
+				fprintf (stderr,
b8f1b8
+				         _("%s: failure while writing changes to %s\n"),
b8f1b8
+				         Prog, sgr_dbname ());
b8f1b8
+				SYSLOG ((LOG_ERR,
b8f1b8
+				         "failure while writing changes to %s",
b8f1b8
+				         sgr_dbname ()));
b8f1b8
+				fail_exit (E_GRP_UPDATE);
b8f1b8
+			}
b8f1b8
+		}
b8f1b8
+#endif
b8f1b8
+#ifdef SHADOWGRP
b8f1b8
+		if (is_shadow_grp) {
b8f1b8
+			if (sgr_unlock () == 0) {
b8f1b8
+				fprintf (stderr,
b8f1b8
+				         _("%s: failed to unlock %s\n"),
b8f1b8
+				         Prog, sgr_dbname ());
b8f1b8
+				SYSLOG ((LOG_ERR,
b8f1b8
+				         "failed to unlock %s",
b8f1b8
+				         sgr_dbname ()));
b8f1b8
+				/* continue */
b8f1b8
+			}
b8f1b8
+		}
b8f1b8
+#endif
b8f1b8
+		if (gr_unlock () == 0) {
b8f1b8
+			fprintf (stderr,
b8f1b8
+			         _("%s: failed to unlock %s\n"),
b8f1b8
+			         Prog, gr_dbname ());
b8f1b8
+			SYSLOG ((LOG_ERR,
b8f1b8
+			         "failed to unlock %s",
b8f1b8
+			         gr_dbname ()));
b8f1b8
+			/* continue */
b8f1b8
+		}
b8f1b8
 	}
b8f1b8
 
b8f1b8
 	if (is_shadow_pwd) {
b8f1b8
@@ -1592,60 +1587,6 @@ static void close_files (void)
b8f1b8
 #endif
b8f1b8
 }
b8f1b8
 
b8f1b8
-/*
b8f1b8
- * close_group_files - close all of the files that were opened
b8f1b8
- *
b8f1b8
- *	close_group_files() closes all of the files that were opened related
b8f1b8
- *  with groups. This causes any modified entries to be written out.
b8f1b8
- */
b8f1b8
-static void close_group_files (void)
b8f1b8
-{
b8f1b8
-	if (gr_close () == 0) {
b8f1b8
-		fprintf (stderr,
b8f1b8
-					_("%s: failure while writing changes to %s\n"),
b8f1b8
-					Prog, gr_dbname ());
b8f1b8
-		SYSLOG ((LOG_ERR,
b8f1b8
-					"failure while writing changes to %s",
b8f1b8
-					gr_dbname ()));
b8f1b8
-		fail_exit (E_GRP_UPDATE);
b8f1b8
-	}
b8f1b8
-#ifdef SHADOWGRP
b8f1b8
-	if (is_shadow_grp) {
b8f1b8
-		if (sgr_close () == 0) {
b8f1b8
-			fprintf (stderr,
b8f1b8
-						_("%s: failure while writing changes to %s\n"),
b8f1b8
-						Prog, sgr_dbname ());
b8f1b8
-			SYSLOG ((LOG_ERR,
b8f1b8
-						"failure while writing changes to %s",
b8f1b8
-						sgr_dbname ()));
b8f1b8
-			fail_exit (E_GRP_UPDATE);
b8f1b8
-		}
b8f1b8
-	}
b8f1b8
-#endif
b8f1b8
-#ifdef SHADOWGRP
b8f1b8
-	if (is_shadow_grp) {
b8f1b8
-		if (sgr_unlock () == 0) {
b8f1b8
-			fprintf (stderr,
b8f1b8
-						_("%s: failed to unlock %s\n"),
b8f1b8
-						Prog, sgr_dbname ());
b8f1b8
-			SYSLOG ((LOG_ERR,
b8f1b8
-						"failed to unlock %s",
b8f1b8
-						sgr_dbname ()));
b8f1b8
-			/* continue */
b8f1b8
-		}
b8f1b8
-	}
b8f1b8
-#endif
b8f1b8
-	if (gr_unlock () == 0) {
b8f1b8
-		fprintf (stderr,
b8f1b8
-					_("%s: failed to unlock %s\n"),
b8f1b8
-					Prog, gr_dbname ());
b8f1b8
-		SYSLOG ((LOG_ERR,
b8f1b8
-					"failed to unlock %s",
b8f1b8
-					gr_dbname ()));
b8f1b8
-		/* continue */
b8f1b8
-	}
b8f1b8
-}
b8f1b8
-
b8f1b8
 /*
b8f1b8
  * open_files - lock and open the password files
b8f1b8
  *
b8f1b8
@@ -1681,7 +1622,38 @@ static void open_files (void)
b8f1b8
 	}
b8f1b8
 
b8f1b8
 	if (Gflg || lflg) {
b8f1b8
-		open_group_files ();
b8f1b8
+		/*
b8f1b8
+		 * Lock and open the group file. This will load all of the
b8f1b8
+		 * group entries.
b8f1b8
+		 */
b8f1b8
+		if (gr_lock () == 0) {
b8f1b8
+			fprintf (stderr,
b8f1b8
+			         _("%s: cannot lock %s; try again later.\n"),
b8f1b8
+			         Prog, gr_dbname ());
b8f1b8
+			fail_exit (E_GRP_UPDATE);
b8f1b8
+		}
b8f1b8
+		gr_locked = true;
b8f1b8
+		if (gr_open (O_CREAT | O_RDWR) == 0) {
b8f1b8
+			fprintf (stderr,
b8f1b8
+			         _("%s: cannot open %s\n"),
b8f1b8
+			         Prog, gr_dbname ());
b8f1b8
+			fail_exit (E_GRP_UPDATE);
b8f1b8
+		}
b8f1b8
+#ifdef SHADOWGRP
b8f1b8
+		if (is_shadow_grp && (sgr_lock () == 0)) {
b8f1b8
+			fprintf (stderr,
b8f1b8
+			         _("%s: cannot lock %s; try again later.\n"),
b8f1b8
+			         Prog, sgr_dbname ());
b8f1b8
+			fail_exit (E_GRP_UPDATE);
b8f1b8
+		}
b8f1b8
+		sgr_locked = true;
b8f1b8
+		if (is_shadow_grp && (sgr_open (O_CREAT | O_RDWR) == 0)) {
b8f1b8
+			fprintf (stderr,
b8f1b8
+			         _("%s: cannot open %s\n"),
b8f1b8
+			         Prog, sgr_dbname ());
b8f1b8
+			fail_exit (E_GRP_UPDATE);
b8f1b8
+		}
b8f1b8
+#endif
b8f1b8
 	}
b8f1b8
 #ifdef ENABLE_SUBIDS
b8f1b8
 	if (vflg || Vflg) {
b8f1b8
@@ -1717,44 +1689,6 @@ static void open_files (void)
b8f1b8
 #endif				/* ENABLE_SUBIDS */
b8f1b8
 }
b8f1b8
 
b8f1b8
-/*
b8f1b8
- * open_group_files - lock and open the group files
b8f1b8
- *
b8f1b8
- *	open_group_files() loads all of the group entries.
b8f1b8
- */
b8f1b8
-static void open_group_files (void)
b8f1b8
-{
b8f1b8
-	if (gr_lock () == 0) {
b8f1b8
-		fprintf (stderr,
b8f1b8
-					_("%s: cannot lock %s; try again later.\n"),
b8f1b8
-					Prog, gr_dbname ());
b8f1b8
-		fail_exit (E_GRP_UPDATE);
b8f1b8
-	}
b8f1b8
-	gr_locked = true;
b8f1b8
-	if (gr_open (O_CREAT | O_RDWR) == 0) {
b8f1b8
-		fprintf (stderr,
b8f1b8
-					_("%s: cannot open %s\n"),
b8f1b8
-					Prog, gr_dbname ());
b8f1b8
-		fail_exit (E_GRP_UPDATE);
b8f1b8
-	}
b8f1b8
-
b8f1b8
-#ifdef SHADOWGRP
b8f1b8
-	if (is_shadow_grp && (sgr_lock () == 0)) {
b8f1b8
-		fprintf (stderr,
b8f1b8
-					_("%s: cannot lock %s; try again later.\n"),
b8f1b8
-					Prog, sgr_dbname ());
b8f1b8
-		fail_exit (E_GRP_UPDATE);
b8f1b8
-	}
b8f1b8
-	sgr_locked = true;
b8f1b8
-	if (is_shadow_grp && (sgr_open (O_CREAT | O_RDWR) == 0)) {
b8f1b8
-		fprintf (stderr,
b8f1b8
-					_("%s: cannot open %s\n"),
b8f1b8
-					Prog, sgr_dbname ());
b8f1b8
-		fail_exit (E_GRP_UPDATE);
b8f1b8
-	}
b8f1b8
-#endif
b8f1b8
-}
b8f1b8
-
b8f1b8
 /*
b8f1b8
  * usr_update - create the user entries
b8f1b8
  *
b8f1b8
-- 
b8f1b8
2.31.1
b8f1b8