Exemplo n.º 1
0
static void
drop_privileges(struct service *service)
{
	struct restrict_access_settings rset;
	bool disallow_root;
	unsigned int len;

	if (service->vsz_limit != 0)
		restrict_process_size(service->vsz_limit);

	restrict_access_init(&rset);
	rset.uid = service->uid;
	rset.gid = service->gid;
	rset.privileged_gid = service->privileged_gid;
	rset.chroot_dir = *service->set->chroot == '\0' ? NULL :
		service->set->chroot;
	if (rset.chroot_dir != NULL) {
		/* drop trailing / if it exists */
		len = strlen(rset.chroot_dir);
		if (rset.chroot_dir[len-1] == '/')
			rset.chroot_dir = t_strndup(rset.chroot_dir, len-1);
	}
	rset.extra_groups = service->extra_gids;

	restrict_access_set_env(&rset);
	if (service->set->drop_priv_before_exec) {
		disallow_root = service->type == SERVICE_TYPE_LOGIN;
		restrict_access(&rset, NULL, disallow_root);
	}
}
Exemplo n.º 2
0
static int
service_drop_privileges(struct mail_storage_service_user *user,
			struct mail_storage_service_privileges *priv,
			bool disallow_root, bool keep_setuid_root,
			bool setenv_only, const char **error_r)
{
	const struct mail_user_settings *set = user->user_set;
	struct restrict_access_settings rset;
	uid_t current_euid, setuid_uid = 0;
	const char *cur_chroot, *error;

	current_euid = geteuid();
	restrict_access_init(&rset);
	restrict_access_get_env(&rset);
	if (priv->uid != (uid_t)-1) {
		rset.uid = priv->uid;
		rset.uid_source = priv->uid_source;
	} else if (rset.uid == (uid_t)-1 &&
		 disallow_root && current_euid == 0) {
		*error_r = "User is missing UID (see mail_uid setting)";
		return -1;
	}
	if (priv->gid != (gid_t)-1) {
		rset.gid = priv->gid;
		rset.gid_source = priv->gid_source;
	} else if (rset.gid == (gid_t)-1 && disallow_root &&
		   set->first_valid_gid > 0 && getegid() == 0) {
		*error_r = "User is missing GID (see mail_gid setting)";
		return -1;
	}
	if (*set->mail_privileged_group != '\0') {
		if (!parse_gid(set->mail_privileged_group, &rset.privileged_gid,
			       &error)) {
			*error_r = t_strdup_printf(
				"%s (in mail_privileged_group setting)", error);
			return -1;
		}
	}
	if (*set->mail_access_groups != '\0') {
		rset.extra_groups = t_strconcat(set->mail_access_groups, ",",
						rset.extra_groups, NULL);
	}

	rset.first_valid_gid = set->first_valid_gid;
	rset.last_valid_gid = set->last_valid_gid;
	rset.chroot_dir = *priv->chroot == '\0' ? NULL : priv->chroot;
	rset.system_groups_user = user->system_groups_user;

	cur_chroot = restrict_access_get_current_chroot();
	if (cur_chroot != NULL) {
		/* we're already chrooted. make sure the chroots are equal. */
		if (rset.chroot_dir == NULL) {
			*error_r = "Process is already chrooted, "
				"can't un-chroot for this user";
			return -1;
		}
		if (strcmp(rset.chroot_dir, cur_chroot) != 0) {
			*error_r = t_strdup_printf(
				"Process is already chrooted to %s, "
				"can't chroot to %s", cur_chroot, priv->chroot);
			return -1;
		}
		/* chrooting to same directory where we're already chrooted */
		rset.chroot_dir = NULL;
	}

	if (disallow_root &&
	    (rset.uid == 0 || (rset.uid == (uid_t)-1 && current_euid == 0))) {
		*error_r = "Mail access not allowed for root";
		return -1;
	}

	if (keep_setuid_root) {
		if (current_euid != rset.uid) {
			if (current_euid != 0) {
				/* we're changing the UID,
				   switch back to root first */
				mail_storage_service_seteuid_root();
			}
			setuid_uid = rset.uid;
		}
		rset.uid = (uid_t)-1;
		disallow_root = FALSE;
	}
	if (!setenv_only) {
		restrict_access(&rset, *priv->home == '\0' ? NULL : priv->home,
				disallow_root);
	} else {
		restrict_access_set_env(&rset);
	}
	if (setuid_uid != 0 && !setenv_only) {
		if (seteuid(setuid_uid) < 0)
			i_fatal("mail-storage-service: seteuid(%s) failed: %m",
				dec2str(setuid_uid));
	}
	return 0;
}