Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 14 Nov 2000 22:01:22 +0100
From:      Gerhard Sittig <Gerhard.Sittig@gmx.net>
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   bin/22860: [PATCH] adduser & friends with '$' in usernames
Message-ID:  <20001114220122.N27042@speedy.gsinet>
In-Reply-To: <20001113124402.C21033@serv.gk-domain>; from GSittig@gk-soft.de on Mon, Nov 13, 2000 at 12:44:02PM %2B0100
References:  <20001113124402.C21033@serv.gk-domain>

next in thread | previous in thread | raw e-mail | index | archive | help

>Number:         22860
>Category:       bin
>Synopsis:       [PATCH] adduser & friends with '$' in usernames
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Tue Nov 14 22:00:01 PST 2000
>Closed-Date:
>Last-Modified:
>Originator:     Gerhard Sittig
>Release:        FreeBSD 4.1-STABLE i386
>Organization:
in private
>Environment:

adduser(8), rmuser(8), pw(8) administrative commands
and usernames with non-alphanumeric characters in them

>Description:

When dealing with NTdom functionality (in heterogenous networks
with NT machines in your LAN) the need arises to put dollar signs
into usernames.

Although they can be handled well when brought into the user
database manually, the "admin's frontend" tools mentioned above
deny to accept these names, since they don't fit a given pattern
the names are checked against.

>How-To-Repeat:

Just try to add or manipulate an account named "machine$" with
the given tools.  They will be claimed "invalid".

# adduser  (opens an interactive session,
            specify "machine$" as the username)
# rmuser machine\$
# pw useradd machine\$ -g machines -h -

>Fix:

The following patch extends the adduser(8) and rmuser(8) scripts
to accept dollar signs at the username's end.  It is drawn from
the command sequence

  cd /usr/src/usr.sbin/adduser
  cvs diff

Index: adduser.perl
===================================================================
RCS file: /home/ncvs/src/usr.sbin/adduser/adduser.perl,v
retrieving revision 1.44
diff -u -r1.44 adduser.perl
--- adduser.perl	1999/08/28 01:15:11	1.44
+++ adduser.perl	2000/11/13 08:51:00
@@ -304,7 +304,7 @@
     local($name);
 
     while(1) {
-	$name = &confirm_list("Enter username", 1, "a-z0-9_-", "");
+	$name = &confirm_list("Enter username", 1, "a-z0-9_-\$", "");
 	if (length($name) > 16) {
 	    warn "Username is longer than 16 chars\a\n";
 	    next;
@@ -317,9 +317,9 @@
 sub new_users_name_valid {
     local($name) = @_;
 
-    if ($name !~ /^[a-z0-9_][a-z0-9_\-]*$/ || $name eq "a-z0-9_-") {
+    if ($name !~ /^[a-z0-9_][a-z0-9_\-]*\$?$/ || $name eq "a-z0-9_-\$") {
 	warn "Wrong username. " .
-	    "Please use only lowercase characters or digits\a\n";
+	    "Please use only lowercase characters or digits and maybe a dollar sign at the end\a\n";
 	return 0;
     } elsif ($username{$name}) {
 	warn "Username ``$name'' already exists!\a\n"; return 0;
Index: rmuser.perl
===================================================================
RCS file: /home/ncvs/src/usr.sbin/adduser/rmuser.perl,v
retrieving revision 1.8.2.1
diff -u -r1.8.2.1 rmuser.perl
--- rmuser.perl	2000/03/20 13:00:36	1.8.2.1
+++ rmuser.perl	2000/11/13 08:50:01
@@ -107,8 +107,8 @@
 if ($#ARGV == 0) {
     # Username was given as a parameter
     $login_name = pop(@ARGV);
-    die "Sorry, login name must contain alphanumeric characters only.\n"
-	if ($login_name !~ /^[a-zA-Z0-9_]\w*$/);
+    die "Sorry, login name must contain alphanumeric characters only and may end with a dollar sign.\n"
+	if ($login_name !~ /^[a-zA-Z0-9_]\w*\$?$/);
 } else {
     if ($affirm) {
 	print STDERR "${whoami}: Error: -y option given without username!\n";
@@ -276,8 +276,8 @@
 	print "Enter login name for user to remove: ";
 	$login_name = <>;
 	chop $login_name;
-	if (!($login_name =~ /^[a-z0-9_][a-z0-9_\-]*$/)) {
-	    print STDERR "Sorry, login name must contain alphanumeric characters only.\n";
+	if (!($login_name =~ /^[a-z0-9_][a-z0-9_\-]*\$?$/)) {
+	    print STDERR "Sorry, login name must contain alphanumeric characters only and may end with a dollar sign.\n";
 	} elsif (length($login_name) > 16 || length($login_name) == 0) {
 	    print STDERR "Sorry, login name must be 16 characters or less.\n";
 	} else {

The following patch extends the pw(8) command to accept dollar
signs at the username's end.  It is drawn from the command
sequence

  cd /usr/src/usr.sbin/pw
  cvs diff

and has the "side effect" of making the pw_checkname() routine
easier to maintain when user names, group names, login classes
and gecos fields should differ in their handling in future.

Index: pw.h
===================================================================
RCS file: /home/ncvs/src/usr.sbin/pw/pw.h,v
retrieving revision 1.10.2.1
diff -u -r1.10.2.1 pw.h
--- pw.h	2000/06/28 19:19:04	1.10.2.1
+++ pw.h	2000/11/13 08:36:09
@@ -62,6 +62,15 @@
         W_NUM
 };
 
+enum _gecos
+{			/* pw_checkname() classes (plausi test) */
+	GEC_PWNAME,	/* user name field */
+	GEC_GROUP,	/* user group field */
+	GEC_CLASS,	/* default login class */
+	GEC_COMMENT,	/* gecos comment field */
+	GEC_MAXDIM	/* allowed patterns table dimensioning */
+};
+
 struct carg
 {
 	int		  ch;
@@ -105,7 +114,7 @@
 
 int pw_user(struct userconf * cnf, int mode, struct cargs * _args);
 int pw_group(struct userconf * cnf, int mode, struct cargs * _args);
-char    *pw_checkname(u_char *name, int gecos);
+char    *pw_checkname(u_char *name, enum _gecos gecos);
 
 int addpwent(struct passwd * pwd);
 int delpwent(struct passwd * pwd);
Index: pw_group.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/pw/pw_group.c,v
retrieving revision 1.12.2.1
diff -u -r1.12.2.1 pw_group.c
--- pw_group.c	2000/06/28 19:19:04	1.12.2.1
+++ pw_group.c	2000/11/13 08:36:58
@@ -135,7 +135,7 @@
 			grp->gr_gid = (gid_t) atoi(a_gid->val);
 
 		if ((arg = getarg(args, 'l')) != NULL)
-			grp->gr_name = pw_checkname((u_char *)arg->val, 0);
+			grp->gr_name = pw_checkname((u_char *)arg->val, GEC_GROUP);
 	} else {
 		if (a_name == NULL)	/* Required */
 			errx(EX_DATAERR, "group name required");
@@ -145,7 +145,7 @@
 		extendarray(&members, &grmembers, 200);
 		members[0] = NULL;
 		grp = &fakegroup;
-		grp->gr_name = pw_checkname((u_char *)a_name->val, 0);
+		grp->gr_name = pw_checkname((u_char *)a_name->val, GEC_GROUP);
 		grp->gr_passwd = "*";
 		grp->gr_gid = gr_gidpolicy(cnf, args);
 		grp->gr_mem = members;
Index: pw_user.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/pw/pw_user.c,v
retrieving revision 1.34.2.7
diff -u -r1.34.2.7 pw_user.c
--- pw_user.c	2000/09/20 11:19:55	1.34.2.7
+++ pw_user.c	2000/11/13 09:16:54
@@ -231,7 +231,7 @@
 		}
 	}
 	if ((arg = getarg(args, 'L')) != NULL)
-		cnf->default_class = pw_checkname((u_char *)arg->val, 0);
+		cnf->default_class = pw_checkname((u_char *)arg->val, GEC_CLASS);
 
 	if ((arg = getarg(args, 'G')) != NULL && arg->val) {
 		int i = 0;
@@ -293,7 +293,7 @@
 	}
 
 	if ((a_name = getarg(args, 'n')) != NULL)
-		pwd = GETPWNAM(pw_checkname((u_char *)a_name->val, 0));
+		pwd = GETPWNAM(pw_checkname((u_char *)a_name->val, GEC_PWNAME));
 	a_uid = getarg(args, 'u');
 
 	if (a_uid == NULL) {
@@ -455,7 +455,7 @@
 		if ((arg = getarg(args, 'l')) != NULL) {
 			if (strcmp(pwd->pw_name, "root") == 0)
 				errx(EX_DATAERR, "can't rename `root' account");
-			pwd->pw_name = pw_checkname((u_char *)arg->val, 0);
+			pwd->pw_name = pw_checkname((u_char *)arg->val, GEC_PWNAME);
 			edited = 1;
 		}
 
@@ -595,7 +595,7 @@
 	 * Shared add/edit code
 	 */
 	if ((arg = getarg(args, 'c')) != NULL) {
-		char	*gecos = pw_checkname((u_char *)arg->val, 1);
+		char	*gecos = pw_checkname((u_char *)arg->val, GEC_COMMENT);
 		if (strcmp(pwd->pw_gecos, gecos) != 0) {
 			pwd->pw_gecos = gecos;
 			edited = 1;
@@ -1208,22 +1208,29 @@
 }
 
 char    *
-pw_checkname(u_char *name, int gecos)
+pw_checkname(u_char *name, enum _gecos gecos)
 {
 	int             l = 0;
-	char const     *notch = gecos ? ":!@" : " ,\t:+&#%$^()!@~*?<>=|\\/\"";
+	static const char *notchtab[GEC_MAXDIM] = {
+		" ,\t:+&#%^()!@~*?<>=|\\/\"" , /* GEC_PWNAME */
+		" ,\t:+&#%$^()!@~*?<>=|\\/\"", /* GEC_GROUP */
+		" ,\t:+&#%$^()!@~*?<>=|\\/\"", /* GEC_CLASS */
+		":!@"                        , /* GEC_COMMENT */
+	};
+	char const     *notch = notchtab[gecos];
 
 	while (name[l]) {
 		if (strchr(notch, name[l]) != NULL || name[l] < ' ' || name[l] == 127 ||
-			(!gecos && l==0 && name[l] == '-') ||	/* leading '-' */
-			(!gecos && name[l] & 0x80))	/* 8-bit */
+			(gecos != GEC_COMMENT && l==0 && name[l] == '-') ||	/* leading '-' */
+			(gecos != GEC_COMMENT && name[l] == '$' && name[l+1]) ||	/* not a trailing '$' */
+			(gecos != GEC_COMMENT && name[l] & 0x80))	/* 8-bit */
 			errx(EX_DATAERR, (name[l] >= ' ' && name[l] < 127)
 					    ? "invalid character `%c' in field"
 					    : "invalid character 0x%02x in field",
 					    name[l]);
 		++l;
 	}
-	if (!gecos && l > LOGNAMESIZE)
+	if (gecos != GEC_COMMENT && l > LOGNAMESIZE)
 		errx(EX_DATAERR, "name too long `%s'", name);
 	return (char *)name;
 }

Feel free to change the wording of printouts and to rearrange the
last check (LOGNAMESIZE length for anything that's not a gecos
field -- does it actually apply only to user names and group
names or maybe login classes, too?  I'm not sure of this.  As
well as I never tried dollar signs in anything that's not a user
name).


virtually yours   82D1 9B9C 01DC 4FB4 D7B4  61BE 3F49 4F77 72DE DA76
Gerhard Sittig   true | mail -s "get gpg key" Gerhard.Sittig@gmx.net
-- 
     If you don't understand or are scared by any of the above
             ask your parents or an adult to help you.

>Release-Note:
>Audit-Trail:
>Unformatted:


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20001114220122.N27042>