[Pkg-shadow-commits] r1760 - in upstream/trunk: . src

nekral-guest at alioth.debian.org nekral-guest at alioth.debian.org
Sun Feb 3 17:45:58 UTC 2008


Author: nekral-guest
Date: 2008-02-03 17:45:58 +0000 (Sun, 03 Feb 2008)
New Revision: 1760

Modified:
   upstream/trunk/ChangeLog
   upstream/trunk/NEWS
   upstream/trunk/src/newusers.c
Log:
	* NEWS: newusers will behave more like useradd.
	* src/newusers.c: The user's ID must be found before the group ID
	to mimic useradd's behavior choices of UID and GID.
	* src/newusers.c: Reuse the generic find_new_uid() and
	find_new_gid() functions. This permits to respect the
	UID_MIN/UID_MAX and GID_MIN/GID_MAX variables, should 
	* src/newusers.c: Check if the user or group exist using the
	external databases (with the libc getpwnam/getgrnam functions).
	Refuse to update an user which exist in an external database but
	does not exist in the local database.
	* src/newusers.c: Check the usernames and groupnames with
	check_user_name() and check_group_name()
	* src/newusers.c: Use isdigit() for readability.
	* src/newusers.c: Check if numerical IDs are valid (no remaining
	chars).

	* NEWS, src/newusers.c: Fix the support for the NONE crypt method.

	* src/newusers.c: Fix shadow group support (the list of admins was
	not defined; it is now set to an empty list).


Modified: upstream/trunk/ChangeLog
===================================================================
--- upstream/trunk/ChangeLog	2008-02-03 17:23:58 UTC (rev 1759)
+++ upstream/trunk/ChangeLog	2008-02-03 17:45:58 UTC (rev 1760)
@@ -1,5 +1,32 @@
 2008-02-03  Nicolas François  <nicolas.francois at centraliens.net>
 
+	* NEWS: newusers will behave more like useradd.
+	* src/newusers.c: The user's ID must be found before the group ID
+	to mimic useradd's behavior choices of UID and GID.
+	* src/newusers.c: Reuse the generic find_new_uid() and
+	find_new_gid() functions. This permits to respect the
+	UID_MIN/UID_MAX and GID_MIN/GID_MAX variables, should 
+	* src/newusers.c: Check if the user or group exist using the
+	external databases (with the libc getpwnam/getgrnam functions).
+	Refuse to update an user which exist in an external database but
+	does not exist in the local database.
+	* src/newusers.c: Check the usernames and groupnames with
+	check_user_name() and check_group_name()
+	* src/newusers.c: Use isdigit() for readability.
+	* src/newusers.c: Check if numerical IDs are valid (no remaining
+	chars).
+
+2008-02-03  Nicolas François  <nicolas.francois at centraliens.net>
+
+	* NEWS, src/newusers.c: Fix the support for the NONE crypt method.
+
+2008-02-03  Nicolas François  <nicolas.francois at centraliens.net>
+
+	* src/newusers.c: Fix shadow group support (the list of admins was
+	not defined; it is now set to an empty list).
+
+2008-02-03  Nicolas François  <nicolas.francois at centraliens.net>
+
 	* NEWS, libmisc/salt.c: Do not seed the random number generator
 	each time, and use the time in microseconds to avoid having the
 	same salt for different passwords generated in the same second.

Modified: upstream/trunk/NEWS
===================================================================
--- upstream/trunk/NEWS	2008-02-03 17:23:58 UTC (rev 1759)
+++ upstream/trunk/NEWS	2008-02-03 17:45:58 UTC (rev 1760)
@@ -34,6 +34,9 @@
     because the membership is already set by their primary group.
   * Added support for gshadow.
   * Avoid using the same salt for different passwords.
+  * Fix support for the NONE crypt method.
+  * newusers will behave more like useradd regarding the choice of UID or
+    GID or regarding the validity of user and group names.
 - passwd
   * Make sure that no more than one username argument was provided.
 - pwck

Modified: upstream/trunk/src/newusers.c
===================================================================
--- upstream/trunk/src/newusers.c	2008-02-03 17:23:58 UTC (rev 1759)
+++ upstream/trunk/src/newusers.c	2008-02-03 17:45:58 UTC (rev 1760)
@@ -44,6 +44,7 @@
 #include <grp.h>
 #include <fcntl.h>
 #include <getopt.h>
+#include <ctype.h>
 #ifdef USE_PAM
 #include "pam_defs.h"
 #endif				/* USE_PAM */
@@ -55,6 +56,7 @@
 #include "pwio.h"
 #include "sgroupio.h"
 #include "shadowio.h"
+#include "chkname.h"
 /*
  * Global variables
  */
@@ -76,8 +78,9 @@
 
 /* local function prototypes */
 static void usage (void);
-static int add_group (const char *, const char *, gid_t *);
-static int add_user (const char *, const char *, uid_t *, gid_t);
+static int add_group (const char *, const char *, gid_t *, gid_t);
+static int get_uid (const char *, uid_t *);
+static int add_user (const char *, uid_t, gid_t);
 static void update_passwd (struct passwd *, const char *);
 static int add_passwd (struct passwd *, const char *);
 static void process_flags (int argc, char **argv);
@@ -111,13 +114,11 @@
 /*
  * add_group - create a new group or add a user to an existing group
  */
-static int add_group (const char *name, const char *gid, gid_t * ngid)
+static int add_group (const char *name, const char *gid, gid_t *ngid, uid_t uid)
 {
-	const struct passwd *pwd;
 	const struct group *grp;
 	struct group grent;
 	char *members[1];
-	int i;
 #ifdef SHADOWGRP
 	const struct sgrp *sg;
 #endif
@@ -126,7 +127,10 @@
 	 * Start by seeing if the named group already exists. This will be
 	 * very easy to deal with if it does.
 	 */
-	grp = gr_locate (gid);
+	grp = getgrnam (gid);
+	if (NULL == grp) {
+		grp = gr_locate (gid);
+	}
 	if (NULL != grp) {
 		/* The user will use this ID for her primary group */
 		*ngid = grp->gr_gid;
@@ -134,72 +138,56 @@
 		return 0;
 	}
 
-	/*
-	 * The group did not exist, so I try to figure out what the GID is
-	 * going to be. The gid parameter is probably "", meaning I figure
-	 * out the GID from the password file. I want the UID and GID to
-	 * match, unless the GID is already used.
-	 */
-	if (gid[0] == '\0') {
-		i = 100;
-		for (pw_rewind (); (pwd = pw_next ());) {
-			if (pwd->pw_uid >= (unsigned int)i) {
-				i = pwd->pw_uid + 1;
-			}
-		}
-		for (gr_rewind (); (grp = gr_next ());) {
-			if (grp->gr_gid == (unsigned int)i) {
-				i = -1;
-				break;
-			}
-		}
-	} else if ((gid[0] >= '0') && (gid[0] <= '9')) {
+	if (isdigit (gid[0])) {
 		/*
 		 * The GID is a number, which means either this is a brand
 		 * new group, or an existing group.
 		 */
-		i = atoi (gid);
-		for (gr_rewind (); (grp = gr_next ());) {
-			if (grp->gr_gid == (unsigned int)i) {
-				/* The user will use this ID for her
-				 * primary group */
-				*ngid = grp->gr_gid;
-				/* Don't check gshadow */
-				return 0;
-			}
+		char *endptr;
+		long int i = strtoul (gid, &endptr, 10);
+		if ((*endptr != '\0') && (errno != ERANGE)) {
+			fprintf (stderr,
+			         _("%s: group ID `%s' is not valid\n"),
+			         Prog, gid);
+			return -1;
 		}
+		if (   (getgrgid (i) != NULL)
+		    || (gr_locate_gid (i) != NULL)) {
+			/* The user will use this ID for her
+			 * primary group */
+			*ngid = i;
+			return 0;
+		}
+		grent.gr_gid = i;
 	} else {
-		/*
-		 * The last alternative is that the GID is a name which is
-		 * not already the name of an existing group, and I need to
-		 * figure out what group ID that group name is going to
-		 * have.
+		/* The gid parameter can be "" or a name which is not
+		 * already the name of an existing group.
+		 * In both cases, figure out what group ID can be used.
 		 */
-		i = -1;
-	}
-
-	/*
-	 * If I don't have a group ID by now, I'll go get the next one.
-	 */
-	if (i == -1) {
-		for (i = 100, gr_rewind (); (grp = gr_next ());) {
-			if (grp->gr_gid >= (unsigned int)i) {
-				i = grp->gr_gid + 1;
-			}
+		if (find_new_gid(0, &grent.gr_gid, &uid) < 0) {
+			return -1;
 		}
 	}
 
 	/*
 	 * Now I have all of the fields required to create the new group.
 	 */
-	if (('\0' != gid[0]) && ((gid[0] <= '0') || (gid[0] >= '9'))) {
+	if (('\0' != gid[0]) && (!isdigit (gid[0]))) {
 		grent.gr_name = xstrdup (gid);
 	} else {
 		grent.gr_name = xstrdup (name);
 	}
 
+	/* Check if this is a valid group name */
+	if (check_group_name (grent.gr_name) == 0) {
+		fprintf (stderr,
+		         _("%s: invalid group name `%s'\n"),
+		         Prog, grent.gr_name);
+		free (grent.gr_name);
+		return -1;
+	}
+
 	grent.gr_passwd = "x";	/* XXX warning: const */
-	grent.gr_gid = i;
 	members[0] = NULL;
 	grent.gr_mem = members;
 
@@ -207,12 +195,12 @@
 
 #ifdef SHADOWGRP
 	if (is_shadow_grp) {
-		sg = sgr_locate (grp->gr_name);
+		sg = sgr_locate (grent.gr_name);
 
 		if (NULL != sg) {
 			fprintf (stderr,
 			         _("%s: group %s is a shadow group, but does not exist in /etc/group\n"),
-			         Prog, grp->gr_name);
+			         Prog, grent.gr_name);
 			return -1;
 		}
 	}
@@ -225,9 +213,11 @@
 #ifdef SHADOWGRP
 	if (is_shadow_grp) {
 		struct sgrp sgrent;
+		char *admins[1];
 		sgrent.sg_name = grent.gr_name;
 		sgrent.sg_passwd = "*";	/* XXX warning: const */
-		sgrent.sg_adm = NULL;
+		admins[0] = NULL;
+		sgrent.sg_adm = admins;
 		sgrent.sg_mem = members;
 
 		if (sgr_update (&sgrent) == 0) {
@@ -242,54 +232,77 @@
 	return 0;
 }
 
-/*
- * add_user - create a new user ID
- */
-static int add_user (const char *name, const char *uid, uid_t * nuid, gid_t gid)
-{
+static int get_uid (const char *uid, uid_t *nuid) {
 	const struct passwd *pwd = NULL;
-	struct passwd pwent;
-	uid_t i;
 
 	/*
 	 * The first guess for the UID is either the numerical UID that the
 	 * caller provided, or the next available UID.
 	 */
-	if ((uid[0] >= '0') && (uid[0] <= '9')) {
-		i = atoi (uid);
+	if (isdigit (uid[0])) {
+		char *endptr;
+		long int i = strtoul (uid, &endptr, 10);
+		if ((*endptr != '\0') && (errno != ERANGE)) {
+			fprintf (stderr,
+			         _("%s: user ID `%s' is not valid\n"),
+			         Prog, uid);
+			return -1;
+		}
+		*nuid = i;
 	} else {
 		if ('\0' != uid[0]) {
-			pwd = pw_locate (uid);
-		}
+			/* local, no need for xgetpwnam */
+			pwd = getpwnam (uid);
+			if (NULL == pwd) {
+				pwd = pw_locate (uid);
+			}
 
-		if (NULL != pwd) {
-			i = pwd->pw_uid;
+			if (NULL != pwd) {
+				*nuid = pwd->pw_uid;
+			} else {
+				fprintf (stderr,
+				         _("%s: user `%s' does not exist\n"),
+				         Prog, uid);
+				return -1;
+			}
 		} else {
-			/* Start with gid, either the specified GID, or an ID
-			 * greater than all the group and user IDs */
-			i = gid;
-			for (pw_rewind (); (pwd = pw_next ());) {
-				if (pwd->pw_uid >= i) {
-					i = pwd->pw_uid + 1;
-				}
+			if (find_new_uid (0, nuid, NULL) < 0) {
+				return -1;
 			}
 		}
 	}
 
+	return 0;
+}
+
+/*
+ * add_user - create a new user ID
+ */
+static int add_user (const char *name, uid_t uid, gid_t gid)
+{
+	struct passwd pwent;
+
+	/* Check if this is a valid user name */
+	if (check_user_name (name) == 0) {
+		fprintf (stderr,
+		         _("%s: invalid user name `%s'\n"),
+		         Prog, name);
+		return -1;
+	}
+
 	/*
 	 * I don't want to fill in the entire password structure members
 	 * JUST YET, since there is still more data to be added. So, I fill
 	 * in the parts that I have.
 	 */
 	pwent.pw_name = xstrdup (name);
+	pwent.pw_uid = uid;
 	pwent.pw_passwd = "x";	/* XXX warning: const */
-	pwent.pw_uid = i;
 	pwent.pw_gid = gid;
 	pwent.pw_gecos = "";	/* XXX warning: const */
 	pwent.pw_dir = "";	/* XXX warning: const */
 	pwent.pw_shell = "";	/* XXX warning: const */
 
-	*nuid = i;
 	return !pw_update (&pwent);
 }
 
@@ -342,9 +355,14 @@
 	sp = spw_locate (pwd->pw_name);
 	if (NULL != sp) {
 		spent = *sp;
-		spent.sp_pwdp = pw_encrypt (password,
-		                            crypt_make_salt (crypt_method,
-		                                             crypt_arg));
+		if (   (crypt_method != NULL)
+		    && (0 == strcmp(crypt_method, "NONE"))) {
+			spent.sp_pwdp = (char *)password;
+		} else {
+			const char *salt = crypt_make_salt (crypt_method,
+			                                    crypt_arg);
+			spent.sp_pwdp = pw_encrypt (password, salt);
+		}
 		return !spw_update (&spent);
 	}
 
@@ -364,8 +382,12 @@
 	 * shadow password file entry.
 	 */
 	spent.sp_namp = pwd->pw_name;
-	spent.sp_pwdp = pw_encrypt (password,
-	                            crypt_make_salt (crypt_method, crypt_arg));
+	if ((crypt_method != NULL) && (0 == strcmp(crypt_method, "NONE"))) {
+		pwd->pw_passwd = (char *)password;
+	} else {
+		const char *salt = crypt_make_salt (crypt_method, crypt_arg);
+		spent.sp_pwdp = pw_encrypt (password, salt);
+	}
 	spent.sp_lstchg = time ((time_t *) 0) / SCALE;
 	spent.sp_min = getdef_num ("PASS_MIN_DAYS", 0);
 	/* 10000 is infinity this week */
@@ -684,8 +706,28 @@
 		}
 
 		/*
-		 * Now the fields are processed one by one. The first field
-		 * to be processed is the group name. A new group will be
+		 * First check if we have to create of update an user
+		 */
+		pw = pw_locate (fields[0]);
+		/* local, no need for xgetpwnam */
+		if (   (NULL == pw)
+		    && (getpwnam (fields[0]) != NULL)) {
+			fprintf (stderr, _("%s: cannot update the entry of user %s (not in the passwd database)\n"), Prog, fields[0]);
+			errors++;
+			continue;
+		}
+
+		if (   (NULL == pw)
+		    && (get_uid (fields[2], &uid) != 0)) {
+			fprintf (stderr,
+			         _("%s: line %d: can't create user\n"),
+			         Prog, line);
+			errors++;
+			continue;
+		}
+
+		/*
+		 * Processed is the group name. A new group will be
 		 * created if the group name is non-numeric and does not
 		 * already exist. If the group name is a number (which is not
 		 * an existing GID), a group with the same name as the user
@@ -696,11 +738,10 @@
 		 * new group, if that group ID exists, a whole new group ID
 		 * will be made up.
 		 */
-		pw = pw_locate (fields[0]);
 		if (   (NULL == pw)
-		    && (add_group (fields[0], fields[3], &gid) != 0)) {
+		    && (add_group (fields[0], fields[3], &gid, uid) != 0)) {
 			fprintf (stderr,
-			         _("%s: line %d: can't create GID\n"),
+			         _("%s: line %d: can't create group\n"),
 			         Prog, line);
 			errors++;
 			continue;
@@ -714,9 +755,9 @@
 		 * will at least be a (struct passwd) for the user.
 		 */
 		if (   (NULL == pw)
-		    && (add_user (fields[0], fields[2], &uid, gid) != 0)) {
+		    && (add_user (fields[0], uid, gid) != 0)) {
 			fprintf (stderr,
-			         _("%s: line %d: can't create UID\n"),
+			         _("%s: line %d: can't create user\n"),
 			         Prog, line);
 			errors++;
 			continue;




More information about the Pkg-shadow-commits mailing list