Goal: Relaxed usernames/groupnames checking patch.

Status wrt upstream: Debian specific. Not to be used upstream

Details:
 Allows any non-empty user/grounames that don't contain ':', ',' or '\n'
 characters and don't start with '-', '+', or '~'. This patch is more
 restrictive than original Karl's version. closes: #264879
 Also closes: #377844
 
 Comments from Karl Ramm (shadow 1:4.0.3-9, 20 Aug 2003 02:06:50 -0400):
 
 I can't come up with a good justification as to why characters other
 than ':'s and '\0's should be disallowed in group and usernames (other
 than '-' as the leading character).  Thus, the maintenance tools don't
 anymore.  closes: #79682, #166798, #171179

--- a/libmisc/chkname.c
+++ b/libmisc/chkname.c
@@ -54,6 +54,7 @@
 		return true;
 	}
 
+#if 0
 	/*
 	 * User/group names must match [a-z_][a-z0-9_-]*[$]
 	 */
@@ -73,7 +74,62 @@
 			return false;
 		}
 	}
+#endif
+	/*
+	 * POSIX indicate that usernames are composed of characters from the
+	 * portable filename character set [A-Za-z0-9._-], and that the hyphen
+	 * should not be used as the first character of a portable user name.
+	 *
+	 * Allow more relaxed user/group names in Debian -- ^[^-~+:,\s][^:,\s]*$
+	 */
+	bool is_numeric = true;
+	bool is_hex = true;
+	bool is_octal = true;
+	/*
+	 * We skip the hex and octal checks for the first two characters in the
+	 * loop, and inspect them individually before the loop starts. This
+	 * checks for "0x" and "0o" at the beginning of the username while still
+	 * treating "x" and "o" as non-numeric characters in all other scenarios
+	 */
+	int chars_checked = 0;
+
+	if (   ('\0' == *name)
+	    || ('-'  == *name)
+	    || ('~'  == *name)
+	    || ('+'  == *name)) {
+		return false;
+	}
+	/* if the username does not start with "0x" it is not hexadecimal */
+	if (*name != '0' || *(name + 1) != 'x') {
+		is_hex = false;
+	}
+	/* if the username does not start with "0o" it is not octal */
+	if (*name != '0' || *(name + 1) != 'o') {
+		is_octal = false;
+	}
+	do {
+		if ((':' == *name) || (',' == *name) || isspace(*name)) {
+			return false;
+		}
+		if ((*name < '0' || *name > '9')) {
+			is_numeric = false;
+		}
+		if ((*name < '0' || *name > '9') &&
+		    (*name < 'A' || *name > 'F') &&
+		    (*name < 'a' || *name > 'f') &&
+		    chars_checked >= 2) {
+			is_hex = false;
+		}
+		if ((*name < '0' || *name > '7') && chars_checked >= 2) {
+			is_octal = false;
+		}
+		chars_checked++;
+		name++;
+	} while ('\0' != *name);
 
+	if (is_numeric || is_hex || is_octal) {
+		return false;
+	}
 	return true;
 }
 
--- a/man/useradd.8.xml
+++ b/man/useradd.8.xml
@@ -662,12 +662,25 @@
     </para>
 
     <para>
-      Usernames must start with a lower case letter or an underscore,
+      It is usually recommended to only use usernames that begin with a lower case letter or an underscore,
       followed by lower case letters, digits, underscores, or dashes.
       They can end with a dollar sign.
       In regular expression terms: [a-z_][a-z0-9_-]*[$]?
     </para>
     <para>
+      On Debian, the only constraints are that usernames must neither start
+      with a dash ('-') nor plus ('+') nor tilde ('~') nor contain a
+      colon (':'), a comma (','), or a whitespace (space: ' ',
+      end of line: '\n', tabulation: '\t', etc.). Note that using a slash
+      ('/') may break the default algorithm for the definition of the
+      user's home directory.
+    </para>
+    <para>
+      On Ubuntu, the same constraints as Debian are in place, with the
+      additional constraint that the username cannot be fully numeric.
+      This includes octal and hexadecimal syntax.
+    </para>
+    <para>
       Usernames may only be up to 32 characters long.
     </para>
   </refsect1>
--- a/man/groupadd.8.xml
+++ b/man/groupadd.8.xml
@@ -273,12 +273,23 @@
    <refsect1 id='caveats'>
      <title>CAVEATS</title>
      <para>
-       Groupnames must start with a lower case letter or an underscore,
+       It is usually recommended to only use groupnames that begin with a lower case letter or an underscore,
        followed by lower case letters, digits, underscores, or dashes.
        They can end with a dollar sign.
        In regular expression terms: [a-z_][a-z0-9_-]*[$]?
      </para>
      <para>
+       On Debian, the only constraints are that groupnames must neither start
+       with a dash ('-') nor plus ('+') nor tilde ('~') nor contain a
+       colon (':'), a comma (','), or a whitespace (space:' ',
+       end of line: '\n', tabulation: '\t', etc.).
+     </para>
+    <para>
+      On Ubuntu, the same constraints as Debian are in place, with the
+      additional constraint that the groupname cannot be fully numeric.
+      This includes octal and hexadecimal syntax.
+    </para>
+     <para>
        Groupnames may only be up to &GROUP_NAME_MAX_LENGTH; characters long.
      </para>
      <para>
