/* Modify the current authentication selected processes Copyright (C) 1997 Free Software Foundation, Inc. Written by Miles Bader This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include "frobauth.h" /* For every pid in FROBAUTH, call MODIFY to change its argument UGIDS from the current authentication to what it should be; CHANGE is whatever ids the user specified. If the user specifies the --verbose flags, PRINT_INFO is called after successfully installing the new authentication in each process, to print a message about what happened. True is returned if no errors occur, although most errors do not cause termination, and error messages are printed for them. */ error_t frobauth_modify (struct frobauth *frobauth, error_t (*modify) (struct ugids *ugids, const struct ugids *change, pid_t pid, void *hook), void (*print_info) (const struct ugids *new, const struct ugids *old, const struct ugids *change, pid_t pid, void *hook), void *hook) { int i; int ok = 1; pid_t cur_pid = getpid (); process_t proc_server = getproc (); /* Map MODIFY over all pids. */ for (i = 0; i < frobauth->num_pids; i++) if (frobauth->pids[i] != cur_pid) { mach_port_t msgport; pid_t pid = frobauth->pids[i]; error_t err = proc_getmsgport (proc_server, pid, &msgport); if (err) error (0, err, "%d: Cannot get message port", pid); else { task_t task; err = proc_pid2task (proc_server, pid, &task); if (err) error (0, err, "%d", pid); else { auth_t old_auth; err = msg_get_init_port (msgport, task, INIT_PORT_AUTH, &old_auth); if (err) error (0, err, "%d: Cannot get auth port", pid); else { struct ugids old = UGIDS_INIT; err = ugids_merge_auth (&old, old_auth); if (err) error (0, err, "%d: Cannot get auth port ids", pid); else { struct ugids new = UGIDS_INIT; /* Assume all gids that can be implied by some uid are only present for that reason. */ ugids_imply_all (&old); err = ugids_set (&new, &old); err = (*modify) (&new, &frobauth->ugids, pid, hook); if (err) error (99, err, "%d: Cannot modify ids", pid); else if (! ugids_equal (&new, &old)) { if (! frobauth->dry_run) { auth_t new_auth; err = ugids_make_auth (&new, old_auth, &new_auth); if (err) error (0, err, "%d: Authentication failure", pid); else { err = msg_set_init_port (msgport, task, INIT_PORT_AUTH, new_auth, MACH_MSG_TYPE_MOVE_SEND); if (err) error (0, err, "%d", pid); else if (new.eff_uids.num == 0 ? old.eff_uids.num > 0 : (old.eff_uids.num == 0 || (new.eff_uids.ids[0] != old.eff_uids.ids[0]))) /* Now change the process's owner. */ { process_t proc; err = proc_pid2proc (proc_server, pid, &proc); if (err) error (0, err, "%d: Cannot get proc port", pid); else { if (new.eff_uids.num == 0) err = proc_setowner (proc, 0, 1); else err = proc_setowner (proc, new.eff_uids.ids[0], 0); if (err) error (0, err, "%d: Cannot set process owner", pid); mach_port_deallocate (mach_task_self (), proc); } } } } if (frobauth->verbose && !err) (*print_info) (&new, &old, &frobauth->ugids, pid, hook); } else if (frobauth->verbose) printf ("%d: Nothing changed\n", pid); ugids_fini (&new); } ugids_fini (&old); mach_port_deallocate (mach_task_self (), old_auth); } mach_port_deallocate (mach_task_self (), task); } mach_port_deallocate (mach_task_self (), msgport); } if (err) ok = 0; /* Something didn't work. */ } return ok; }