user-util.c revision 67c7c892b9fcb946792b380a30c4ba704c700934
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering/***
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering This file is part of systemd.
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering Copyright 2010 Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering systemd is free software; you can redistribute it and/or modify it
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering under the terms of the GNU Lesser General Public License as published by
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering (at your option) any later version.
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering systemd is distributed in the hope that it will be useful, but
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering Lesser General Public License for more details.
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering You should have received a copy of the GNU Lesser General Public License
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering***/
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering#include <pwd.h>
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering#include <grp.h>
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering#include "user-util.h"
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering#include "macro.h"
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering#include "util.h"
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering#include "string-util.h"
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering#include "path-util.h"
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poetteringbool uid_is_valid(uid_t uid) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering /* Some libc APIs use UID_INVALID as special placeholder */
b1d5277372a26e5a5b9980174652e1e287ba6b14Lennart Poettering if (uid == (uid_t) UINT32_C(0xFFFFFFFF))
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return false;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering /* A long time ago UIDs where 16bit, hence explicitly avoid the 16bit -1 too */
b1d5277372a26e5a5b9980174652e1e287ba6b14Lennart Poettering if (uid == (uid_t) UINT32_C(0xFFFF))
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return false;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return true;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering}
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d5277372a26e5a5b9980174652e1e287ba6b14Lennart Poetteringint parse_uid(const char *s, uid_t *ret) {
b1d5277372a26e5a5b9980174652e1e287ba6b14Lennart Poettering uint32_t uid = 0;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering int r;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering assert(s);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d5277372a26e5a5b9980174652e1e287ba6b14Lennart Poettering assert_cc(sizeof(uid_t) == sizeof(uint32_t));
b1d5277372a26e5a5b9980174652e1e287ba6b14Lennart Poettering r = safe_atou32(s, &uid);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (r < 0)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return r;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (!uid_is_valid(uid))
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return -ENXIO; /* we return ENXIO instead of EINVAL
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering * here, to make it easy to distuingish
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering * invalid numeric uids invalid
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering * strings. */
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d5277372a26e5a5b9980174652e1e287ba6b14Lennart Poettering if (ret)
b1d5277372a26e5a5b9980174652e1e287ba6b14Lennart Poettering *ret = uid;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return 0;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering}
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poetteringchar* getlogname_malloc(void) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering uid_t uid;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering struct stat st;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (isatty(STDIN_FILENO) && fstat(STDIN_FILENO, &st) >= 0)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering uid = st.st_uid;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering else
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering uid = getuid();
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering return uid_to_name(uid);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering}
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poetteringchar *getusername_malloc(void) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering const char *e;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering e = getenv("USER");
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (e)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return strdup(e);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering return uid_to_name(getuid());
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering}
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poetteringint get_user_creds(
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering const char **username,
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering uid_t *uid, gid_t *gid,
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering const char **home,
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering const char **shell) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering struct passwd *p;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering uid_t u;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering assert(username);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering assert(*username);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering /* We enforce some special rules for uid=0: in order to avoid
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering * NSS lookups for root we hardcode its data. */
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (streq(*username, "root") || streq(*username, "0")) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering *username = "root";
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (uid)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering *uid = 0;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (gid)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering *gid = 0;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (home)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering *home = "/root";
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (shell)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering *shell = "/bin/sh";
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return 0;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (parse_uid(*username, &u) >= 0) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering errno = 0;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering p = getpwuid(u);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering /* If there are multiple users with the same id, make
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering * sure to leave $USER to the configured value instead
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering * of the first occurrence in the database. However if
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering * the uid was configured by a numeric uid, then let's
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering * pick the real username from /etc/passwd. */
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (p)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering *username = p->pw_name;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering } else {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering errno = 0;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering p = getpwnam(*username);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (!p)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return errno > 0 ? -errno : -ESRCH;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering if (uid) {
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering if (!uid_is_valid(p->pw_uid))
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering return -EBADMSG;
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering *uid = p->pw_uid;
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering }
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering if (gid) {
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering if (!gid_is_valid(p->pw_gid))
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering return -EBADMSG;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering *gid = p->pw_gid;
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (home)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering *home = p->pw_dir;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (shell)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering *shell = p->pw_shell;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return 0;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering}
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poetteringint get_group_creds(const char **groupname, gid_t *gid) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering struct group *g;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering gid_t id;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering assert(groupname);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering /* We enforce some special rules for gid=0: in order to avoid
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering * NSS lookups for root we hardcode its data. */
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (streq(*groupname, "root") || streq(*groupname, "0")) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering *groupname = "root";
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (gid)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering *gid = 0;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return 0;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (parse_gid(*groupname, &id) >= 0) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering errno = 0;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering g = getgrgid(id);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (g)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering *groupname = g->gr_name;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering } else {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering errno = 0;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering g = getgrnam(*groupname);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (!g)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return errno > 0 ? -errno : -ESRCH;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering if (gid) {
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering if (!gid_is_valid(g->gr_gid))
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering return -EBADMSG;
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering *gid = g->gr_gid;
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return 0;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering}
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poetteringchar* uid_to_name(uid_t uid) {
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering char *ret;
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering int r;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering /* Shortcut things to avoid NSS lookups */
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (uid == 0)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return strdup("root");
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering if (uid_is_valid(uid)) {
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering long bufsize;
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering if (bufsize <= 0)
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering bufsize = 4096;
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering for (;;) {
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering struct passwd pwbuf, *pw = NULL;
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering _cleanup_free_ char *buf = NULL;
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering buf = malloc(bufsize);
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering if (!buf)
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering return NULL;
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering r = getpwuid_r(uid, &pwbuf, buf, (size_t) bufsize, &pw);
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering if (r == 0 && pw)
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering return strdup(pw->pw_name);
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering if (r != ERANGE)
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering break;
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering bufsize *= 2;
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering }
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering if (asprintf(&ret, UID_FMT, uid) < 0)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return NULL;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering return ret;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering}
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poetteringchar* gid_to_name(gid_t gid) {
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering char *ret;
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering int r;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (gid == 0)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return strdup("root");
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering if (gid_is_valid(gid)) {
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering long bufsize;
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering bufsize = sysconf(_SC_GETGR_R_SIZE_MAX);
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering if (bufsize <= 0)
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering bufsize = 4096;
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering for (;;) {
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering struct group grbuf, *gr = NULL;
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering _cleanup_free_ char *buf = NULL;
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering buf = malloc(bufsize);
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering if (!buf)
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering return NULL;
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering r = getgrgid_r(gid, &grbuf, buf, (size_t) bufsize, &gr);
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering if (r == 0 && gr)
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering return strdup(gr->gr_name);
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering if (r != ERANGE)
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering break;
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering bufsize *= 2;
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering }
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering if (asprintf(&ret, GID_FMT, gid) < 0)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return NULL;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poettering return ret;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering}
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poetteringint in_gid(gid_t gid) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering gid_t *gids;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering int ngroups_max, r, i;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (getgid() == gid)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return 1;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (getegid() == gid)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return 1;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering if (!gid_is_valid(gid))
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering return -EINVAL;
67c7c892b9fcb946792b380a30c4ba704c700934Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering ngroups_max = sysconf(_SC_NGROUPS_MAX);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering assert(ngroups_max > 0);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering gids = alloca(sizeof(gid_t) * ngroups_max);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering r = getgroups(ngroups_max, gids);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (r < 0)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return -errno;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering for (i = 0; i < r; i++)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (gids[i] == gid)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return 1;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return 0;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering}
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poetteringint in_group(const char *name) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering int r;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering gid_t gid;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering r = get_group_creds(&name, &gid);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (r < 0)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return r;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return in_gid(gid);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering}
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poetteringint get_home_dir(char **_h) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering struct passwd *p;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering const char *e;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering char *h;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering uid_t u;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering assert(_h);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering /* Take the user specified one */
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering e = secure_getenv("HOME");
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (e && path_is_absolute(e)) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering h = strdup(e);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (!h)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return -ENOMEM;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering *_h = h;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return 0;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering /* Hardcode home directory for root to avoid NSS */
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering u = getuid();
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (u == 0) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering h = strdup("/root");
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (!h)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return -ENOMEM;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering *_h = h;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return 0;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering /* Check the database... */
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering errno = 0;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering p = getpwuid(u);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (!p)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return errno > 0 ? -errno : -ESRCH;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (!path_is_absolute(p->pw_dir))
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return -EINVAL;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering h = strdup(p->pw_dir);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (!h)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return -ENOMEM;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering *_h = h;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return 0;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering}
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poetteringint get_shell(char **_s) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering struct passwd *p;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering const char *e;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering char *s;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering uid_t u;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering assert(_s);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering /* Take the user specified one */
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering e = getenv("SHELL");
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (e) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering s = strdup(e);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (!s)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return -ENOMEM;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering *_s = s;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return 0;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering /* Hardcode home directory for root to avoid NSS */
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering u = getuid();
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (u == 0) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering s = strdup("/bin/sh");
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (!s)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return -ENOMEM;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering *_s = s;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return 0;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering }
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering /* Check the database... */
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering errno = 0;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering p = getpwuid(u);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (!p)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return errno > 0 ? -errno : -ESRCH;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (!path_is_absolute(p->pw_shell))
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return -EINVAL;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering s = strdup(p->pw_shell);
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (!s)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return -ENOMEM;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering *_s = s;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return 0;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering}
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poetteringint reset_uid_gid(void) {
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (setgroups(0, NULL) < 0)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return -errno;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (setresgid(0, 0, 0) < 0)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return -errno;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering if (setresuid(0, 0, 0) < 0)
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return -errno;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering return 0;
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering}