restrict-access.c revision 30abcf7cbda58078b3bf8b85bbd1e1df6c17d5a3
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (c) 2002-2008 Dovecot authors, see the included COPYING file */
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen#include "lib.h"
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen#include "restrict-access.h"
c96eb61168670cfdd7596baba18856d3f086a093Timo Sirainen#include "env-util.h"
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen#include <stdlib.h>
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen#include <unistd.h>
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen#include <time.h>
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen#include <grp.h>
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainenvoid restrict_access_set_env(const char *user, uid_t uid, gid_t gid,
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen const char *chroot_dir,
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen gid_t first_valid_gid, gid_t last_valid_gid,
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen const char *extra_groups)
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen{
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen if (user != NULL && *user != '\0')
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen env_put(t_strconcat("RESTRICT_USER=", user, NULL));
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen if (chroot_dir != NULL && *chroot_dir != '\0')
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen env_put(t_strconcat("RESTRICT_CHROOT=", chroot_dir, NULL));
ccd83028a34cc6e2b6370eb7ecf1cf25e717c2d3Timo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen env_put(t_strdup_printf("RESTRICT_SETUID=%s", dec2str(uid)));
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen env_put(t_strdup_printf("RESTRICT_SETGID=%s", dec2str(gid)));
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen if (extra_groups != NULL && *extra_groups != '\0') {
39e6fcc3e8b1ccb13087c232cb6bdea04d1a20a4Timo Sirainen env_put(t_strconcat("RESTRICT_SETEXTRAGROUPS=",
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen extra_groups, NULL));
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen }
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (first_valid_gid != 0) {
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen env_put(t_strdup_printf("RESTRICT_GID_FIRST=%s",
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen dec2str(first_valid_gid)));
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen }
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen if (last_valid_gid != 0) {
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen env_put(t_strdup_printf("RESTRICT_GID_LAST=%s",
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen dec2str(last_valid_gid)));
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen }
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen}
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainenstatic gid_t *get_groups_list(unsigned int *gid_count_r)
150e64c376365becf1ec5c9d45912ecb840eea96Timo Sirainen{
150e64c376365becf1ec5c9d45912ecb840eea96Timo Sirainen gid_t *gid_list;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen int ret, gid_count;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if ((gid_count = getgroups(0, NULL)) < 0)
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen i_fatal("getgroups() failed: %m");
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen /* @UNSAFE */
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen gid_list = t_new(gid_t, gid_count);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if ((ret = getgroups(gid_count, gid_list)) < 0)
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen i_fatal("getgroups() failed: %m");
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen *gid_count_r = ret;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen return gid_list;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen}
5afa8e2edf4f313cd56e5909f92f39c3b5b7b4d3Timo Sirainen
5afa8e2edf4f313cd56e5909f92f39c3b5b7b4d3Timo Sirainenstatic bool drop_restricted_groups(gid_t *gid_list, unsigned int *gid_count,
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen bool *have_root_group)
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen{
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen /* @UNSAFE */
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen gid_t first_valid, last_valid;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen const char *env;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen unsigned int i, used;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen env = getenv("RESTRICT_GID_FIRST");
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen first_valid = env == NULL ? 0 : (gid_t)strtoul(env, NULL, 10);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen env = getenv("RESTRICT_GID_LAST");
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen last_valid = env == NULL ? (gid_t)-1 : (gid_t)strtoul(env, NULL, 10);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen for (i = 0, used = 0; i < *gid_count; i++) {
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (gid_list[i] >= first_valid &&
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen (last_valid == (gid_t)-1 || gid_list[i] <= last_valid)) {
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (gid_list[i] == 0)
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen *have_root_group = TRUE;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen gid_list[used++] = gid_list[i];
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen }
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen }
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (*gid_count == used)
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen return FALSE;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen *gid_count = used;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen return TRUE;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen}
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainenstatic gid_t get_group_id(const char *name)
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen{
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen struct group *group;
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (is_numeric(name, '\0'))
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainen return (gid_t)strtoul(name, NULL, 10);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen group = getgrnam(name);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (group == NULL)
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen i_fatal("unknown group name in extra_groups: %s", name);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen return group->gr_gid;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen}
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainenstatic void fix_groups_list(const char *extra_groups, gid_t egid,
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen bool preserve_existing, bool *have_root_group)
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainen{
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen gid_t *gid_list, *gid_list2;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen const char *const *tmp, *empty = NULL;
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainen unsigned int gid_count;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainen tmp = extra_groups == NULL ? &empty :
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen t_strsplit_spaces(extra_groups, ", ");
f2bd9e507b8befdd95a983f86664febf5c19bd95Timo Sirainen
303a87c31cb4aa198326694e231df53a043e63c7Timo Sirainen if (preserve_existing) {
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen gid_list = get_groups_list(&gid_count);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (!drop_restricted_groups(gid_list, &gid_count,
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen have_root_group) &&
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen *tmp == NULL) {
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen /* nothing dropped, no extra groups to grant. */
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen return;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen }
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen } else {
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (egid == (gid_t)-1 && *tmp == NULL) {
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen /* nothing to do */
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen return;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen }
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen /* Some OSes don't like an empty groups list,
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen so use the effective GID as the only one. */
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen gid_list = t_new(gid_t, 2);
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen gid_list[0] = egid != (gid_t)-1 ? egid : getegid();
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen gid_count = 1;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen }
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (*tmp != NULL) {
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen /* @UNSAFE: add extra groups to gids list */
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen gid_list2 = t_new(gid_t, gid_count + str_array_length(tmp));
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen memcpy(gid_list2, gid_list, gid_count * sizeof(gid_t));
39e6fcc3e8b1ccb13087c232cb6bdea04d1a20a4Timo Sirainen for (; *tmp != NULL; tmp++)
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen gid_list2[gid_count++] = get_group_id(*tmp);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen gid_list = gid_list2;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen }
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen if (setgroups(gid_count, gid_list) < 0) {
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen if (errno == EINVAL) {
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen i_fatal("setgroups(%s) failed: Too many extra groups",
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen extra_groups == NULL ? "" : extra_groups);
39e6fcc3e8b1ccb13087c232cb6bdea04d1a20a4Timo Sirainen } else {
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen i_fatal("setgroups() failed: %m");
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen }
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen }
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen}
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainenvoid restrict_access_by_env(bool disallow_root)
bc3698b8892df8003b410daea6f5bbcd20433808Timo Sirainen{
06e72c658de3ce1252594b151313df90acf73271Timo Sirainen const char *env;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen gid_t gid;
06e72c658de3ce1252594b151313df90acf73271Timo Sirainen uid_t uid;
06e72c658de3ce1252594b151313df90acf73271Timo Sirainen bool is_root, have_root_group, preserve_groups = FALSE;
06e72c658de3ce1252594b151313df90acf73271Timo Sirainen
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen is_root = geteuid() == 0;
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainen
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen /* set the primary group */
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen env = getenv("RESTRICT_SETGID");
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen gid = env == NULL || *env == '\0' ? (gid_t)-1 :
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen (gid_t)strtoul(env, NULL, 10);
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen have_root_group = gid == 0;
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen if (gid != (gid_t)-1 && (gid != getgid() || gid != getegid())) {
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen if (setgid(gid) != 0) {
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen i_fatal("setgid(%s) failed with euid=%s, egid=%s: %m",
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen dec2str(gid), dec2str(geteuid()),
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen dec2str(getegid()));
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen }
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen }
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen /* set system user's groups */
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen env = getenv("RESTRICT_USER");
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen if (env != NULL && *env != '\0' && is_root) {
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen if (initgroups(env, gid) < 0) {
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen i_fatal("initgroups(%s, %s) failed: %m",
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen env, dec2str(gid));
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen }
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen preserve_groups = TRUE;
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen }
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen /* add extra groups. if we set system user's groups, drop the
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen restricted groups at the same time. */
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen env = getenv("RESTRICT_SETEXTRAGROUPS");
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen if (is_root) {
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen T_FRAME(
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen fix_groups_list(env, gid, preserve_groups,
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen &have_root_group);
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen );
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen }
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen /* chrooting */
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen env = getenv("RESTRICT_CHROOT");
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen if (env != NULL && *env != '\0') {
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen /* kludge: localtime() must be called before chroot(),
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen or the timezone isn't known */
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen const char *home = getenv("HOME");
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen time_t t = 0;
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen (void)localtime(&t);
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen if (chroot(env) != 0)
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen i_fatal("chroot(%s) failed: %m", env);
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen if (home != NULL) {
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen if (chdir(home) < 0) {
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen i_error("chdir(%s) failed: %m", home);
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen home = NULL;
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen }
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen }
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen if (home == NULL) {
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen if (chdir("/") != 0)
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen i_fatal("chdir(/) failed: %m");
28cd2599128e102198758cf6080588305feb6bcdTimo Sirainen }
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen }
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainen
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen /* uid last */
ccb77e2f63626ec46e5745ef4f38baa8e8e504fcTimo Sirainen env = getenv("RESTRICT_SETUID");
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen uid = env == NULL || *env == '\0' ? 0 : (uid_t)strtoul(env, NULL, 10);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (uid != 0) {
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen if (setuid(uid) != 0) {
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen i_fatal("setuid(%s) failed with euid=%s: %m",
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen dec2str(uid), dec2str(geteuid()));
bd74402ca1a39ec303075fefb1212d7e18a71531Timo Sirainen }
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainen }
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainen
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen /* verify that we actually dropped the privileges */
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (uid != 0 || disallow_root) {
f5a24412980cb19b07cb0cd12dba75886f281875Timo Sirainen if (setuid(0) == 0) {
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen if (uid == 0)
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen i_fatal("Running as root isn't permitted");
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen i_fatal("We couldn't drop root privileges");
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen }
63f36c2b47217fc2dc4ed49cfc1907311d5ed366Timo Sirainen }
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainen env = getenv("RESTRICT_GID_FIRST");
bd74402ca1a39ec303075fefb1212d7e18a71531Timo Sirainen if ((!have_root_group || (env != NULL && atoi(env) != 0)) && uid != 0) {
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainen if (getgid() == 0 || getegid() == 0 || setgid(0) == 0) {
bd74402ca1a39ec303075fefb1212d7e18a71531Timo Sirainen if (gid == 0)
bd74402ca1a39ec303075fefb1212d7e18a71531Timo Sirainen i_fatal("GID 0 isn't permitted");
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen i_fatal("We couldn't drop root group privileges "
c6ae908f6a2313573625d782bdd4e0ff3882c44aTimo Sirainen "(wanted=%s, gid=%s, egid=%s)", dec2str(gid),
c6ae908f6a2313573625d782bdd4e0ff3882c44aTimo Sirainen dec2str(getgid()), dec2str(getegid()));
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainen }
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen }
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainen
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen /* clear the environment, so we don't fail if we get back here */
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen env_put("RESTRICT_USER=");
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainen env_put("RESTRICT_CHROOT=");
17b03c9db961e1c004284907d969eb11b08a795eTimo Sirainen env_put("RESTRICT_SETUID=");
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainen env_put("RESTRICT_SETGID=");
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainen env_put("RESTRICT_SETEXTRAGROUPS=");
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen env_put("RESTRICT_GID_FIRST=");
ef11d3930c3602fc86349a4e3a53442df470b601Timo Sirainen env_put("RESTRICT_GID_LAST=");
c4267cf4c40fb1f866b5958ff122ef836b8c5dfbTimo Sirainen}
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen