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
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <alloca.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <errno.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <fcntl.h>
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering#include <grp.h>
cf0fbc49e67b55f8d346fc94de28c90113505297Thomas Hindoe Paaboel Andersen#include <pwd.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <stddef.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <stdint.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <stdio.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <stdlib.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <string.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <sys/stat.h>
11c3a36649e5e5e77db499c92f3cdcbd619efd3aThomas Hindoe Paaboel Andersen#include <unistd.h>
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "alloc-util.h"
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering#include "fd-util.h"
93cc7779e0c121b75183920173f37cd1ee9d59cfThomas Hindoe Paaboel Andersen#include "formats-util.h"
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering#include "macro.h"
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering#include "parse-util.h"
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering#include "path-util.h"
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering#include "string-util.h"
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering#include "user-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
ba60af86aa593ab4efe87babac73ec9e3af194c7Zbigniew Jędrzejewski-Szmek * invalid numeric uids from 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}
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poetteringint take_etc_passwd_lock(const char *root) {
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering struct flock flock = {
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering .l_type = F_WRLCK,
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering .l_whence = SEEK_SET,
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering .l_start = 0,
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering .l_len = 0,
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering };
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering const char *path;
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering int fd, r;
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering /* This is roughly the same as lckpwdf(), but not as awful. We
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering * don't want to use alarm() and signals, hence we implement
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering * our own trivial version of this.
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering *
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering * Note that shadow-utils also takes per-database locks in
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering * addition to lckpwdf(). However, we don't given that they
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering * are redundant as they they invoke lckpwdf() first and keep
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering * it during everything they do. The per-database locks are
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering * awfully racy, and thus we just won't do them. */
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering if (root)
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering path = prefix_roota(root, "/etc/.pwd.lock");
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering else
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering path = "/etc/.pwd.lock";
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0600);
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering if (fd < 0)
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering return -errno;
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering r = fcntl(fd, F_SETLKW, &flock);
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering if (r < 0) {
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering safe_close(fd);
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering return -errno;
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering }
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering return fd;
e929bee09ab8000e87b7e825ed3a78d73ecdd7f0Lennart Poettering}