]> git.ipfire.org Git - thirdparty/shadow.git/commitdiff
src/chfn.c: Do not allow the 'slop' fields to appear before any non-slop gecos fields
authorAlejandro Colomar <alx@kernel.org>
Fri, 18 Jul 2025 21:53:30 +0000 (23:53 +0200)
committerSerge Hallyn <serge@hallyn.com>
Sat, 9 Aug 2025 23:00:36 +0000 (18:00 -0500)
According to the Wikipedia page for the 'Gecos field', the "typical"
format for the GECOS field is a comma-delimited list with this order:

1)  User's full name (or application name, if the account is for a program)
2)  Building and room number or contact person
3)  Office telephone number
4)  Home telephone number
5+) Any other contact information (pager number, fax, external e-mail address, etc.)

But our code supported the "other contact information", which we call
slop, and which is composed of an arbitrary number of key=value fields,
to appear before any of the other 4 fields.

This seems to be undocumented, and none of the documentation I've found
for the GECOS field in any systems I checked claims to support this.
By removing support for those, we can significantly simplify the
copy_field() function, which was quite unreadable.

After this patch, the GECOS field is treated as a CSV, blindly copying
the fields as they appear, where the first 4 fields are as specified
above, and anything after them is the slop (5+ fields, any other contact
information).

Signed-off-by: Alejandro Colomar <alx@kernel.org>
src/chfn.c

index 2fb0825df7c85bd0d19a5cf06e58241186d1ecf7..9d7a2343fd67de1117a89a2cc379e6a5abc4c5f3 100644 (file)
@@ -214,33 +214,15 @@ static void new_fields (void)
  *
  *     in - the current GECOS field
  *     out - where to copy the field to
- *     extra - fields with '=' get copied here
  */
-static char *copy_field (char *in, char *out, char *extra)
+static char *copy_field(char *in, char *out)
 {
-       char  *next = NULL;
+       char  *next;
 
-       while (NULL != in) {
-               const char  *f;
+       next = stpsep(in, ",");
 
-               f = in;
-               next = stpsep(in, ",");
-
-               if (strchr(f, '=') == NULL)
-                       break;
-
-               if (NULL != extra) {
-                       if (!streq(extra, "")) {
-                               strcat (extra, ",");
-                       }
-
-                       strcat(extra, f);
-               }
-               in = next;
-       }
-       if ((NULL != in) && (NULL != out)) {
-               strcpy (out, in);
-       }
+       if (out != NULL)
+               strcpy(out, in);
 
        return next;
 }
@@ -521,39 +503,35 @@ static void get_old_fields (const char *gecos)
         * Now get the full name. It is the first comma separated field in
         * the GECOS field.
         */
-       cp = copy_field (old_gecos, fflg ? NULL : fullnm, slop);
+       cp = copy_field(old_gecos, fflg ? NULL : fullnm);
 
        /*
         * Now get the room number. It is the next comma separated field,
         * if there is indeed one.
         */
        if (NULL != cp) {
-               cp = copy_field (cp, rflg ? NULL : roomno, slop);
+               cp = copy_field(cp, rflg ? NULL : roomno);
        }
 
        /*
         * Now get the work phone number. It is the third field.
         */
        if (NULL != cp) {
-               cp = copy_field (cp, wflg ? NULL : workph, slop);
+               cp = copy_field(cp, wflg ? NULL : workph);
        }
 
        /*
         * Now get the home phone number. It is the fourth field.
         */
        if (NULL != cp) {
-               cp = copy_field (cp, hflg ? NULL : homeph, slop);
+               cp = copy_field(cp, hflg ? NULL : homeph);
        }
 
        /*
         * Anything left over is "slop".
         */
        if ((NULL != cp) && !oflg) {
-               if (!streq(slop, "")) {
-                       strcat (slop, ",");
-               }
-
-               strcat (slop, cp);
+               strcpy(slop, cp);
        }
 }