diff -Nru shadow-4.8.1/debian/changelog shadow-4.8.1/debian/changelog --- shadow-4.8.1/debian/changelog 2020-05-28 06:37:47.000000000 +0000 +++ shadow-4.8.1/debian/changelog 2021-07-14 22:08:18.000000000 +0000 @@ -1,3 +1,10 @@ +shadow (1:4.8.1-1ubuntu5.20.04.1) focal; urgency=medium + + * Disallow purely numeric usernames. This includes hexadecimal + octal syntax. (LP: #1927078) + + -- William 'jawn-smith' Wilson Wed, 14 Jul 2021 17:08:18 -0500 + shadow (1:4.8.1-1ubuntu5.20.04) focal; urgency=medium * debian/patches/1015_add_zsys_support.patch: diff -Nru shadow-4.8.1/debian/patches/506_relaxed_usernames shadow-4.8.1/debian/patches/506_relaxed_usernames --- shadow-4.8.1/debian/patches/506_relaxed_usernames 2020-02-07 15:32:06.000000000 +0000 +++ shadow-4.8.1/debian/patches/506_relaxed_usernames 2021-07-14 22:08:18.000000000 +0000 @@ -25,7 +25,7 @@ /* * User/group names must match [a-z_][a-z0-9_-]*[$] */ -@@ -73,6 +74,26 @@ +@@ -73,7 +74,62 @@ return false; } } @@ -37,24 +37,60 @@ + * + * 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,20 @@ +@@ -662,12 +662,25 @@ @@ -73,12 +109,17 @@ + user's home directory. + + ++ 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. ++ ++ Usernames may only be up to 32 characters long. --- a/man/groupadd.8.xml +++ b/man/groupadd.8.xml -@@ -273,12 +273,18 @@ +@@ -273,12 +273,23 @@ CAVEATS @@ -94,6 +135,11 @@ + colon (':'), a comma (','), or a whitespace (space:' ', + end of line: '\n', tabulation: '\t', etc.). + ++ ++ 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. ++ + Groupnames may only be up to &GROUP_NAME_MAX_LENGTH; characters long. diff -Nru shadow-4.8.1/debian/tests/control shadow-4.8.1/debian/tests/control --- shadow-4.8.1/debian/tests/control 2020-03-09 09:33:50.000000000 +0000 +++ shadow-4.8.1/debian/tests/control 2021-07-14 22:08:18.000000000 +0000 @@ -1,2 +1,2 @@ -Tests: smoke +Tests: smoke, numeric-username Restrictions: needs-root, allow-stderr diff -Nru shadow-4.8.1/debian/tests/numeric-username shadow-4.8.1/debian/tests/numeric-username --- shadow-4.8.1/debian/tests/numeric-username 1970-01-01 00:00:00.000000000 +0000 +++ shadow-4.8.1/debian/tests/numeric-username 2021-07-14 22:08:18.000000000 +0000 @@ -0,0 +1,25 @@ +#!/bin/sh + +set -ux + +# purely numeric usernames are considered invalid +for invalidUsername in "0" "00" "0123456789" "0x0" "0x0123456789" "0o0" "0o01234567" "0xDEADBEEF" "0xcafe42" "0xdeadbeef" "0xdeadBEEF" +do + useradd $invalidUsername + ret=$? + if [ $ret -eq 0 ] + then + exit 1 + fi +done + +# usernames that start with a digit and contain other valid characters should not fail +for validUsername in "0root" "0123456789root" "0-0" "0_0" "0.o" "0xo" "0-o" "0_o" "0x0x0x0" "0o0123456789" "0.0.0.0" "0x123.456.789" "0o123.456.789" "123.456" "0.0" "0xdeadbeefjawn-smith" "0o123jawn-smith" +do + useradd $validUsername + ret=$? + if [ $ret -ne 0 ] + then + exit 1 + fi +done