restrict-access.c revision 752a892ae980f09bd28876715541b0cda86b6229
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2002-2007 Dovecot authors, see the included COPYING file */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "lib.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "restrict-access.h"
7e209b78ca757294dbbc15604c88673b3a6b0c39Timo Sirainen#include "env-util.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include <stdlib.h>
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include <unistd.h>
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen#include <time.h>
7a7d2aa11e46195e2d92d6c337d7e78052a5ce67Timo Sirainen#include <grp.h>
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainenvoid restrict_access_set_env(const char *user, uid_t uid, gid_t gid,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *chroot_dir,
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen gid_t first_valid_gid, gid_t last_valid_gid,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *extra_groups)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (user != NULL && *user != '\0')
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen env_put(t_strconcat("RESTRICT_USER=", user, NULL));
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (chroot_dir != NULL && *chroot_dir != '\0')
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen env_put(t_strconcat("RESTRICT_CHROOT=", chroot_dir, NULL));
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen env_put(t_strdup_printf("RESTRICT_SETUID=%s", dec2str(uid)));
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen env_put(t_strdup_printf("RESTRICT_SETGID=%s", dec2str(gid)));
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (extra_groups != NULL && *extra_groups != '\0') {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen env_put(t_strconcat("RESTRICT_SETEXTRAGROUPS=",
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen extra_groups, NULL));
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen }
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (first_valid_gid != 0) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen env_put(t_strdup_printf("RESTRICT_GID_FIRST=%s",
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen dec2str(first_valid_gid)));
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (last_valid_gid != 0) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen env_put(t_strdup_printf("RESTRICT_GID_LAST=%s",
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen dec2str(last_valid_gid)));
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen}
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic gid_t *get_groups_list(unsigned int *gid_count_r)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen gid_t *gid_list;
6b265a8a9d1ce3b3a8033445e99c9035d62ffbc7Timo Sirainen int ret, gid_count;
6b265a8a9d1ce3b3a8033445e99c9035d62ffbc7Timo Sirainen
6b265a8a9d1ce3b3a8033445e99c9035d62ffbc7Timo Sirainen if ((gid_count = getgroups(0, NULL)) < 0)
6b265a8a9d1ce3b3a8033445e99c9035d62ffbc7Timo Sirainen i_fatal("getgroups() failed: %m");
6b265a8a9d1ce3b3a8033445e99c9035d62ffbc7Timo Sirainen
6b265a8a9d1ce3b3a8033445e99c9035d62ffbc7Timo Sirainen /* @UNSAFE */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen gid_list = t_new(gid_t, gid_count);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if ((ret = getgroups(gid_count, gid_list)) < 0)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_fatal("getgroups() failed: %m");
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen *gid_count_r = ret;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return gid_list;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainenstatic bool drop_restricted_groups(gid_t *gid_list, unsigned int *gid_count,
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen bool *have_root_group)
84078771687fabf75819918f0f3aecdc3ed08b36Timo Sirainen{
84078771687fabf75819918f0f3aecdc3ed08b36Timo Sirainen /* @UNSAFE */
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen gid_t first_valid, last_valid;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen const char *env;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen unsigned int i, used;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen env = getenv("RESTRICT_GID_FIRST");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen first_valid = env == NULL ? 0 : (gid_t)strtoul(env, NULL, 10);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen env = getenv("RESTRICT_GID_LAST");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen last_valid = env == NULL ? (gid_t)-1 : (gid_t)strtoul(env, NULL, 10);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen for (i = 0, used = 0; i < *gid_count; i++) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (gid_list[i] >= first_valid &&
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen (last_valid == (gid_t)-1 || gid_list[i] <= last_valid)) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (gid_list[i] == 0)
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen *have_root_group = TRUE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen gid_list[used++] = gid_list[i];
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
66c0f96d704f09c88dd03b0ee13a3e9711ffe593Timo Sirainen }
66c0f96d704f09c88dd03b0ee13a3e9711ffe593Timo Sirainen if (*gid_count == used)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return FALSE;
66c0f96d704f09c88dd03b0ee13a3e9711ffe593Timo Sirainen *gid_count = used;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return TRUE;
7e209b78ca757294dbbc15604c88673b3a6b0c39Timo Sirainen}
7e209b78ca757294dbbc15604c88673b3a6b0c39Timo Sirainen
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainenstatic gid_t get_group_id(const char *name)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct group *group;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (is_numeric(name, '\0'))
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return (gid_t)strtoul(name, NULL, 10);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen group = getgrnam(name);
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen if (group == NULL)
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen i_fatal("unknown group name in extra_groups: %s", name);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return group->gr_gid;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainenstatic void fix_groups_list(const char *extra_groups, gid_t egid,
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen bool preserve_existing, bool *have_root_group)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen gid_t *gid_list;
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen const char *const *tmp, *empty = NULL;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen unsigned int gid_count;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen tmp = extra_groups == NULL ? &empty :
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen t_strsplit_spaces(extra_groups, ", ");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (preserve_existing) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen gid_list = get_groups_list(&gid_count);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (!drop_restricted_groups(gid_list, &gid_count,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen have_root_group) &&
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen *tmp == NULL) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* nothing dropped, no extra groups to grant. */
834f2b9f60d93e4c7dfc6992e692f5b7213a1b11Timo Sirainen return;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
67770c0874918e3b73bbd1ff75b5ec91790d51dcTimo Sirainen } else {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* Some OSes don't like an empty groups list,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen so use the effective GID as the only one. */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen gid_list = t_new(gid_t, 2);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen gid_list[0] = egid;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen gid_count = 1;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* add extra groups to gids list */
bcdb6c0bd2e7dbb34b306d3d8c2383a7d7654612Timo Sirainen for (; *tmp != NULL; tmp++) {
bcdb6c0bd2e7dbb34b306d3d8c2383a7d7654612Timo Sirainen if (!t_try_realloc(gid_list, (gid_count+1) * sizeof(gid_t)))
bcdb6c0bd2e7dbb34b306d3d8c2383a7d7654612Timo Sirainen i_unreached();
bcdb6c0bd2e7dbb34b306d3d8c2383a7d7654612Timo Sirainen gid_list[gid_count++] = get_group_id(*tmp);
bcdb6c0bd2e7dbb34b306d3d8c2383a7d7654612Timo Sirainen }
bcdb6c0bd2e7dbb34b306d3d8c2383a7d7654612Timo Sirainen if (setgroups(gid_count, gid_list) < 0) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (errno == EINVAL) {
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen i_fatal("setgroups(%s) failed: Too many extra groups",
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen extra_groups == NULL ? "" : extra_groups);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen } else {
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen i_fatal("setgroups() failed: %m");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
c3001a6476bae22fc0f55abc73014211b0775d98Timo Sirainen }
c3001a6476bae22fc0f55abc73014211b0775d98Timo Sirainen}
c3001a6476bae22fc0f55abc73014211b0775d98Timo Sirainen
c3001a6476bae22fc0f55abc73014211b0775d98Timo Sirainenvoid restrict_access_by_env(bool disallow_root)
899ebb8ba3fbebaafd3e431943283719ce2b106dTimo Sirainen{
899ebb8ba3fbebaafd3e431943283719ce2b106dTimo Sirainen const char *env;
899ebb8ba3fbebaafd3e431943283719ce2b106dTimo Sirainen gid_t gid;
899ebb8ba3fbebaafd3e431943283719ce2b106dTimo Sirainen uid_t uid;
899ebb8ba3fbebaafd3e431943283719ce2b106dTimo Sirainen bool is_root, have_root_group, preserve_groups = FALSE;
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen is_root = geteuid() == 0;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
834f2b9f60d93e4c7dfc6992e692f5b7213a1b11Timo Sirainen /* set the primary group */
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen env = getenv("RESTRICT_SETGID");
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen gid = env == NULL || *env == '\0' ? (gid_t)-1 :
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen (gid_t)strtoul(env, NULL, 10);
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen have_root_group = gid == 0;
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen if (gid != (gid_t)-1 && (gid != getgid() || gid != getegid())) {
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen if (setgid(gid) != 0) {
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen i_fatal("setgid(%s) failed with euid=%s, egid=%s: %m",
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen dec2str(gid), dec2str(geteuid()),
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen dec2str(getegid()));
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* set system user's groups */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen env = getenv("RESTRICT_USER");
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen if (env != NULL && *env != '\0' && is_root) {
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen if (initgroups(env, gid) < 0) {
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen i_fatal("initgroups(%s, %s) failed: %m",
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen env, dec2str(gid));
b8835b8a21c617ceb82ddc5a176243faf36aa8f7Timo Sirainen }
b8835b8a21c617ceb82ddc5a176243faf36aa8f7Timo Sirainen preserve_groups = TRUE;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen }
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen /* add extra groups. if we set system user's groups, drop the
b8835b8a21c617ceb82ddc5a176243faf36aa8f7Timo Sirainen restricted groups at the same time. */
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen env = getenv("RESTRICT_SETEXTRAGROUPS");
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen if (is_root) {
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen T_FRAME(
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen fix_groups_list(env, gid, preserve_groups,
b8835b8a21c617ceb82ddc5a176243faf36aa8f7Timo Sirainen &have_root_group);
b8835b8a21c617ceb82ddc5a176243faf36aa8f7Timo Sirainen );
b8835b8a21c617ceb82ddc5a176243faf36aa8f7Timo Sirainen }
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
b8835b8a21c617ceb82ddc5a176243faf36aa8f7Timo Sirainen /* chrooting */
b8835b8a21c617ceb82ddc5a176243faf36aa8f7Timo Sirainen env = getenv("RESTRICT_CHROOT");
b8835b8a21c617ceb82ddc5a176243faf36aa8f7Timo Sirainen if (env != NULL && *env != '\0') {
b8835b8a21c617ceb82ddc5a176243faf36aa8f7Timo Sirainen /* kludge: localtime() must be called before chroot(),
b8835b8a21c617ceb82ddc5a176243faf36aa8f7Timo Sirainen or the timezone isn't known */
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen const char *home = getenv("HOME");
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen time_t t = 0;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen (void)localtime(&t);
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen if (chroot(env) != 0)
834f2b9f60d93e4c7dfc6992e692f5b7213a1b11Timo Sirainen i_fatal("chroot(%s) failed: %m", env);
834f2b9f60d93e4c7dfc6992e692f5b7213a1b11Timo Sirainen
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen if (home != NULL) {
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen if (chdir(home) < 0) {
834f2b9f60d93e4c7dfc6992e692f5b7213a1b11Timo Sirainen i_error("chdir(%s) failed: %m", home);
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen home = NULL;
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen }
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen }
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen if (home == NULL) {
834f2b9f60d93e4c7dfc6992e692f5b7213a1b11Timo Sirainen if (chdir("/") != 0)
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen i_fatal("chdir(/) failed: %m");
834f2b9f60d93e4c7dfc6992e692f5b7213a1b11Timo Sirainen }
834f2b9f60d93e4c7dfc6992e692f5b7213a1b11Timo Sirainen }
834f2b9f60d93e4c7dfc6992e692f5b7213a1b11Timo Sirainen
834f2b9f60d93e4c7dfc6992e692f5b7213a1b11Timo Sirainen /* uid last */
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen env = getenv("RESTRICT_SETUID");
834f2b9f60d93e4c7dfc6992e692f5b7213a1b11Timo Sirainen uid = env == NULL || *env == '\0' ? 0 : (uid_t)strtoul(env, NULL, 10);
834f2b9f60d93e4c7dfc6992e692f5b7213a1b11Timo Sirainen if (uid != 0) {
834f2b9f60d93e4c7dfc6992e692f5b7213a1b11Timo Sirainen if (setuid(uid) != 0) {
834f2b9f60d93e4c7dfc6992e692f5b7213a1b11Timo Sirainen i_fatal("setuid(%s) failed with euid=%s: %m",
834f2b9f60d93e4c7dfc6992e692f5b7213a1b11Timo Sirainen dec2str(uid), dec2str(geteuid()));
834f2b9f60d93e4c7dfc6992e692f5b7213a1b11Timo Sirainen }
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen }
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen /* verify that we actually dropped the privileges */
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen if (uid != 0 || disallow_root) {
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen if (setuid(0) == 0) {
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen if (uid == 0)
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen i_fatal("Running as root isn't permitted");
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen i_fatal("We couldn't drop root privileges");
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen }
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen }
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen env = getenv("RESTRICT_GID_FIRST");
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen if ((!have_root_group || (env != NULL && atoi(env) != 0)) && uid != 0) {
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen if (getgid() == 0 || getegid() == 0 || setgid(0) == 0) {
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen if (gid == 0)
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen i_fatal("GID 0 isn't permitted");
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen i_fatal("We couldn't drop root group privileges "
7f3b826a89bcb7a72759912e99f574b28309fe1bTimo Sirainen "(wanted=%s, gid=%s, egid=%s)", dec2str(gid),
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen dec2str(getgid()), dec2str(getegid()));
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen }
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen }
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen
834f2b9f60d93e4c7dfc6992e692f5b7213a1b11Timo Sirainen /* clear the environment, so we don't fail if we get back here */
834f2b9f60d93e4c7dfc6992e692f5b7213a1b11Timo Sirainen env_put("RESTRICT_USER=");
834f2b9f60d93e4c7dfc6992e692f5b7213a1b11Timo Sirainen env_put("RESTRICT_CHROOT=");
834f2b9f60d93e4c7dfc6992e692f5b7213a1b11Timo Sirainen env_put("RESTRICT_SETUID=");
834f2b9f60d93e4c7dfc6992e692f5b7213a1b11Timo Sirainen env_put("RESTRICT_SETGID=");
834f2b9f60d93e4c7dfc6992e692f5b7213a1b11Timo Sirainen env_put("RESTRICT_SETEXTRAGROUPS=");
834f2b9f60d93e4c7dfc6992e692f5b7213a1b11Timo Sirainen env_put("RESTRICT_GID_FIRST=");
834f2b9f60d93e4c7dfc6992e692f5b7213a1b11Timo Sirainen env_put("RESTRICT_GID_LAST=");
834f2b9f60d93e4c7dfc6992e692f5b7213a1b11Timo Sirainen}
834f2b9f60d93e4c7dfc6992e692f5b7213a1b11Timo Sirainen