Subject: Re: useradd: spaces and $ in usernames
To: Todd Vierling <tv@wasabisystems.com>
From: Hubert Feyrer <hubert.feyrer@informatik.fh-regensburg.de>
List: tech-userlevel
Date: 11/20/2001 00:57:13
On Fri, 16 Nov 2001, Todd Vierling wrote:
> : What do you think about a warning if some "unusual" username is requested?
> : Warning: non-alphanumeric/./_/- usernames may leed to non-obvious problems!
> 
> (Fine with me personally, but it still belongs in the manpage
> regardless....)

I've changed the format of the warning slightly:

user: Warning: non-standard login names may lead to non-obvious problems!

Here's a suggested text for the useradd/mod/del.8 manpages:

     user    The login name of the user to add. Login names are recommended to
             contain only alphanumeric characters, ".", "_" and "_". Using
             other characters is supported by useradd, but may lead to unex-
             pected behaviour in random applications.

Improvements?

Below is the latest patch that I would like to commit. 


 - Hubert


Index: user.c
===================================================================
RCS file: /cvsroot/basesrc/usr.sbin/user/user.c,v
retrieving revision 1.20.4.8
diff -u -r1.20.4.8 user.c
--- user.c	2001/02/26 18:01:17	1.20.4.8
+++ user.c	2001/11/19 23:55:05
@@ -45,6 +45,7 @@
 #include <ctype.h>
 #include <dirent.h>
 #include <err.h>
+#include <errno.h>
 #include <fcntl.h>
 #include <grp.h>
 #include <paths.h>
@@ -213,6 +214,30 @@
 	return ret;
 }
 
+/* quote shell metachars in a string */
+/* caller should free(3) returned string */
+static char *
+quote(const char *str)
+{
+	char *q, *qt;
+	/* This should cover most shells :-( */
+	static char meta[] = "\n \t'`\";&<>()|*?{}[]\\$!#^~";
+
+	q = malloc(2*strlen(str) + 1);
+	if (q == NULL)
+		errx(EXIT_FAILURE, "Cannot allocate memory in quote()");
+
+	qt = q;
+	for (; *str; str++) {
+		if (strchr(meta, *str) != NULL)
+			*qt++ = '\\';
+		*qt++ = *str;
+	}
+	*qt = '\0';
+
+	return q;
+}
+
 /* remove a users home directory, returning 1 for success (ie, no problems encountered) */
 static int
 removehomedir(const char *user, int uid, const char *dir)
@@ -243,7 +268,7 @@
 
 	(void) seteuid(uid);
 	/* we add the "|| true" to keep asystem() quiet if there is a non-zero exit status. */
-	(void) asystem("%s -rf %s > /dev/null 2>&1 || true", RM, dir);
+	(void) asystem("%s -rf %s > /dev/null 2>&1 || true", RM, quote(dir));
 	(void) seteuid(0);
 	if (rmdir(dir) < 0) {
 		warnx("Unable to remove all files in `%s'\n", dir);
@@ -386,10 +411,11 @@
 		warnx("No \"dot\" initialisation files found");
 	} else {
 		(void) asystem("cd %s; %s -rw -pe %s . %s", 
-				skeldir, PAX, (verbose) ? "-v" : "", dir);
+				quote(skeldir), PAX, (verbose) ? "-v" : "",
+			        quote(dir));
 	}
-	(void) asystem("%s -R -h %d:%d %s", CHOWN, uid, gid, dir);
-	(void) asystem("%s -R u+w %s", CHMOD, dir);
+	(void) asystem("%s -R -h %d:%d %s", CHOWN, uid, gid, quote(dir));
+	(void) asystem("%s -R u+w %s", CHMOD, quote(dir));
 	return n;
 }
 
@@ -407,6 +433,7 @@
 
 	if (getgrnam(group) != NULL) {
 		warnx("group `%s' already exists", group);
+		errno=0;
 		return 0;
 	}
 	if ((from = fopen(_PATH_GROUP, "r")) == NULL) {
@@ -855,7 +882,7 @@
 	int		i;
 
 	if (!valid_login(login)) {
-		errx(EXIT_FAILURE, "`%s' is not a valid login name", login);
+		warnx("Warning: non-standard login names may lead to non-obvious problems!", login);
 	}
 	if ((masterfd = open(_PATH_MASTERPASSWD, O_RDONLY)) < 0) {
 		err(EXIT_FAILURE, "can't open `%s'", _PATH_MASTERPASSWD);
@@ -971,7 +998,7 @@
 			(void) pw_abort();
 			errx(EXIT_FAILURE, "home directory `%s' already exists", home);
 		} else {
-			if (asystem("%s -p %s", MKDIR, home) != 0) {
+			if (asystem("%s -p %s", MKDIR, quote(home)) != 0) {
 				(void) close(ptmpfd);
 				(void) pw_abort();
 				err(EXIT_FAILURE, "can't mkdir `%s'", home);
@@ -1014,7 +1041,7 @@
 	int		ptmpfd;
 
 	if (!valid_login(newlogin)) {
-		errx(EXIT_FAILURE, "`%s' is not a valid login name", login);
+		warnx("Warning: non-standard login names may lead to non-obvious problems!", login);
 	}
 	if ((pwp = getpwnam(login)) == NULL) {
 		errx(EXIT_FAILURE, "No such user `%s'", login);
@@ -1144,7 +1171,7 @@
 	}
 	if (up != NULL) {
 		if ((up->u_flags & F_MKDIR) &&
-		    asystem("%s %s %s", MV, homedir, pwp->pw_dir) != 0) {
+		    asystem("%s %s %s", MV, quote(homedir), quote(pwp->pw_dir)) != 0) {
 			(void) close(ptmpfd);
 			(void) pw_abort();
 			err(EXIT_FAILURE, "can't move `%s' to `%s'",
Index: useradd.8
===================================================================
RCS file: /cvsroot/basesrc/usr.sbin/user/useradd.8,v
retrieving revision 1.5.4.1
diff -u -r1.5.4.1 useradd.8
--- useradd.8	2000/10/20 20:00:33	1.5.4.1
+++ useradd.8	2001/11/19 23:55:05
@@ -244,6 +244,13 @@
 .Ed
 .It Fl v
 enables verbose mode - explain the commands as they are executed.
+.It Ar user
+The login name of the user to add. Login names are recommended to
+contain only alphanumeric characters, ".", "_" and "_". Using other
+characters is supported by
+.Nm "" ,
+but may lead to unexpected behaviour in
+random applications. 
 .El
 .Pp
 The
Index: userdel.8
===================================================================
RCS file: /cvsroot/basesrc/usr.sbin/user/userdel.8,v
retrieving revision 1.5.4.1
diff -u -r1.5.4.1 userdel.8
--- userdel.8	2000/10/20 20:00:33	1.5.4.1
+++ userdel.8	2001/11/19 23:55:05
@@ -97,6 +97,13 @@
 and any files and other entries in them.
 .It Fl v
 perform any actions in a verbose manner.
+.It Ar user
+The login name of the user to add. Login names are recommended to
+contain only alphanumeric characters, ".", "_" and "_". Using other
+characters is supported by
+.Nm "" ,
+but may lead to unexpected behaviour in
+random applications. 
 .El
 .Pp
 The
Index: usermod.8
===================================================================
RCS file: /cvsroot/basesrc/usr.sbin/user/usermod.8,v
retrieving revision 1.4.4.3
diff -u -r1.4.4.3 usermod.8
--- usermod.8	2001/02/26 15:16:09	1.4.4.3
+++ usermod.8	2001/11/19 23:55:05
@@ -176,6 +176,13 @@
 .Ed
 .It Fl v
 enables verbose mode - explain the commands as they are executed.
+.It Ar user
+The login name of the user to add. Login names are recommended to
+contain only alphanumeric characters, ".", "_" and "_". Using other
+characters is supported by
+.Nm "" ,
+but may lead to unexpected behaviour in
+random applications. 
 .El
 .Pp
 The

-- 
Want to get a clue on IPv6 but don't know where to start? Try this:
* Basics -> http://www.onlamp.com/pub/a/onlamp/2001/05/24/ipv6_tutorial.html
* Setup  -> http://www.onlamp.com/pub/a/onlamp/2001/06/01/ipv6_tutorial.html 
Of course with your #1 IPv6 ready operating system -> http://www.NetBSD.org/