diff options
-rw-r--r-- | utils/frobauth-mod.c | 177 | ||||
-rw-r--r-- | utils/frobauth.c | 282 | ||||
-rw-r--r-- | utils/frobauth.h | 68 | ||||
-rw-r--r-- | utils/nonsugid.c | 60 | ||||
-rw-r--r-- | utils/pids.c | 232 | ||||
-rw-r--r-- | utils/pids.h | 47 | ||||
-rw-r--r-- | utils/rmauth.c | 121 | ||||
-rw-r--r-- | utils/setauth.c | 132 | ||||
-rw-r--r-- | utils/unsu.c | 90 |
9 files changed, 1209 insertions, 0 deletions
diff --git a/utils/frobauth-mod.c b/utils/frobauth-mod.c new file mode 100644 index 00000000..8606e783 --- /dev/null +++ b/utils/frobauth-mod.c @@ -0,0 +1,177 @@ +/* Modify the current authentication selected processes + + Copyright (C) 1997 Free Software Foundation, Inc. + + Written by Miles Bader <miles@gnu.ai.mit.edu> + + 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 <stdlib.h> +#include <stdio.h> +#include <unistd.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. 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; +} diff --git a/utils/frobauth.c b/utils/frobauth.c new file mode 100644 index 00000000..ccb7c3bb --- /dev/null +++ b/utils/frobauth.c @@ -0,0 +1,282 @@ +/* Common interface for auth frobbing utilities + + Copyright (C) 1997 Free Software Foundation, Inc. + + Written by Miles Bader <miles@gnu.ai.mit.edu> + + 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. */ + +/* This file is rather a mess of intertwined argps; it shoud be redone as a + single level once argp can handle dynamic option frobbing. XXX */ + +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <hurd.h> +#include <hurd/process.h> + +#include "frobauth.h" +#include "ugids.h" +#include "pids.h" + +static struct argp common_argp; +static struct argp fr_ugids_argp; + +static const struct argp_option common_options[] = +{ + {"verbose", 'v', 0, 0, "Print informational messages"}, + {"dry-run", 'n', 0, 0, "Don't do anything, just print what would be done"}, + { 0 } +}; +static struct argp_child common_child_argps[] = +{ + { &pids_argp, 0, "Process selection:" }, + { 0 } +}; + +static const char common_args_doc[] = "USER..."; +static const char common_doc[] = + "\vBy default, all processes in the current login collection are selected"; + +static struct argp_child ugids_child_argps[] = +{ + { &ugids_argp, 0, "User/group ids:" }, + { 0 } +}; + +/* An argp on top of the base frobauth argp that provides switchable + effective/available ids (XXX this junk should be moved into a single argp + [indeed, into ugids_argp] once argp can deal with the init routine + frobbing the argp source). */ +static const struct argp_option ea_options[] = +{ + {"available", 'a', 0, 0, "USER... specifies available ids"}, + {"effective", 'e', 0, 0, "USER... specifies effective ids"}, + { 0 } +}; + +static struct argp_child ea_posix_child_argps[] = +{ + { &common_argp }, + { &fr_ugids_argp }, + { 0 } +}; + +static struct argp_child no_ugids_child_argps[] = +{ + { &common_argp }, + { 0 } +}; + +/* This holds state information that's only active during parsing. */ +struct frobauth_argp_state +{ + struct frobauth *frobauth; + struct pids_argp_params pids_argp_params; + struct ugids_argp_params ugids_argp_params; +}; + +static error_t +common_parse_opt (int key, char *arg, struct argp_state *state) +{ + struct frobauth_argp_state *fs = state->input; + struct frobauth *frobauth = fs->frobauth; + + switch (key) + { + case 'v': + frobauth->verbose = 1; break; + case 'n': + frobauth->dry_run = 1; break; + + case ARGP_KEY_END: + if (frobauth->num_pids == 0) + /* No pids specified! By default, do the current login collection. */ + { + pid_t lid; + error_t err = proc_getloginid (getproc (), getpid (), &lid); + + if (err) + argp_failure (state, 2, err, + "Couldn't get current login collection"); + + err = add_fn_pids (&frobauth->pids, &frobauth->num_pids, + lid, proc_getloginpids); + if (err) + argp_failure (state, 3, err, + "%d: Couldn't get login collection pids", lid); + + return err; + } + break; + + case ARGP_KEY_INIT: + bzero (fs, sizeof *fs); + fs->frobauth = frobauth; + fs->pids_argp_params.pids = &frobauth->pids; + fs->pids_argp_params.num_pids = &frobauth->num_pids; + state->child_inputs[0] = &fs->pids_argp_params; + break; + + case ARGP_KEY_SUCCESS: + case ARGP_KEY_ERROR: + free (fs); + + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +static error_t +ugids_parse_opt (int key, char *arg, struct argp_state *state) +{ + struct frobauth_argp_state *fs = state->input; + struct frobauth *frobauth = fs->frobauth; + + switch (key) + { + case ARGP_KEY_INIT: + fs->ugids_argp_params.ugids = &frobauth->ugids; + fs->ugids_argp_params.parse_user_args = 1; + fs->ugids_argp_params.default_user = frobauth->default_user; + fs->ugids_argp_params.require_ids = frobauth->require_ids; + fs->pids_argp_params.pids = &frobauth->pids; + fs->pids_argp_params.num_pids = &frobauth->num_pids; + + state->child_inputs[0] = &fs->ugids_argp_params; + + break; + + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +static error_t +ea_parse_opt (int key, char *arg, struct argp_state *state) +{ + struct frobauth_argp_state *fs = state->hook; + + switch (key) + { + case 'a': + fs->ugids_argp_params.user_args_are_available = 1; + break; + case 'e': + fs->ugids_argp_params.user_args_are_effective = 1; + break; + + case ARGP_KEY_ARG: + if (!fs->ugids_argp_params.user_args_are_effective + && !fs->ugids_argp_params.user_args_are_available) + /* Default to effective. */ + fs->ugids_argp_params.user_args_are_effective = 1; + + /* Let someone else parse the arg. */ + return ARGP_ERR_UNKNOWN; + + case ARGP_KEY_INIT: + /* Initialize inputs for child parsers. */ + fs = state->hook = malloc (sizeof (struct frobauth_argp_state)); + if (! fs) + return ENOMEM; + + fs->frobauth = state->input; + state->child_inputs[0] = fs; /* Pass our state to the common parser. */ + state->child_inputs[1] = fs; /* Pass our state to the common parser. */ + break; + + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +static error_t +posix_parse_opt (int key, char *arg, struct argp_state *state) +{ + struct frobauth_argp_state *fs = state->hook; + + switch (key) + { + case ARGP_KEY_INIT: + /* Initialize inputs for child parsers. */ + fs = state->hook = malloc (sizeof (struct frobauth_argp_state)); + if (! fs) + return ENOMEM; + + fs->frobauth = state->input; + state->child_inputs[0] = fs; /* Pass our state to the common parser. */ + state->child_inputs[1] = fs; /* Pass our state to the common parser. */ + break; + + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +static error_t +no_ugids_parse_opt (int key, char *arg, struct argp_state *state) +{ + struct frobauth_argp_state *fs = state->hook; + + switch (key) + { + case ARGP_KEY_INIT: + /* Initialize inputs for child parsers. */ + fs = state->hook = malloc (sizeof (struct frobauth_argp_state)); + if (! fs) + return ENOMEM; + + fs->frobauth = state->input; + state->child_inputs[0] = fs; /* Pass our state to the common parser. */ + break; + + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +static struct argp common_argp = +{ + common_options, common_parse_opt, 0, common_doc, common_child_argps +}; +static struct argp fr_ugids_argp = +{ + 0, ugids_parse_opt, 0, 0, ugids_child_argps +}; + +/* Parse frobauth args/options, where user args are added as single ids to + either the effective or available ids. */ +struct argp frobauth_ea_argp = +{ + ea_options, ea_parse_opt, 0, 0, ea_posix_child_argps +}; + +/* Parse frobauth args/options, where user args are added as posix user. */ +struct argp frobauth_posix_argp = +{ + 0, posix_parse_opt, 0, 0, ea_posix_child_argps +}; + +/* Parse frobauth args/options, where user args are added as posix user. */ +struct argp frobauth_no_ugids_argp = +{ + 0, no_ugids_parse_opt, 0, 0, no_ugids_child_argps +}; diff --git a/utils/frobauth.h b/utils/frobauth.h new file mode 100644 index 00000000..0423337e --- /dev/null +++ b/utils/frobauth.h @@ -0,0 +1,68 @@ +/* Common interface for auth frobbing utilities + + Copyright (C) 1997 Free Software Foundation, Inc. + + Written by Miles Bader <miles@gnu.ai.mit.edu> + + 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. */ + +#ifndef __FROBAUTH_H__ +#define __FROBAUTH_H__ + +#include <sys/types.h> +#include <ugids.h> +#include <argp.h> + +/* Structure describing which processes to frob, and how to frob them. */ +struct frobauth +{ + struct ugids ugids; + pid_t *pids; + size_t num_pids; + int verbose, dry_run; /* User options */ + uid_t default_user; /* If none specified; -1 means none. */ + int require_ids; /* If true, require some ids be specified. */ +}; + +#define FROBAUTH_INIT { UGIDS_INIT, 0, 0, 0, 0, -1 } + +/* 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); + +/* Parse frobauth args/options, where user args are added as single ids to + either the effective or available ids. */ +extern struct argp frobauth_ea_argp; + +/* Parse frobauth args/options, where user args are added as posix user. */ +extern struct argp frobauth_posix_argp; + +/* Parse frobauth args/options, with no user specifications. */ +extern struct argp frobauth_no_ugids_argp; + +#endif /* __FROBAUTH_H__ */ diff --git a/utils/nonsugid.c b/utils/nonsugid.c new file mode 100644 index 00000000..ad3a2176 --- /dev/null +++ b/utils/nonsugid.c @@ -0,0 +1,60 @@ +/* Get our ids, minus any setuid result + + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + + Written by Miles Bader <miles@gnu.ai.mit.edu> + + 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 <errno.h> +#include <idvec.h> +#include <hurd.h> + +/* Make sure that the [UG]IDS are filled in. To make them useful for + su'ing, each is the avail ids with all effective ids but the first + appended; this gets rid of the effect of being suid, and is useful as a + new process's avail id list (e.g., the real id is right). */ +error_t +get_nonsugid_ids (struct idvec *uids, struct idvec *gids) +{ + if (uids->num == 0 && gids->num == 0) + { + error_t err = 0; + static auth_t auth = MACH_PORT_NULL; + struct idvec *p_eff_uids = make_idvec (); + struct idvec *p_eff_gids = make_idvec (); + + if (!p_eff_uids || !p_eff_gids) + err = ENOMEM; + + if (auth == MACH_PORT_NULL) + auth = getauth (); + + if (! err) + err = idvec_merge_auth (p_eff_uids, uids, p_eff_gids, gids, auth); + if (! err) + { + idvec_delete (p_eff_uids, 0); /* Counteract setuid. */ + idvec_delete (p_eff_gids, 0); + err = idvec_merge (uids, p_eff_uids); + if (! err) + err = idvec_merge (gids, p_eff_gids); + } + + return err; + } + else + return 0; +} diff --git a/utils/pids.c b/utils/pids.c new file mode 100644 index 00000000..ea759247 --- /dev/null +++ b/utils/pids.c @@ -0,0 +1,232 @@ +/* Pid parsing/frobbing + + Copyright (C) 1997 Free Software Foundation, Inc. + + Written by Miles Bader <miles@gnu.ai.mit.edu> + + 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 <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <argp.h> +#include <hurd.h> +#include <hurd/process.h> +#include <mach.h> + +#include "parse.h" +#include "pids.h" + +static process_t _proc_server = MACH_PORT_NULL; + +/* Return this process's proc server. */ +static inline process_t +proc_server () +{ + if (_proc_server == MACH_PORT_NULL) + _proc_server = getproc (); + return _proc_server; +} + +/* Add the pids returned in vm_allocated memory by calling PIDS_FN with ID as + an argument to PIDS and NUM_PIDS, reallocating it in malloced memory. */ +error_t +add_fn_pids (pid_t **pids, size_t *num_pids, unsigned id, + error_t (*pids_fn)(process_t proc, pid_t id, + pid_t **pids, unsigned *num_pids)) +{ + size_t num_new_pids = 25; + pid_t _new_pids[num_new_pids], *new_pids = _new_pids; + error_t err = (*pids_fn)(proc_server (), id, &new_pids, &num_new_pids); + + if (! err) + { + size_t new_sz = *num_pids + num_new_pids; + pid_t *new = realloc (*pids, new_sz * sizeof (pid_t)); + if (new) + { + bcopy (new_pids, new + (*num_pids * sizeof (pid_t)), + num_new_pids * sizeof (pid_t)); + *pids = new; + *num_pids = new_sz; + } + else + err = ENOMEM; + if (new_pids != _new_pids) + vm_deallocate (mach_task_self (), (vm_address_t)new_pids, + num_new_pids * sizeof (pid_t)); + } + + return err; +} + +/* Add PID to PIDS and NUM_PIDS, reallocating it in malloced memory. */ +error_t +add_pid (pid_t **pids, size_t *num_pids, pid_t pid) +{ + size_t new_sz = *num_pids + 1; + pid_t *new = realloc (*pids, new_sz * sizeof (pid_t)); + + if (new) + { + new[new_sz - 1] = pid; + *pids = new; + *num_pids = new_sz; + return 0; + } + else + return ENOMEM; +} + +struct pids_parse_state +{ + struct pids_argp_params *params; + struct argp_state *state; +}; + +/* Returns our session id. */ +static pid_t +current_sid (struct argp_state *state) +{ + pid_t sid = -1; + error_t err = proc_getsid (proc_server (), getpid (), &sid); + if (err) + argp_failure (state, 2, err, "Couldn't get current session id"); + return sid; +} + +/* Returns our login collection id. */ +static pid_t +current_lid (struct argp_state *state) +{ + pid_t lid = -1; + error_t err = proc_getloginid (proc_server (), getpid (), &lid); + if (err) + argp_failure (state, 2, err, "Couldn't get current login collection"); + return lid; +} + +/* Add a specific process to be printed out. */ +static error_t +parse_pid (unsigned pid, struct argp_state *state) +{ + struct pids_argp_params *params = state->input; + error_t err = add_pid (params->pids, params->num_pids, pid); + if (err) + argp_failure (state, 2, err, "%d: Cannot add process", pid); + return err; +} + +/* Print out all process from the given session. */ +static error_t +parse_sid (unsigned sid, struct argp_state *state) +{ + struct pids_argp_params *params = state->input; + error_t err = + add_fn_pids (params->pids, params->num_pids, sid, proc_getsessionpids); + if (err) + argp_failure (state, 2, err, "%d: Cannot add session", sid); + return err; +} + +/* Print out all process from the given login collection. */ +static error_t +parse_lid (unsigned lid, struct argp_state *state) +{ + struct pids_argp_params *params = state->input; + error_t err = + add_fn_pids (params->pids, params->num_pids, lid, proc_getloginpids); + if (err) + argp_failure (state, 2, err, "%d: Cannot add login collection", lid); + return err; +} + +/* Print out all process from the given process group. */ +static error_t +parse_pgrp (unsigned pgrp, struct argp_state *state) +{ + struct pids_argp_params *params = state->input; + error_t err = + add_fn_pids (params->pids, params->num_pids, pgrp, proc_getpgrppids); + if (err) + argp_failure (state, 2, err, "%d: Cannot add process group", pgrp); + return err; +} + +#define OA OPTION_ARG_OPTIONAL + +/* Options for PIDS_ARGP. */ +static const struct argp_option options[] = +{ + {"login", 'L', "LID", OA, "Processes from the login" + " collection LID (which defaults that of" + " the current process)"}, + {"lid", 0, 0, OPTION_ALIAS | OPTION_HIDDEN}, + {"pid", 'p', "PID", 0, "The process PID"}, + {"pgrp", 'P', "PGRP", 0, "Processes in process group PGRP"}, + {"session", 'S', "SID", OA, "Processes from the session SID" + " (which defaults to that of the" + " current process)"}, + {"sid", 0, 0, OPTION_ALIAS | OPTION_HIDDEN}, + {0, 0} +}; + +/* Parse one option/arg for PIDS_ARGP. */ +static error_t +parse_opt (int key, char *arg, struct argp_state *state) +{ + struct pids_argp_params *params = state->input; + + switch (key) + { + case 'p': + return + parse_numlist (arg, parse_pid, NULL, NULL, "process id", state); + case 'S': + return + parse_numlist (arg, parse_sid, current_sid, NULL, "session id", state); + case 'L': + return + parse_numlist (arg, parse_lid, current_lid, NULL, "login collection", + state); + case 'P': + return + parse_numlist (arg, parse_pgrp, NULL, NULL, "process group", state); + + case ARGP_KEY_ARG: + if (params->parse_pid_args) + return parse_numlist (arg, parse_pid, NULL, NULL, "process id", state); + /* Else fall through */ + + default: + return ARGP_ERR_UNKNOWN; + } +} + +/* Filtering of help output strings for PIDS_ARGP. */ +static char * +help_filter (int key, const char *text, void *input) +{ + struct pids_argp_params *params = input; + + /* Describe the optional behavior of parsing normal args as pids. */ + if (key == ARGP_KEY_HELP_ARGS_DOC && params->parse_pid_args) + return strdup ("[PID...]"); + + return (char *)text; +} + +/* A parser for selecting a set of pids. */ +struct argp pids_argp = { options, parse_opt, 0, 0, 0, help_filter }; diff --git a/utils/pids.h b/utils/pids.h new file mode 100644 index 00000000..8b192b5a --- /dev/null +++ b/utils/pids.h @@ -0,0 +1,47 @@ +/* Pid parsing/frobbing + + Copyright (C) 1997 Free Software Foundation, Inc. + + Written by Miles Bader <miles@gnu.ai.mit.edu> + + 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. */ + +#ifndef __PIDS_H__ +#define __PIDS_H__ + +/* Add the pids returned in vm_allocated memory by calling PIDS_FN with ID as + an argument to PIDS and NUM_PIDS, reallocating it in malloced memory. */ +extern error_t add_fn_pids (pid_t **pids, size_t *num_pids, unsigned id, + error_t (*pids_fn)(process_t proc, pid_t id, + pid_t **pids, size_t *num_pids)); + +/* Add PID to PIDS and NUM_PIDS, reallocating it in malloced memory. */ +extern error_t add_pid (pid_t **pids, size_t *num_pids, pid_t pid); + +/* Params to be passed as the input when parsing PIDS_ARGP. */ +struct pids_argp_params +{ + /* Array to be extended with parsed pids. */ + pid_t **pids; + size_t *num_pids; + + /* If true, parse non-option arguments as pids. */ + int parse_pid_args; +}; + +/* A parser for selecting a set of pids. */ +extern struct argp pids_argp; + +#endif __PIDS_H__ diff --git a/utils/rmauth.c b/utils/rmauth.c new file mode 100644 index 00000000..56d6a6a4 --- /dev/null +++ b/utils/rmauth.c @@ -0,0 +1,121 @@ +/* Remove authentication from selected processes + + Copyright (C) 1997 Free Software Foundation, Inc. + + Written by Miles Bader <miles@gnu.ai.mit.edu> + + 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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <hurd.h> +#include <argp.h> +#include <error.h> +#include <version.h> + +#include "frobauth.h" + +const char *argp_program_version = STANDARD_HURD_VERSION (rmauth); + +static const struct argp_option options[] = +{ +#ifndef UNSU + {"save", 's', 0, 0, "Save removed effective ids as available ids"}, +#endif + { 0 } +}; + +#ifdef UNSU +static struct argp_child child_argps[] = {{ &frobauth_posix_argp }, { 0 }}; +#else +static struct argp_child child_argps[] = {{ &frobauth_ea_argp }, { 0 }}; +#endif + +static char doc[] = + "Remove user/group ids from the authentication of selected processes"; + +void +main (int argc, char *argv[]) +{ + int save = 0; /* save effective ids */ + struct frobauth frobauth = FROBAUTH_INIT; + error_t parse_opt (int key, char *arg, struct argp_state *state) + { + switch (key) + { + case 's': save = 1; break; + case ARGP_KEY_INIT: + state->child_inputs[0] = state->input; break; + default: + return ARGP_ERR_UNKNOWN; + } + return 0; + } + /* Modify UGIDS, to be what PID's new authentication should be, UGIDS is + what the user specified. */ + error_t modify (struct ugids *ugids, const struct ugids *remove, + pid_t pid, void *hook) + { + error_t err = 0; + struct ugids saved = UGIDS_INIT; + + if (save) + ugids_set (&saved, ugids); + + err = ugids_subtract (ugids, remove); + + if (save) + { + ugids_subtract (&saved, ugids); + ugids_save (&saved); + ugids_merge (ugids, &saved); + } + + return err; + } + void print_info (const struct ugids *new, + const struct ugids *old, + const struct ugids *removed, + pid_t pid, void *hook) + { + char *delta_rep; + struct ugids delta = UGIDS_INIT; + + ugids_set (&delta, old); + ugids_subtract (&delta, new); + + delta_rep = ugids_rep (&delta, 1, 1, 0, 0, 0); + printf ("%d: Removed %s\n", pid, delta_rep); + + free (delta_rep); + ugids_fini (&delta); + } + struct argp argp = { options, parse_opt, 0, doc, child_argps }; + +#ifdef UNSU + frobauth.default_user = 0; +#endif + frobauth.require_ids = 1; + + /* Parse our command line. This shouldn't ever return an error. */ + argp_parse (&argp, argc, argv, 0, 0, &frobauth); + + if (frobauth_modify (&frobauth, modify, print_info, 0)) + exit (0); + else + exit (1); +} diff --git a/utils/setauth.c b/utils/setauth.c new file mode 100644 index 00000000..92b6816a --- /dev/null +++ b/utils/setauth.c @@ -0,0 +1,132 @@ +/* Change the authentication of selected processes + + Copyright (C) 1997 Free Software Foundation, Inc. + + Written by Miles Bader <miles@gnu.ai.mit.edu> + + 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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <hurd.h> +#include <argp.h> +#include <error.h> +#include <version.h> + +#include "frobauth.h" + +const char *argp_program_version = STANDARD_HURD_VERSION (setauth); + +#define OPT_NO_SAVE 1 + +static const struct argp_option options[] = +{ +#ifdef SU + {"no-save", OPT_NO_SAVE, 0, 0, "Don't save removed effective ids as available ids"}, +#else + {"save", 's', 0, 0, "Save removed effective ids as available ids"}, +#endif + {"keep", 'k', 0, 0, "Keep old ids in addition to the new ones"}, + { 0 } +}; + +static struct argp_child child_argps[] = {{ &frobauth_posix_argp }, { 0 }}; + +static char doc[] = + "Change the authentication of selected processes"; + +extern error_t +get_nonsugid_ids (struct idvec *uids, struct idvec *gids); + +void +main (int argc, char *argv[]) +{ + error_t err; + int save = 0, keep = 0; + struct idvec have_uids = IDVEC_INIT, have_gids = IDVEC_INIT; + struct frobauth frobauth = FROBAUTH_INIT; + + error_t parse_opt (int key, char *arg, struct argp_state *state) + { + switch (key) + { + case 's': save = 1; break; + case 'k': keep = 1; break; + case OPT_NO_SAVE: save = 0; break; + case ARGP_KEY_INIT: + state->child_inputs[0] = state->input; break; + default: + return ARGP_ERR_UNKNOWN; + } + return 0; + } + /* Modify UGIDS, to be what PID's new authentication should be, UGIDS is + what the user specified. */ + error_t modify (struct ugids *ugids, const struct ugids *new, + pid_t pid, void *hook) + { + struct ugids old = UGIDS_INIT; + ugids_set (&old, ugids); + + ugids_set (ugids, new); + + if (keep) + ugids_merge (ugids, &old); + if (save) + { + ugids_save (&old); + ugids_merge (ugids, &old); + } + + return 0; + } + void print_info (const struct ugids *new, + const struct ugids *old, + const struct ugids *user, + pid_t pid, void *hook) + { + char *new_rep = ugids_rep (new, 1, 1, 0, 0, 0); + printf ("%d: Changed auth to %s\n", pid, new_rep); + free (new_rep); + } + struct argp argp = { options, parse_opt, 0, doc, child_argps }; + +#ifdef SU + frobauth.default_user = 0; + save = 1; /* Default to saving ids */ +#endif + + /* Parse our command line. This shouldn't ever return an error. */ + argp_parse (&argp, argc, argv, 0, 0, &frobauth); + + /* See what the invoking user is authorized to do. */ + err = get_nonsugid_ids (&have_uids, &have_gids); + if (err) + error (52, err, "Cannot get invoking authentication"); + + /* Check passwords. */ + err = ugids_verify (&frobauth.ugids, &have_uids, &have_gids, 0); + if (err == EINVAL) + error (15, 0, "Invalid password"); + else if (err) + error (16, err, "Cannot verify authentication"); + + if (frobauth_modify (&frobauth, modify, print_info, 0)) + exit (0); + else + exit (1); +} diff --git a/utils/unsu.c b/utils/unsu.c new file mode 100644 index 00000000..4672821b --- /dev/null +++ b/utils/unsu.c @@ -0,0 +1,90 @@ +/* Attempt to undo a previous su + + Copyright (C) 1997 Free Software Foundation, Inc. + + Written by Miles Bader <miles@gnu.ai.mit.edu> + + 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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <hurd.h> +#include <argp.h> +#include <error.h> +#include <version.h> + +#include "frobauth.h" +#include "pids.h" + +const char *argp_program_version = STANDARD_HURD_VERSION (rmauth); + +static struct argp_child child_argps[] = {{ &frobauth_no_ugids_argp }, { 0 }}; + +static char doc[] = + "Attempt to undo a previous su" + "\vThis command is convenient, but will only correctly undo a limited" + " subset of possible su commands. It works by simply deleting all" + " current effective ids and the first two available ids, and then" + " making the first remaining available id the current effective id."; + +void +main (int argc, char *argv[]) +{ + struct frobauth frobauth = FROBAUTH_INIT; + + /* Modify UGIDS, to be what PID's new authentication should be, NOISE is + ignored. */ + error_t modify (struct ugids *ugids, const struct ugids *noise, + pid_t pid, void *hook) + { + error_t err = 0; + + idvec_clear (&ugids->eff_uids); + idvec_clear (&ugids->eff_gids); + idvec_clear (&ugids->imp_eff_gids); + + idvec_delete (&ugids->avail_uids, 0); + idvec_delete (&ugids->avail_uids, 0); + + idvec_delete (&ugids->avail_gids, 0); + idvec_delete (&ugids->avail_gids, 0); + idvec_keep (&ugids->imp_avail_gids, &ugids->avail_gids); + + if (ugids->avail_uids.num > 0) + err = ugids_set_posix_user (ugids, ugids->avail_uids.ids[0]); + + return err; + } + void print_info (const struct ugids *new, + const struct ugids *old, + const struct ugids *removed, + pid_t pid, void *hook) + { + char *new_rep = ugids_rep (new, 1, 1, 0, 0, 0); + printf ("%d: Changed auth to %s\n", pid, new_rep); + free (new_rep); + } + struct argp argp = { 0, 0, 0, doc, child_argps }; + + /* Parse our command line. This shouldn't ever return an error. */ + argp_parse (&argp, argc, argv, 0, 0, &frobauth); + + if (frobauth_modify (&frobauth, modify, print_info, 0)) + exit (0); + else + exit (1); +} |