chiark / gitweb /
sysusers: move various user credential validity checks to src/basic/
authorLennart Poettering <lennart@poettering.net>
Thu, 14 Jul 2016 10:23:39 +0000 (12:23 +0200)
committerSven Eden <yamakuzure@gmx.net>
Wed, 5 Jul 2017 06:50:49 +0000 (08:50 +0200)
This way we can reuse them for validating User=/Group= settings in unit files
(to be added in a later commit).

Also, add some tests for them.

src/basic/user-util.c
src/basic/user-util.h

index fbe9f2a969987f86b225bd3a170173c0698aa7d5..2ba5c8575f414cc57257ff192e94e5c9539a814e 100644 (file)
@@ -485,3 +485,94 @@ int take_etc_passwd_lock(const char *root) {
         return fd;
 }
 #endif // 0
         return fd;
 }
 #endif // 0
+
+bool valid_user_group_name(const char *u) {
+        const char *i;
+        long sz;
+
+        /* Checks if the specified name is a valid user/group name. */
+
+        if (isempty(u))
+                return false;
+
+        if (!(u[0] >= 'a' && u[0] <= 'z') &&
+            !(u[0] >= 'A' && u[0] <= 'Z') &&
+            u[0] != '_')
+                return false;
+
+        for (i = u+1; *i; i++) {
+                if (!(*i >= 'a' && *i <= 'z') &&
+                    !(*i >= 'A' && *i <= 'Z') &&
+                    !(*i >= '0' && *i <= '9') &&
+                    *i != '_' &&
+                    *i != '-')
+                        return false;
+        }
+
+        sz = sysconf(_SC_LOGIN_NAME_MAX);
+        assert_se(sz > 0);
+
+        if ((size_t) (i-u) > (size_t) sz)
+                return false;
+
+        if ((size_t) (i-u) > UT_NAMESIZE - 1)
+                return false;
+
+        return true;
+}
+
+bool valid_user_group_name_or_id(const char *u) {
+
+        /* Similar as above, but is also fine with numeric UID/GID specifications, as long as they are in the right
+         * range, and not the invalid user ids. */
+
+        if (isempty(u))
+                return false;
+
+        if (valid_user_group_name(u))
+                return true;
+
+        return parse_uid(u, NULL) >= 0;
+}
+
+bool valid_gecos(const char *d) {
+
+        if (!d)
+                return false;
+
+        if (!utf8_is_valid(d))
+                return false;
+
+        if (string_has_cc(d, NULL))
+                return false;
+
+        /* Colons are used as field separators, and hence not OK */
+        if (strchr(d, ':'))
+                return false;
+
+        return true;
+}
+
+bool valid_home(const char *p) {
+
+        if (isempty(p))
+                return false;
+
+        if (!utf8_is_valid(p))
+                return false;
+
+        if (string_has_cc(p, NULL))
+                return false;
+
+        if (!path_is_absolute(p))
+                return false;
+
+        if (!path_is_safe(p))
+                return false;
+
+        /* Colons are used as field separators, and hence not OK */
+        if (strchr(p, ':'))
+                return false;
+
+        return true;
+}
index 5d1d0abe4d1c960f12eda860335bd90453193e0b..1b5b4f454df861f0c1d24403da4d7129f0fb3976 100644 (file)
@@ -74,3 +74,8 @@ int take_etc_passwd_lock(const char *root);
 static inline bool userns_supported(void) {
         return access("/proc/self/uid_map", F_OK) >= 0;
 }
 static inline bool userns_supported(void) {
         return access("/proc/self/uid_map", F_OK) >= 0;
 }
+
+bool valid_user_group_name(const char *u);
+bool valid_user_group_name_or_id(const char *u);
+bool valid_gecos(const char *d);
+bool valid_home(const char *p);