diff options
Diffstat (limited to 'utils/frobauth-mod.c')
-rw-r--r-- | utils/frobauth-mod.c | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/utils/frobauth-mod.c b/utils/frobauth-mod.c new file mode 100644 index 00000000..06ccdbfa --- /dev/null +++ b/utils/frobauth-mod.c @@ -0,0 +1,160 @@ +/* Modify the current authentication selected processes + + Copyright (C) 1997, 1999 Free Software Foundation, Inc. + Written by Miles Bader <miles@gnu.ai.mit.edu> + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + The GNU Hurd 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <hurd.h> +#include <error.h> + +#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. AUTHS, of length NUM_AUTHS, should be a vector of + auth ports giving whatever additional authentication is needed (besides + the process's current authentication). 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, + const auth_t *auths, size_t num_auths, + 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; + size_t num_all_auths = num_auths + 1; + auth_t all_auths[num_all_auths]; + pid_t cur_pid = getpid (); + process_t proc_server = getproc (); + + bcopy (auths, all_auths, num_auths * sizeof *auths); + + /* 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; + + /* Add the PID's old authentication to that + supplied by the calller. */ + all_auths[num_all_auths - 1] = old_auth; + + err = ugids_make_auth (&new, + all_auths, + num_all_auths, + &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); + } + + } + + 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; +} |