]> git.ipfire.org Git - thirdparty/shadow.git/commitdiff
src/newusers.c: A user/group name with a leading digit is valid
authorAlejandro Colomar <alx@kernel.org>
Sat, 3 Jan 2026 23:15:15 +0000 (00:15 +0100)
committerSerge Hallyn <serge@hallyn.com>
Wed, 8 Jul 2026 12:35:04 +0000 (07:35 -0500)
Only consider a string to be a UID/GID if it is all digits.

Here's a reproducer of the bug:

$ echo 'foo:p::1a::/tmp/nonexistent:/usr/bin/false' > x
$ sudo newusers ./x
newusers: invalid group ID '1a'
newusers: line 1: can't create group

Where the expected behavior would be the same as for a group name that
doesn't start with a digit:

$ echo 'foo:p::a1a::/tmp/nonexistent:/usr/bin/false' > x
$ sudo newusers ./x
$ tail -n1 /etc/group
a1a:x:1004:
$ tail -n1 /etc/passwd
foo:x:1004:1004::/tmp/nonexistent:/usr/bin/false

Closes: <https://github.com/shadow-maint/shadow/issues/1474>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
src/newusers.c

index a8df7c1b759dbf140db54fcdb2c817a6f432b13c..d71f7f5c65d405a36ea62b86d1b09a004d385c4a 100644 (file)
@@ -236,7 +236,7 @@ static int add_group (const char *name, const char *gid, gid_t *ngid, uid_t uid)
                return 0;
        }
 
-       if (isdigit_c(gid[0])) {
+       if (!streq(gid, "") && strisdigit_c(gid)) {
                /*
                 * The GID is a number, which means either this is a brand
                 * new group, or an existing group.
@@ -280,7 +280,7 @@ static int add_group (const char *name, const char *gid, gid_t *ngid, uid_t uid)
        /*
         * Now I have all of the fields required to create the new group.
         */
-       if (!streq(gid, "") && (!isdigit_c(gid[0]))) {
+       if (!streq(gid, "") && !strisdigit_c(gid)) {
                grent.gr_name = xstrdup (gid);
        } else {
                grent.gr_name = xstrdup (name);
@@ -345,7 +345,7 @@ static int get_user_id (const char *uid, uid_t *nuid) {
         * The first guess for the UID is either the numerical UID that the
         * caller provided, or the next available UID.
         */
-       if (isdigit_c(uid[0])) {
+       if (!streq(uid, "") && strisdigit_c(uid)) {
                if ((get_uid(uid, nuid) == -1) || (*nuid == (uid_t)-1)) {
                        fprintf (stderr,
                                 _("%s: invalid user ID '%s'\n"),