restrict-access.c revision d7b81a1e17f5b115cb1b36bf6c6f64295e357dc2
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2002-2010 Dovecot authors, see the included COPYING file */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen#define _GNU_SOURCE /* setresgid() */
46552a931924c2d743f045e95b08c3ce6beda91aTimo Sirainen#include <stdio.h> /* for AIX */
c5f932968281763df360b9c97cef60f5f80d5e3dTimo Sirainen#include <sys/types.h>
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen#include <unistd.h>
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen#include "lib.h"
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen#include "restrict-access.h"
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen#include "env-util.h"
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen#include <stdlib.h>
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen#include <time.h>
f29756821a4c6b12b73e4a2a3e1c230117a43773Timo Sirainen#include <pwd.h>
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen#include <grp.h>
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen#ifdef HAVE_PR_SET_DUMPABLE
53dfcefa9440a49d703e49193819a79be99c9ba6Timo Sirainen# include <sys/prctl.h>
f0d93763f210ecdb85a115fdd0210a16cfc5ff5cTimo Sirainen#endif
53dfcefa9440a49d703e49193819a79be99c9ba6Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic gid_t process_primary_gid = (gid_t)-1;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic gid_t process_privileged_gid = (gid_t)-1;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic bool process_using_priv_gid = FALSE;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainenstatic char *chroot_dir = NULL;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainenvoid restrict_access_init(struct restrict_access_settings *set)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen{
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen memset(set, 0, sizeof(*set));
2e78f05b11df23ec2731afaf8f19d5b5240cb29fTimo Sirainen
2e78f05b11df23ec2731afaf8f19d5b5240cb29fTimo Sirainen set->uid = (uid_t)-1;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen set->gid = (gid_t)-1;
d1e7425048c61d71f41f737ba947687198842dc2Timo Sirainen set->privileged_gid = (gid_t)-1;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen}
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic const char *get_uid_str(uid_t uid)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen{
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen const struct passwd *pw;
660b99a7059824676b2b8d6f79b8e15d47df25a2Timo Sirainen const char *ret;
660b99a7059824676b2b8d6f79b8e15d47df25a2Timo Sirainen int old_errno = errno;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen pw = getpwuid(uid);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (pw == NULL)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen ret = dec2str(uid);
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen else
b9c76fe9d9ca194816606342da1ddbd9be6bc8abTimo Sirainen ret = t_strdup_printf("%s(%s)", dec2str(uid), pw->pw_name);
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen errno = old_errno;
b9c76fe9d9ca194816606342da1ddbd9be6bc8abTimo Sirainen return ret;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen}
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic const char *get_gid_str(gid_t gid)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen{
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen const struct group *group;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen const char *ret;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen int old_errno = errno;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen group = getgrgid(gid);
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen if (group == NULL)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen ret = dec2str(gid);
b9c76fe9d9ca194816606342da1ddbd9be6bc8abTimo Sirainen else
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen ret = t_strdup_printf("%s(%s)", dec2str(gid), group->gr_name);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen errno = old_errno;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return ret;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen}
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic void restrict_init_groups(gid_t primary_gid, gid_t privileged_gid)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen{
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (privileged_gid == (gid_t)-1) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (primary_gid == getgid() && primary_gid == getegid()) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* everything is already set */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (setgid(primary_gid) != 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen i_fatal("setgid(%s) failed with "
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen "euid=%s, gid=%s, egid=%s: %m "
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen "(This binary should probably be called with "
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen "process group set to %s instead of %s)",
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen get_gid_str(primary_gid), get_uid_str(geteuid()),
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen get_gid_str(getgid()), get_gid_str(getegid()),
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen get_gid_str(primary_gid), get_uid_str(geteuid()));
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (getegid() != 0 && primary_gid == getgid() &&
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen primary_gid == getegid()) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* privileged_gid is hopefully in saved ID. if not,
ca843e046e98b12f4730f4b87ee2e1a659c26e78Timo Sirainen there's nothing we can do about it. */
ca843e046e98b12f4730f4b87ee2e1a659c26e78Timo Sirainen return;
ca843e046e98b12f4730f4b87ee2e1a659c26e78Timo Sirainen }
ca843e046e98b12f4730f4b87ee2e1a659c26e78Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen#ifdef HAVE_SETRESGID
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (setresgid(primary_gid, primary_gid, privileged_gid) != 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen i_fatal("setresgid(%s,%s,%s) failed with euid=%s: %m",
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen get_gid_str(primary_gid), get_gid_str(primary_gid),
e7dd5065d21c569e5e6ddd713bd345dadd1cf51dTimo Sirainen get_gid_str(privileged_gid), get_uid_str(geteuid()));
e7dd5065d21c569e5e6ddd713bd345dadd1cf51dTimo Sirainen }
d694a52bce62c52080c3f87a56dcf77030fd2712Timo Sirainen#else
d694a52bce62c52080c3f87a56dcf77030fd2712Timo Sirainen if (geteuid() == 0) {
009217abb57a24a4076092e8e4e165545747839eStephan Bosch /* real, effective, saved -> privileged_gid */
009217abb57a24a4076092e8e4e165545747839eStephan Bosch if (setgid(privileged_gid) < 0) {
009217abb57a24a4076092e8e4e165545747839eStephan Bosch i_fatal("setgid(%s) failed: %m",
009217abb57a24a4076092e8e4e165545747839eStephan Bosch get_gid_str(privileged_gid));
009217abb57a24a4076092e8e4e165545747839eStephan Bosch }
009217abb57a24a4076092e8e4e165545747839eStephan Bosch }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* real, effective -> primary_gid
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen saved -> keep */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (setregid(primary_gid, primary_gid) != 0) {
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch i_fatal("setregid(%s,%s) failed with euid=%s: %m",
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch get_gid_str(primary_gid), get_gid_str(privileged_gid),
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch get_uid_str(geteuid()));
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch }
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch#endif
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch}
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Boschgid_t *restrict_get_groups_list(unsigned int *gid_count_r)
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch{
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch gid_t *gid_list;
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch int ret, gid_count;
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen if ((gid_count = getgroups(0, NULL)) < 0)
ab281fc992907b6cf6c730f672dc3aa4c6685015Timo Sirainen i_fatal("getgroups() failed: %m");
ab281fc992907b6cf6c730f672dc3aa4c6685015Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* @UNSAFE */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen gid_list = t_new(gid_t, gid_count);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if ((ret = getgroups(gid_count, gid_list)) < 0)
1bf5c6c20f3d51f13d3240cfb46e471074c86276Timo Sirainen i_fatal("getgroups() failed: %m");
1bf5c6c20f3d51f13d3240cfb46e471074c86276Timo Sirainen
1bf5c6c20f3d51f13d3240cfb46e471074c86276Timo Sirainen *gid_count_r = ret;
1bf5c6c20f3d51f13d3240cfb46e471074c86276Timo Sirainen return gid_list;
5a250816ffc4cc5db203f9410ea99b6601c7b91aTimo Sirainen}
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
1bf5c6c20f3d51f13d3240cfb46e471074c86276Timo Sirainenstatic void drop_restricted_groups(const struct restrict_access_settings *set,
1bf5c6c20f3d51f13d3240cfb46e471074c86276Timo Sirainen gid_t *gid_list, unsigned int *gid_count,
1bf5c6c20f3d51f13d3240cfb46e471074c86276Timo Sirainen bool *have_root_group)
1bf5c6c20f3d51f13d3240cfb46e471074c86276Timo Sirainen{
8ce3071e80b9973230048ecadfcb073fb82cc69fTimo Sirainen /* @UNSAFE */
8ce3071e80b9973230048ecadfcb073fb82cc69fTimo Sirainen unsigned int i, used;
8ce3071e80b9973230048ecadfcb073fb82cc69fTimo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen for (i = 0, used = 0; i < *gid_count; i++) {
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk if (gid_list[i] >= set->first_valid_gid &&
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen (set->last_valid_gid == 0 ||
2e2a1d720ed53490e8e5c5031e773d395bd5683dTimo Sirainen gid_list[i] <= set->last_valid_gid)) {
5a250816ffc4cc5db203f9410ea99b6601c7b91aTimo Sirainen if (gid_list[i] == 0)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen *have_root_group = TRUE;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen gid_list[used++] = gid_list[i];
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen *gid_count = used;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen}
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic gid_t get_group_id(const char *name)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen{
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct group *group;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (is_numeric(name, '\0'))
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return (gid_t)strtoul(name, NULL, 10);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen group = getgrnam(name);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (group == NULL)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen i_fatal("unknown group name in extra_groups: %s", name);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return group->gr_gid;
b8afdaa1bffe2f27cd4b02bf3bfbd2d297c8e648Timo Sirainen}
b8afdaa1bffe2f27cd4b02bf3bfbd2d297c8e648Timo Sirainen
b8afdaa1bffe2f27cd4b02bf3bfbd2d297c8e648Timo Sirainenstatic void fix_groups_list(const struct restrict_access_settings *set,
b8afdaa1bffe2f27cd4b02bf3bfbd2d297c8e648Timo Sirainen bool preserve_existing, bool *have_root_group)
b8afdaa1bffe2f27cd4b02bf3bfbd2d297c8e648Timo Sirainen{
b8afdaa1bffe2f27cd4b02bf3bfbd2d297c8e648Timo Sirainen gid_t gid, *gid_list, *gid_list2;
b8afdaa1bffe2f27cd4b02bf3bfbd2d297c8e648Timo Sirainen const char *const *tmp, *empty = NULL;
b8afdaa1bffe2f27cd4b02bf3bfbd2d297c8e648Timo Sirainen unsigned int i, gid_count;
b8afdaa1bffe2f27cd4b02bf3bfbd2d297c8e648Timo Sirainen bool add_primary_gid;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* if we're using a privileged GID, we can temporarily drop our
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen effective GID. we still want to be able to use its privileges,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen so add it to supplementary groups. */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen add_primary_gid = process_privileged_gid != (gid_t)-1;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen tmp = set->extra_groups == NULL ? &empty :
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen t_strsplit_spaces(set->extra_groups, ", ");
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (preserve_existing) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen gid_list = restrict_get_groups_list(&gid_count);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen drop_restricted_groups(set, gid_list, &gid_count,
ec23e16ed879e289d12c6e1a5f9745dd3979004aTimo Sirainen have_root_group);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* see if the list already contains the primary GID */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen for (i = 0; i < gid_count; i++) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (gid_list[i] == process_primary_gid) {
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen add_primary_gid = FALSE;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen break;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen }
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen }
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen } else {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen gid_list = NULL;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen gid_count = 0;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (gid_count == 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* Some OSes don't like an empty groups list,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen so use the primary GID as the only one. */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen gid_list = t_new(gid_t, 2);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen gid_list[0] = process_primary_gid;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen gid_count = 1;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen add_primary_gid = FALSE;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (*tmp != NULL || add_primary_gid) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* @UNSAFE: add extra groups and/or primary GID to gids list */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen gid_list2 = t_new(gid_t, gid_count + str_array_length(tmp) + 1);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen memcpy(gid_list2, gid_list, gid_count * sizeof(gid_t));
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen for (; *tmp != NULL; tmp++) {
cbaac1e9a69099a2c25e09b1db19bcbf9037e342Timo Sirainen gid = get_group_id(*tmp);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (gid != process_primary_gid)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen gid_list2[gid_count++] = gid;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (add_primary_gid)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen gid_list2[gid_count++] = process_primary_gid;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen gid_list = gid_list2;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen if (setgroups(gid_count, gid_list) < 0) {
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen if (errno == EINVAL) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen i_fatal("setgroups(%s) failed: Too many extra groups",
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen set->extra_groups == NULL ? "" :
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen set->extra_groups);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen } else {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen i_fatal("setgroups() failed: %m");
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
660b99a7059824676b2b8d6f79b8e15d47df25a2Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen}
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenvoid restrict_access(const struct restrict_access_settings *set,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen const char *home, bool disallow_root)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen{
e911b23f3e05308df9b98b1a3fdaf72e4302d8fdTimo Sirainen bool is_root, have_root_group, preserve_groups = FALSE;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen bool allow_root_gid;
77f1da4b5e2b800197d8db548235497d5e9d6a4fTimo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen is_root = geteuid() == 0;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* set the primary/privileged group */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen process_primary_gid = set->gid;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen process_privileged_gid = set->privileged_gid;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen have_root_group = process_primary_gid == 0;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (process_primary_gid != (gid_t)-1 ||
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen process_privileged_gid != (gid_t)-1) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (process_primary_gid == (gid_t)-1)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen process_primary_gid = getegid();
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen restrict_init_groups(process_primary_gid,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen process_privileged_gid);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen } else {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (process_primary_gid == (gid_t)-1)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen process_primary_gid = getegid();
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* set system user's groups */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (set->system_groups_user != NULL && is_root) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (initgroups(set->system_groups_user,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen process_primary_gid) < 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen i_fatal("initgroups(%s, %s) failed: %m",
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen set->system_groups_user,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen get_gid_str(process_primary_gid));
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
18f1bbf05980d3c53ecae81b62574212f0891522Timo Sirainen preserve_groups = TRUE;
77f1da4b5e2b800197d8db548235497d5e9d6a4fTimo Sirainen }
75e46142d8fbac811df8f2ca58d9a2f48a75d65fTimo Sirainen
77f1da4b5e2b800197d8db548235497d5e9d6a4fTimo Sirainen /* add extra groups. if we set system user's groups, drop the
18f1bbf05980d3c53ecae81b62574212f0891522Timo Sirainen restricted groups at the same time. */
75e46142d8fbac811df8f2ca58d9a2f48a75d65fTimo Sirainen if (is_root) T_BEGIN {
75e46142d8fbac811df8f2ca58d9a2f48a75d65fTimo Sirainen fix_groups_list(set, preserve_groups,
c5f932968281763df360b9c97cef60f5f80d5e3dTimo Sirainen &have_root_group);
18f1bbf05980d3c53ecae81b62574212f0891522Timo Sirainen } T_END;
18f1bbf05980d3c53ecae81b62574212f0891522Timo Sirainen
18f1bbf05980d3c53ecae81b62574212f0891522Timo Sirainen /* chrooting */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (set->chroot_dir != NULL) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* kludge: localtime() must be called before chroot(),
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen or the timezone isn't known */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen time_t t = 0;
e911b23f3e05308df9b98b1a3fdaf72e4302d8fdTimo Sirainen (void)localtime(&t);
e911b23f3e05308df9b98b1a3fdaf72e4302d8fdTimo Sirainen
e911b23f3e05308df9b98b1a3fdaf72e4302d8fdTimo Sirainen if (chroot(set->chroot_dir) != 0)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen i_fatal("chroot(%s) failed: %m", set->chroot_dir);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen chroot_dir = i_strdup(set->chroot_dir);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (home != NULL) {
e911b23f3e05308df9b98b1a3fdaf72e4302d8fdTimo Sirainen if (chdir(home) < 0) {
e911b23f3e05308df9b98b1a3fdaf72e4302d8fdTimo Sirainen i_error("chdir(%s) failed: %m", home);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen home = NULL;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (home == NULL) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (chdir("/") != 0)
2598b2f36365b52d9754b9348a5be29569293e46Timo Sirainen i_fatal("chdir(/) failed: %m");
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen }
2598b2f36365b52d9754b9348a5be29569293e46Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* uid last */
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen if (set->uid != (uid_t)-1) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (setuid(set->uid) != 0) {
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen i_fatal("setuid(%s) failed with euid=%s: %m "
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen "(This binary should probably be called with "
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen "process user set to %s instead of %s)",
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen get_uid_str(set->uid), get_uid_str(geteuid()),
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen get_uid_str(set->uid), get_uid_str(geteuid()));
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
04b7dc631f33bf61f273138c679da9bd0910fb6dTimo Sirainen /* verify that we actually dropped the privileges */
04b7dc631f33bf61f273138c679da9bd0910fb6dTimo Sirainen if ((set->uid != (uid_t)-1 && set->uid != 0) || disallow_root) {
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen if (setuid(0) == 0) {
04b7dc631f33bf61f273138c679da9bd0910fb6dTimo Sirainen if (disallow_root &&
04b7dc631f33bf61f273138c679da9bd0910fb6dTimo Sirainen (set->uid == 0 || set->uid == (uid_t)-1))
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen i_fatal("This process must not be run as root");
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen i_fatal("We couldn't drop root privileges");
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen }
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen }
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen if (set->first_valid_gid != 0)
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen allow_root_gid = FALSE;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen else if (process_primary_gid == 0 || process_privileged_gid == 0)
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen allow_root_gid = TRUE;
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen else
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen allow_root_gid = FALSE;
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen if (!allow_root_gid && set->uid != 0 &&
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen (set->uid != (uid_t)-1 || !is_root)) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (getgid() == 0 || getegid() == 0 || setgid(0) == 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (process_primary_gid == 0)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen i_fatal("GID 0 isn't permitted");
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen i_fatal("We couldn't drop root group privileges "
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen "(wanted=%s, gid=%s, egid=%s)",
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen get_gid_str(process_primary_gid),
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen get_gid_str(getgid()), get_gid_str(getegid()));
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen}
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenvoid restrict_access_set_env(const struct restrict_access_settings *set)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen{
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (set->system_groups_user != NULL &&
2598b2f36365b52d9754b9348a5be29569293e46Timo Sirainen *set->system_groups_user != '\0') {
2598b2f36365b52d9754b9348a5be29569293e46Timo Sirainen env_put(t_strconcat("RESTRICT_USER=",
e7dd5065d21c569e5e6ddd713bd345dadd1cf51dTimo Sirainen set->system_groups_user, NULL));
e7dd5065d21c569e5e6ddd713bd345dadd1cf51dTimo Sirainen }
e7dd5065d21c569e5e6ddd713bd345dadd1cf51dTimo Sirainen if (set->chroot_dir != NULL && *set->chroot_dir != '\0')
c51644e9e04effbbc9c415cadcfbcb4d9465855cTimo Sirainen env_put(t_strconcat("RESTRICT_CHROOT=", set->chroot_dir, NULL));
c51644e9e04effbbc9c415cadcfbcb4d9465855cTimo Sirainen
c51644e9e04effbbc9c415cadcfbcb4d9465855cTimo Sirainen if (set->uid != (uid_t)-1) {
c51644e9e04effbbc9c415cadcfbcb4d9465855cTimo Sirainen env_put(t_strdup_printf("RESTRICT_SETUID=%s",
c51644e9e04effbbc9c415cadcfbcb4d9465855cTimo Sirainen dec2str(set->uid)));
c51644e9e04effbbc9c415cadcfbcb4d9465855cTimo Sirainen }
c51644e9e04effbbc9c415cadcfbcb4d9465855cTimo Sirainen if (set->gid != (gid_t)-1) {
c51644e9e04effbbc9c415cadcfbcb4d9465855cTimo Sirainen env_put(t_strdup_printf("RESTRICT_SETGID=%s",
c51644e9e04effbbc9c415cadcfbcb4d9465855cTimo Sirainen dec2str(set->gid)));
2598b2f36365b52d9754b9348a5be29569293e46Timo Sirainen }
2598b2f36365b52d9754b9348a5be29569293e46Timo Sirainen if (set->privileged_gid != (gid_t)-1) {
f0d93763f210ecdb85a115fdd0210a16cfc5ff5cTimo Sirainen env_put(t_strdup_printf("RESTRICT_SETGID_PRIV=%s",
f0d93763f210ecdb85a115fdd0210a16cfc5ff5cTimo Sirainen dec2str(set->privileged_gid)));
6303191abcb37164f435ccdc56e9dbddf1288851Timo Sirainen }
2598b2f36365b52d9754b9348a5be29569293e46Timo Sirainen if (set->extra_groups != NULL && *set->extra_groups != '\0') {
2598b2f36365b52d9754b9348a5be29569293e46Timo Sirainen env_put(t_strconcat("RESTRICT_SETEXTRAGROUPS=",
2ef0e8ee48c9683f7bd6698798efa3328e4322d1Timo Sirainen set->extra_groups, NULL));
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (set->first_valid_gid != 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen env_put(t_strdup_printf("RESTRICT_GID_FIRST=%s",
1093de32efb2a231949566d4bd8aa55a8f43fb70Timo Sirainen dec2str(set->first_valid_gid)));
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (set->last_valid_gid != 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen env_put(t_strdup_printf("RESTRICT_GID_LAST=%s",
ab281fc992907b6cf6c730f672dc3aa4c6685015Timo Sirainen dec2str(set->last_valid_gid)));
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen }
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen}
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic const char *null_if_empty(const char *str)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen{
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return str == NULL || *str == '\0' ? NULL : str;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen}
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainenvoid restrict_access_by_env(const char *home, bool disallow_root)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen{
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen struct restrict_access_settings set;
280503e88a6b2f72a32a8fbe363794abaaa845d6Timo Sirainen const char *value;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen
280503e88a6b2f72a32a8fbe363794abaaa845d6Timo Sirainen restrict_access_init(&set);
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen if ((value = getenv("RESTRICT_SETUID")) != NULL)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen set.uid = (uid_t)strtol(value, NULL, 10);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if ((value = getenv("RESTRICT_SETGID")) != NULL)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen set.gid = (gid_t)strtol(value, NULL, 10);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if ((value = getenv("RESTRICT_SETGID_PRIV")) != NULL)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen set.privileged_gid = (gid_t)strtol(value, NULL, 10);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if ((value = getenv("RESTRICT_GID_FIRST")) != NULL)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen set.first_valid_gid = (gid_t)strtol(value, NULL, 10);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if ((value = getenv("RESTRICT_GID_LAST")) != NULL)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen set.last_valid_gid = (gid_t)strtol(value, NULL, 10);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen set.extra_groups = null_if_empty(getenv("RESTRICT_SETEXTRAGROUPS"));
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen set.system_groups_user = null_if_empty(getenv("RESTRICT_USER"));
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen set.chroot_dir = null_if_empty(getenv("RESTRICT_CHROOT"));
660b99a7059824676b2b8d6f79b8e15d47df25a2Timo Sirainen
42fcc708268a89aa9640693e71d13a2bb76e19c8Timo Sirainen restrict_access(&set, home, disallow_root);
42fcc708268a89aa9640693e71d13a2bb76e19c8Timo Sirainen
42fcc708268a89aa9640693e71d13a2bb76e19c8Timo Sirainen /* clear the environment, so we don't fail if we get back here */
42fcc708268a89aa9640693e71d13a2bb76e19c8Timo Sirainen env_remove("RESTRICT_SETUID");
42fcc708268a89aa9640693e71d13a2bb76e19c8Timo Sirainen if (process_privileged_gid == (gid_t)-1) {
42fcc708268a89aa9640693e71d13a2bb76e19c8Timo Sirainen /* if we're dropping privileges before executing and
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen a privileged group is set, the groups must be fixed
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen after exec */
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen env_remove("RESTRICT_SETGID");
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen env_remove("RESTRICT_SETGID_PRIV");
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen }
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen env_remove("RESTRICT_GID_FIRST");
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen env_remove("RESTRICT_GID_LAST");
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen env_remove("RESTRICT_SETEXTRAGROUPS");
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen env_remove("RESTRICT_USER");
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen env_remove("RESTRICT_CHROOT");
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen}
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainenconst char *restrict_access_get_current_chroot(void)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen{
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen return chroot_dir;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen}
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainenvoid restrict_access_allow_coredumps(bool allow ATTR_UNUSED)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen{
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen#ifdef HAVE_PR_SET_DUMPABLE
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen (void)prctl(PR_SET_DUMPABLE, allow, 0, 0, 0);
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen#endif
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen}
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainenint restrict_access_use_priv_gid(void)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen{
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen i_assert(!process_using_priv_gid);
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen if (process_privileged_gid == (gid_t)-1)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen return 0;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen if (setegid(process_privileged_gid) < 0) {
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen i_error("setegid(privileged) failed: %m");
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen return -1;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen }
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen process_using_priv_gid = TRUE;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen return 0;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen}
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainenvoid restrict_access_drop_priv_gid(void)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen{
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen if (!process_using_priv_gid)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen return;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen if (setegid(process_primary_gid) < 0)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen i_fatal("setegid(primary) failed: %m");
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen process_using_priv_gid = FALSE;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen}
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainenbool restrict_access_have_priv_gid(void)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen{
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen return process_privileged_gid != (gid_t)-1;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen}
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen