fd_close_on_exec(group->listen_fd, TRUE);
/* set correct permissions */
- if (chown(path, geteuid(), auth_set->parent->defaults->login_gid) < 0) {
+ if (chown(path, master_uid,
+ auth_set->parent->defaults->login_gid) < 0) {
i_fatal("login: chown(%s, %s, %s) failed: %m",
- path, dec2str(geteuid()),
+ path, dec2str(master_uid),
dec2str(auth_set->parent->defaults->login_gid));
}
extern struct ioloop *ioloop;
extern struct hash_table *pids;
extern int null_fd, inetd_login_fd;
+extern uid_t master_uid;
#define IS_INETD() \
(inetd_login_fd != -1)
return FALSE;
}
- if (set->login_uid == uid && geteuid() != uid) {
+ if (set->login_uid == uid && master_uid != uid) {
i_error("Can't log in using login processes UID %s (user %s) "
"(see login_user in config file).",
dec2str(uid), user);
const char *addr, *mail, *chroot_dir, *home_dir, *full_home_dir;
char title[1024];
pid_t pid;
- int i, err;
+ int i, err, ret;
// FIXME: per-group
if (mail_process_count == set->max_mail_processes) {
full_home_dir = *chroot_dir == '\0' ? home_dir :
t_strconcat(chroot_dir, "/", home_dir, NULL);
/* NOTE: if home directory is NFS-mounted, we might not
- have access to it as root. Ignore such errors. */
- if (chdir(full_home_dir) < 0 && errno != EACCES)
- i_fatal("chdir(%s) failed: %m", full_home_dir);
+ have access to it as root. Change the effective UID
+ temporarily to make it work. */
+ if (reply->uid != master_uid && seteuid(reply->uid) < 0)
+ i_fatal("seteuid(%s) failed: %m", dec2str(reply->uid));
+ ret = chdir(full_home_dir);
+ if (reply->uid != master_uid && seteuid(master_uid) < 0)
+ i_fatal("seteuid(%s) failed: %m", dec2str(master_uid));
+ if (ret < 0) {
+ i_fatal("chdir(%s) failed with uid %s: %m",
+ full_home_dir, dec2str(reply->uid));
+ }
+ } else {
+ /* We still have to change to some directory where we have
+ rx-access. /tmp should exist everywhere. */
+ if (chdir("/tmp") < 0)
+ i_fatal("chdir(/tmp) failed: %m");
}
env_put("LOGGED_IN=1");
for (i = 0; i < 3; i++)
(void)close(i);
+ errno = err;
i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m",
group->set->mail_executable);
struct ioloop *ioloop;
struct hash_table *pids;
int null_fd, inetd_login_fd;
+uid_t master_uid;
int validate_str(const char *str, size_t max_len)
{
lib_init();
+ master_uid = geteuid();
inetd_login_fd = -1;
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "-F") == 0) {
/* since they're under /var/run by default, they may have been
deleted. */
- if (safe_mkdir(set->base_dir, 0700, geteuid(), getegid()) == 0) {
+ if (safe_mkdir(set->base_dir, 0700, master_uid, getegid()) == 0) {
i_warning("Corrected permissions for base directory %s",
PKG_RUNDIR);
}
return FALSE;
}
- if (safe_mkdir(set->login_dir, 0750, geteuid(), set->login_gid) == 0) {
+ if (safe_mkdir(set->login_dir, 0750, master_uid, set->login_gid) == 0) {
i_warning("Corrected permissions for login directory %s",
set->login_dir);
}
regen_time = st.st_mtime +
(time_t)(set->ssl_parameters_regenerate*3600);
if (regen_time < ioloop_time || (st.st_mode & 077) != 0 ||
- st.st_uid != geteuid() || st.st_gid != getegid()) {
+ st.st_uid != master_uid || st.st_gid != getegid()) {
start_generate_process(set);
return FALSE;
}