932fac9
--- shadow-4.0.14/man/useradd.8.goodname	2006-01-05 17:54:26.000000000 +0100
932fac9
+++ shadow-4.0.14/man/useradd.8	2006-01-05 18:01:18.000000000 +0100
932fac9
@@ -166,8 +166,6 @@
932fac9
 Similarly, if the username already exists in an external user database such as NIS,
932fac9
 \fBuseradd\fR
932fac9
 will deny the user account creation request.
932fac9
-.PP
932fac9
-Usernames must begin with a lower case letter or an underscore, and only lower case letters, underscores, dashes, and dollar signs may follow. In regular expression terms: [a\-z_][a\-z0\-9_\-]*[$]
932fac9
 .SH "FILES"
932fac9
 .TP
932fac9
 \fI/etc/passwd\fR
932fac9
--- shadow-4.0.14/libmisc/chkname.c.goodname	2005-08-31 19:24:57.000000000 +0200
932fac9
+++ shadow-4.0.14/libmisc/chkname.c	2006-01-05 17:59:45.000000000 +0100
932fac9
@@ -18,16 +18,24 @@
932fac9
 static int good_name (const char *name)
932fac9
 {
932fac9
 	/*
932fac9
-	 * User/group names must match [a-z_][a-z0-9_-]*[$]
932fac9
-	 */
932fac9
-	if (!*name || !((*name >= 'a' && *name <= 'z') || *name == '_'))
932fac9
+         * User/group names must match gnu e-regex:
932fac9
+         *    [a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,30}[a-zA-Z0-9_.$-]?
932fac9
+         *
932fac9
+         * as a non-POSIX, extension, allow "$" as the last char for
932fac9
+         * sake of Samba 3.x "add machine script"
932fac9
+         */
932fac9
+	if (!*name || !((*name >= 'a' && *name <= 'z')
932fac9
+             || (*name >= 'A' && *name <= 'Z')
932fac9
+             || (*name >= '0' && *name <= '9')
932fac9
+             || *name == '_' || *name == '.'))
932fac9
 		return 0;
932fac9
 
932fac9
 	while (*++name) {
932fac9
-		if (!((*name >= 'a' && *name <= 'z') ||
932fac9
-		      (*name >= '0' && *name <= '9') ||
932fac9
-		      *name == '_' || *name == '-' ||
932fac9
-		      (*name == '$' && *(name + 1) == '\0')))
932fac9
+		if (!(  (*name >= 'a' && *name <= 'z')
932fac9
+		     || (*name >= 'A' && *name <= 'Z')
932fac9
+                     || (*name >= '0' && *name <= '9')
932fac9
+                     || *name == '_' || *name == '.' || *name == '-'
932fac9
+                     || (*name == '$' && *(name + 1) == '\0')))
932fac9
 			return 0;
932fac9
 	}
932fac9
 
932fac9
@@ -43,10 +51,9 @@
932fac9
 #endif
932fac9
 
932fac9
 	/*
932fac9
-	 * User names are limited by whatever utmp can
932fac9
-	 * handle (usually max 8 characters).
932fac9
+	 * User names are limited by whatever utmp can handle.
932fac9
 	 */
932fac9
-	if (strlen (name) > sizeof (ut.ut_user))
932fac9
+	if (strlen(name) + 1 > sizeof(ut.ut_user))
932fac9
 		return 0;
932fac9
 
932fac9
 	return good_name (name);
932fac9
@@ -54,11 +61,13 @@
932fac9
 
932fac9
 int check_group_name (const char *name)
932fac9
 {
932fac9
-	/*
932fac9
-	 * Arbitrary limit for group names - max 16
932fac9
-	 * characters (same as on HP-UX 10).
932fac9
-	 */
932fac9
-	if (strlen (name) > 16)
932fac9
+#if HAVE_UTMPX_H
932fac9
+	struct utmpx ut;
932fac9
+#else
932fac9
+	struct utmp ut;
932fac9
+#endif
932fac9
+
932fac9
+	if (strlen(name) + 1 > sizeof(ut.ut_user))
932fac9
 		return 0;
932fac9
 
932fac9
 	return good_name (name);