]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
user-util: add mangle_gecos() call for turning strings into fields suitable as GECOS...
authorLennart Poettering <lennart@poettering.net>
Thu, 6 Aug 2020 14:46:18 +0000 (16:46 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 7 Aug 2020 15:36:11 +0000 (17:36 +0200)
src/basic/user-util.c
src/basic/user-util.h
src/test/test-user-util.c

index 8115065b5eca119a8515a776cb27428ee9d76b18..0e96a75797a95fdb9412ee7acada798e1ff8d7c0 100644 (file)
@@ -863,6 +863,37 @@ bool valid_gecos(const char *d) {
         return true;
 }
 
+char *mangle_gecos(const char *d) {
+        char *mangled;
+
+        /* Makes sure the provided string becomes valid as a GEGOS field, by dropping bad chars. glibc's
+         * putwent() only changes \n and : to spaces. We do more: replace all CC too, and remove invalid
+         * UTF-8 */
+
+        mangled = strdup(d);
+        if (!mangled)
+                return NULL;
+
+        for (char *i = mangled; *i; i++) {
+                int len;
+
+                if ((uint8_t) *i < (uint8_t) ' ' || *i == ':') {
+                        *i = ' ';
+                        continue;
+                }
+
+                len = utf8_encoded_valid_unichar(i, (size_t) -1);
+                if (len < 0) {
+                        *i = ' ';
+                        continue;
+                }
+
+                i += len - 1;
+        }
+
+        return mangled;
+}
+
 bool valid_home(const char *p) {
         /* Note that this function is also called by valid_shell(), any
          * changes must account for that. */
index 1f267d21a3f3f188af142b3f7e2925b9626fd450..7c142dd1e66e6521f91a2cf73eb247a755870257 100644 (file)
@@ -105,6 +105,7 @@ typedef enum ValidUserFlags {
 
 bool valid_user_group_name(const char *u, ValidUserFlags flags);
 bool valid_gecos(const char *d);
+char *mangle_gecos(const char *d);
 bool valid_home(const char *p);
 
 static inline bool valid_shell(const char *p) {
index c9bff941be17673ab4d327057026a201e83511ea..306d08a2824cb9640075a6ed385da9796da19610 100644 (file)
@@ -452,6 +452,25 @@ static void test_parse_uid_range(void) {
         assert_se(parse_uid_range(" 01", &a, &b) == -EINVAL && a == 4 && b == 5);
 }
 
+static void test_mangle_gecos_one(const char *input, const char *expected) {
+        _cleanup_free_ char *p = NULL;
+
+        assert_se(p = mangle_gecos(input));
+        assert_se(streq(p, expected));
+        assert_se(valid_gecos(p));
+}
+
+static void test_mangle_gecos(void) {
+        test_mangle_gecos_one("", "");
+        test_mangle_gecos_one("root", "root");
+        test_mangle_gecos_one("wuff\nwuff", "wuff wuff");
+        test_mangle_gecos_one("wuff:wuff", "wuff wuff");
+        test_mangle_gecos_one("wuff\r\n:wuff", "wuff   wuff");
+        test_mangle_gecos_one("\n--wüff-wäff-wöff::", " --wüff-wäff-wöff  ");
+        test_mangle_gecos_one("\xc3\x28", " (");
+        test_mangle_gecos_one("\xe2\x28\xa1", " ( ");
+}
+
 int main(int argc, char *argv[]) {
         test_uid_to_name_one(0, "root");
         test_uid_to_name_one(UID_NOBODY, NOBODY_USER_NAME);
@@ -482,6 +501,7 @@ int main(int argc, char *argv[]) {
         test_valid_user_group_name_or_numeric_relaxed();
         test_valid_user_group_name_or_numeric();
         test_valid_gecos();
+        test_mangle_gecos();
         test_valid_home();
 
         test_make_salt();