X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fbasic%2Fuser-util.c;h=332e1c6a9c7bc6a4b640208f70958a45004fa3c5;hb=f082899f180431f04553e4ee3b0968020ef59188;hp=2ba5c8575f414cc57257ff192e94e5c9539a814e;hpb=599f015c68718f04ee1946fc263aad8aaa614072;p=elogind.git diff --git a/src/basic/user-util.c b/src/basic/user-util.c index 2ba5c8575..332e1c6a9 100644 --- a/src/basic/user-util.c +++ b/src/basic/user-util.c @@ -29,19 +29,25 @@ #include #include #include +#include -#include "missing.h" #include "alloc-util.h" #include "fd-util.h" -#include "formats-util.h" +#include "fileio.h" +#include "format-util.h" #include "macro.h" +#include "missing.h" #include "parse-util.h" #include "path-util.h" #include "string-util.h" +#include "strv.h" #include "user-util.h" +#include "utf8.h" bool uid_is_valid(uid_t uid) { + /* Also see POSIX IEEE Std 1003.1-2008, 2016 Edition, 3.436. */ + /* Some libc APIs use UID_INVALID as special placeholder */ if (uid == (uid_t) UINT32_C(0xFFFFFFFF)) return false; @@ -175,6 +181,36 @@ int get_user_creds( return 0; } +#if 0 /// UNNEEDED by elogind +int get_user_creds_clean( + const char **username, + uid_t *uid, gid_t *gid, + const char **home, + const char **shell) { + + int r; + + /* Like get_user_creds(), but resets home/shell to NULL if they don't contain anything relevant. */ + + r = get_user_creds(username, uid, gid, home, shell); + if (r < 0) + return r; + + if (shell && + (isempty(*shell) || PATH_IN_SET(*shell, + "/bin/nologin", + "/sbin/nologin", + "/usr/bin/nologin", + "/usr/sbin/nologin"))) + *shell = NULL; + + if (home && + (isempty(*home) || path_equal(*home, "/"))) + *home = NULL; + + return 0; +} + int get_group_creds(const char **groupname, gid_t *gid) { struct group *g; gid_t id; @@ -216,6 +252,7 @@ int get_group_creds(const char **groupname, gid_t *gid) { return 0; } +#endif // 0 char* uid_to_name(uid_t uid) { char *ret; @@ -431,9 +468,11 @@ int get_shell(char **_s) { #endif // 0 int reset_uid_gid(void) { + int r; - if (setgroups(0, NULL) < 0) - return -errno; + r = maybe_setgroups(0, NULL); + if (r < 0) + return r; if (setresgid(0, 0, 0) < 0) return -errno; @@ -490,7 +529,15 @@ bool valid_user_group_name(const char *u) { const char *i; long sz; - /* Checks if the specified name is a valid user/group name. */ + /* Checks if the specified name is a valid user/group name. Also see POSIX IEEE Std 1003.1-2008, 2016 Edition, + * 3.437. We are a bit stricter here however. Specifically we deviate from POSIX rules: + * + * - We don't allow any dots (this would break chown syntax which permits dots as user/group name separator) + * - We require that names fit into the appropriate utmp field + * - We don't allow empty user names + * + * Note that other systems are even more restrictive, and don't permit underscores or uppercase characters. + */ if (isempty(u)) return false; @@ -576,3 +623,32 @@ bool valid_home(const char *p) { return true; } + +int maybe_setgroups(size_t size, const gid_t *list) { + int r; + + /* Check if setgroups is allowed before we try to drop all the auxiliary groups */ + if (size == 0) { /* Dropping all aux groups? */ + _cleanup_free_ char *setgroups_content = NULL; + bool can_setgroups; + + r = read_one_line_file("/proc/self/setgroups", &setgroups_content); + if (r == -ENOENT) + /* Old kernels don't have /proc/self/setgroups, so assume we can use setgroups */ + can_setgroups = true; + else if (r < 0) + return r; + else + can_setgroups = streq(setgroups_content, "allow"); + + if (!can_setgroups) { + log_debug("Skipping setgroups(), /proc/self/setgroups is set to 'deny'"); + return 0; + } + } + + if (setgroups(size, list) < 0) + return -errno; + + return 0; +}