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. */
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) {
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);
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();